This commit is contained in:
2026-02-13 15:53:22 +01:00
commit 25271189b5
639 changed files with 49083 additions and 0 deletions

View File

@@ -0,0 +1,673 @@
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:hiddingsel_app/appflow/model/location.dart';
import 'package:hiddingsel_app/appflow/view/widgets/gallery.dart';
import 'package:hiddingsel_app/packages/html_view/html_view.dart';
import 'package:hiddingsel_app/constants/constant.dart';
import '../further_pages/article.dart';
import '../../../services/environment.dart';
import '../home.dart';
import '../../model/articles.dart';
import '../../model/companies.dart';
import '../../model/pois.dart';
import '../../model/represented_organisations.dart';
import '../../../packages/icon_switch/icon_switch.dart';
class ItemCard extends StatelessWidget {
final Widget _title;
final ImageProvider? _imageProvider;
final Widget _child;
final Function()? _onShare;
final Function(bool favorite) _onFavorite;
final Future<bool> _initFavorite;
final Function(bool notify) _onNotify;
final Future<bool> _initNotify;
final Gradient _gradientColor;
final bool _right;
ItemCard(this._title, this._imageProvider, this._child, this._onShare,
{onFavorite, initFavorite, onNotify, initNotify, gradientColor, right = true})
: _onFavorite = onFavorite,
_initFavorite = initFavorite ?? Future.value(false),
_onNotify = onNotify,
_initNotify = initNotify ?? Future.value(false),
_gradientColor = gradientColor ??
LinearGradient(
colors: [
UIColors.white,
UIColors.white,
],
),
_right = right;
@override
Widget build(BuildContext context) {
int space = 20;
List<Widget> buttons = [
IconButton(
icon: Icon(Icons.share, color: UIColors.white),
tooltip: 'Share',
onPressed: _onShare,
),
];
buttons.add(Spacer());
/*buttons.add(
IconSwitch(
_onFavorite,
initFavorite: _initFavorite,
gradientColor: _gradientColor,
defaultColor: UIColors.white,
),
);
buttons.add(Spacer());*/
buttons.add(
IconSwitch(
_onNotify,
initFavorite: _initNotify,
gradientColor: _gradientColor,
defaultColor: UIColors.white,
iconFavorite: Icons.notifications_active,
iconDefavorite: Icons.notifications_outlined,
),
);
return LayoutBuilder(
builder: (context, constraints) {
Widget image;
if (_imageProvider != null) {
image = Image(
image: _imageProvider,
fit: BoxFit.cover,
width: constraints.maxWidth - 48 - space,
);
} else {
image = Container(
width: constraints.maxWidth - 48 - space,
child: Center(
child: CircularProgressIndicator(),
),
);
}
RoundedRectangleBorder border;
double paddingLeft = 0;
double paddingRight = 0;
if (_right) {
border = UIShapes.leftRoundedRectangleWithBorder;
paddingLeft = UIShapes.paddingSimple + space / 2;
} else {
border = UIShapes.rightRoundedRectangleWithBorder;
paddingRight = UIShapes.paddingSimple + space / 2;
}
return Container(
margin: EdgeInsets.symmetric(vertical: UIShapes.paddingSimple),
child: Stack(
alignment: Alignment.topRight,
children: [
Positioned.fill(
left: paddingLeft,
right: paddingRight,
child: Container(
decoration: ShapeDecoration(shape: border),
width: constraints.maxWidth - UIShapes.paddingDouble,
),
),
Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.fromLTRB(
_right? UIShapes.paddingMax + UIShapes.paddingDouble : UIShapes.paddingMax,
UIShapes.paddingDouble,
UIShapes.paddingSimple,
UIShapes.paddingSimple),
child: _title,
),
Container(
height: constraints.maxWidth * 0.6,
decoration: BoxDecoration(
color: UIColors.grey5,
),
child: Row(
children: [
Padding(
padding: EdgeInsets.fromLTRB(
0,
UIShapes.paddingSimple,
0,
UIShapes.paddingSimple,
),
child: ClipRRect(
borderRadius: UIShapes.rightRoundedRectangle,
child: image,
),
),
Padding(
padding: EdgeInsets.fromLTRB(
0,
UIShapes.paddingSimple,
0,
UIShapes.paddingSimple,
),
child: Column(children: buttons),
),
VerticalDivider(
color: _right ? Colors.transparent : UIColors.white,
width: 2,
)
],
),
),
Padding(
padding: EdgeInsets.fromLTRB(
UIShapes.paddingMax + paddingLeft,
UIShapes.paddingSimple,
UIShapes.paddingSimple + paddingRight,
UIShapes.paddingDouble),
child: _child,
),
],
),
],
),
);
},
);
}
}
class ItemWithPersonAndText extends StatelessWidget {
final String _title;
final String _assetLogo;
final String _assetPerson;
final String _personName;
final String? _personText;
final InlineSpan _text;
final String? _mail;
final String? _phone;
final Uri? _website;
final LocationModel? _location;
final String? _facebook;
final String? _instagram;
final Function() _onShare;
final Function(bool favorite) _onFavorite;
final Future<bool> _initFavorite;
final Function(bool notify) _onNotify;
final Future<bool> _initNotify;
final Gradient _gradientColor;
ItemWithPersonAndText.fromOrganisation(RepresentedOrganisationModel _organisation)
: _title = _organisation.name,
_assetLogo = _organisation.image.resource,
_assetPerson = _organisation.person.image.resource,
_personName = _organisation.person.name,
_personText = _organisation.person.position,
_mail = _organisation.contact.mail,
_phone = _organisation.contact.phone,
_website = _organisation.contact.website,
_location = _organisation.contact.location,
_facebook = _organisation.contact.facebook,
_instagram = _organisation.contact.instagram,
_text = _organisation.text,
_onShare = shareOrganisation(_organisation),
_onFavorite = _organisation.favorize,
_initFavorite = _organisation.favorized,
_onNotify = _organisation.subscribe,
_initNotify = _organisation.subscribed,
_gradientColor = UIGradiants.yellow;
ItemWithPersonAndText.fromCompany(CompanyModel _company)
: _title = _company.name,
_assetLogo = _company.image.resource,
_assetPerson = _company.person.image.resource,
_personName = _company.person.name,
_personText = _company.person.position,
_text = _company.text,
_mail = _company.contact.mail,
_phone = _company.contact.phone,
_website = _company.contact.website,
_location = _company.contact.location,
_facebook = _company.contact.facebook,
_instagram = _company.contact.instagram,
_onShare = shareCompany(_company),
_onFavorite = doNothing,
_initFavorite = Future(() => false),
_onNotify = _company.subscribe,
_initNotify = _company.subscribed,
_gradientColor = UIGradiants.purple;
static doNothing(s) {}
@override
Widget build(
BuildContext context) {
Text title = Text(
_title,
style: UITheme.theme.textTheme.displaySmall,
);
ImageProvider image = AssetImage(_assetLogo);
List<Widget> iconButtons = [];
if (_mail != null) {
iconButtons.add(
IconButton(
icon: const Icon(
Icons.mail,
color: UIColors.grey5,
),
tooltip: 'Mail',
onPressed: () {
EnvironmentConnector.openMail(_mail);
},
),
);
}
if (_phone != null) {
iconButtons.add(
IconButton(
icon: const Icon(
Icons.phone,
color: UIColors.grey5,
),
tooltip: 'Phone',
onPressed: () {
EnvironmentConnector.openPhone(_phone);
},
),
);
}
if (_website != null) {
iconButtons.add(
IconButton(
icon: const Icon(
Icons.web,
color: UIColors.grey5,
),
tooltip: 'Website',
onPressed: () {
EnvironmentConnector.openBrowser(_website);
},
),
);
}
if (_location != null) {
iconButtons.add(
IconButton(
icon: const Icon(
Icons.place,
color: UIColors.grey5,
),
tooltip: 'Location',
onPressed: () {EnvironmentConnector.openMaps(_location);},
),
);
}
if (_facebook != null) {
iconButtons.add(
IconButton(
icon: const Icon(
Icons.facebook,
color: UIColors.grey5,
),
tooltip: 'Facebook',
onPressed: () {EnvironmentConnector.openFacebook(_facebook);},
),
);
}
if (_instagram != null) {
iconButtons.add(
IconButton(
icon: const Icon(
FontAwesomeIcons.instagram,
color: UIColors.grey5,
),
tooltip: 'Instagram',
onPressed: () {EnvironmentConnector.openInstagram(_instagram);},
),
);
}
Widget child = Column(
crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.alphabetic,
children: [
Row(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(UIShapes.paddingDouble),
child: Image(
image: AssetImage(_assetPerson),
fit: BoxFit.cover,
width: 100,
height: 100,
),
),
VerticalDivider(width: UIShapes.paddingSimple),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
_personName,
style: UITheme.theme.textTheme.displaySmall,
),
Text(
_personText??'',
style: UITheme.theme.textTheme.bodyLarge,
),
],
),
),
Column(
children: iconButtons,
),
],
),
RichText(text: _text,),
],
);
return ItemCard(
title,
image,
child,
_onShare,
onFavorite: _onFavorite,
initFavorite: _initFavorite,
onNotify: _onNotify,
initNotify: _initNotify,
gradientColor: _gradientColor,
);
}
}
class ItemWithText extends StatelessWidget {
final String _title;
final String _assetTitle;
final String? _subtitle;
final String _text;
final Function() _onShare;
final Function()? _onFavorite;
final Function()? _onNotify;
ItemWithText.fromPoi(PointOfInterestModel _poi)
: _title = _poi.name,
_assetTitle = _poi.image.resource,
_subtitle = _poi.subtitle,
_text = _poi.text,
_onShare = sharePoi(_poi),
_onFavorite = null,
_onNotify = null;
@override
Widget build(BuildContext context) {
Text title = Text(
_title,
style: UITheme.theme.textTheme.headlineSmall,
);
ImageProvider image = AssetImage(_assetTitle);
Column child = Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
_subtitle ?? '',
style: UITheme.theme.textTheme.displaySmall,
),
Text(
_text,
style: UITheme.theme.textTheme.bodyLarge,
),
],
);
return ItemCard(
title,
image,
child,
_onShare,
onFavorite: _onFavorite,
onNotify: _onNotify,
);
}
}
class ItemWithTitle extends StatelessWidget {
final ArticleModel _article;
final String _title;
final String? _thumbnailPictureUrl;
final String _subtitle;
final Function()? _onShare;
final Function(bool favorite)? _onFavorite;
final Future<bool>? _initFavorite;
final Function(bool notify)? _onNotify;
final Future<bool>? _initNotify;
final bool _right;
final Function(PreferredSizeWidget appBar, Widget body)? _onChange;
ItemWithTitle.fromNull()
: _title = '',
_thumbnailPictureUrl = null,
_subtitle = '',
_onShare = null,
_onFavorite = null,
_initFavorite = null,
_onNotify = null,
_initNotify = null,
_right = false,
_onChange = null,
_article = ArticleModel(-1, '', '', DateTime.now(), '', Uri());
ItemWithTitle.fromArticle(this._article, this._onChange)
: _title =
'${_article.publishedAt.year}-${_article.publishedAt.month}-${_article.publishedAt.day}',
_thumbnailPictureUrl = _article.image.resource,
_subtitle = _article.title,
_onShare = shareArticle(_article),
_onFavorite = favorizeAll(_article.categories),
_initFavorite = allFavorized(_article.categories),
_onNotify = subscribeAll(_article.categories),
_initNotify = allSubscribed(_article.categories),
_right = false;
static favorizeAll(List<RepresentedOrganisationModel> list) {
return (fav) => list.forEach((e) => e.favorize(fav));
}
static Future<bool> allFavorized(List<RepresentedOrganisationModel> list) async {
bool favorized = false;
for(RepresentedOrganisationModel e in list) {
favorized = favorized || await e.favorized;
}
return favorized;
}
static subscribeAll(List<RepresentedOrganisationModel> list) {
return (sub) => list.forEach((e) => e.subscribe(sub));
}
static Future<bool> allSubscribed(List<RepresentedOrganisationModel> list) async {
bool subscribed = false;
for(RepresentedOrganisationModel e in list) {
subscribed = subscribed || await e.subscribed;
}
return subscribed;
}
@override
Widget build(BuildContext context) {
Text title = Text(
_title,
style: UITheme.theme.textTheme.headlineSmall,
);
ImageProvider? image = _thumbnailPictureUrl != null ? CachedNetworkImageProvider(_thumbnailPictureUrl) : null;
Widget child = Row(
children: [
Expanded(
child: Text(
_subtitle,
style: UITheme.theme.textTheme.displaySmall,
),
),
Icon(
Icons.arrow_forward_ios,
color: UIColors.grey4,
),
],
);
var onTap;
if (_article.id != -1) {
onTap = () {
Home.openPage(ArticleView(_article), _onChange);
};
}
return GestureDetector(
child: ItemCard(
title,
image,
child,
_onShare,
onFavorite: _onFavorite,
initFavorite: _initFavorite,
onNotify: _onNotify,
initNotify: _initNotify,
right: _right,
gradientColor: UIGradiants.yellow,
),
onTap: onTap,
);
}
}
class ItemWithWebView extends StatelessWidget {
final ArticleModel _article;
final String _title;
final String _thumbnailPictureUrl;
final String _subtitle;
final Function() _onShare;
final Function(bool favorite) _onFavorite;
final Future<bool> _initFavorite;
final Function(bool notify) _onNotify;
final Future<bool> _initNotify;
final bool _right;
ItemWithWebView.fromArticle(this._article)
: _title =
'${_article.publishedAt.year}-${_article.publishedAt.month}-${_article.publishedAt.day}',
_thumbnailPictureUrl = _article.image.resource,
_subtitle = _article.title,
_onShare = shareArticle(_article),
_onFavorite = favorizeAll(_article.categories),
_initFavorite = allFavorized(_article.categories),
_onNotify = subscribeAll(_article.categories),
_initNotify = allSubscribed(_article.categories),
_right = true;
static favorizeAll(List<RepresentedOrganisationModel> list) {
return (fav) => list.forEach((e) => e.favorize(fav));
}
static Future<bool> allFavorized(List<RepresentedOrganisationModel> list) async {
bool favorized = false;
for(RepresentedOrganisationModel e in list) {
favorized = favorized || await e.favorized;
}
return favorized;
}
static subscribeAll(List<RepresentedOrganisationModel> list) {
return (sub) => list.forEach((e) => e.subscribe(sub));
}
static Future<bool> allSubscribed(List<RepresentedOrganisationModel> list) async {
bool subscribed = false;
for(RepresentedOrganisationModel e in list) {
subscribed = subscribed || await e.subscribed;
}
return subscribed;
}
@override
Widget build(BuildContext context) {
Text title = Text(
_title,
style: UITheme.theme.textTheme.headlineSmall,
);
ImageProvider image = CachedNetworkImageProvider(_thumbnailPictureUrl);
Widget child = Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
_subtitle,
style: UITheme.theme.textTheme.displaySmall,
textAlign: TextAlign.left,
),
HtmlView(
_article.content,
),
],
);
SizedBox otherImages = SizedBox(
height: 200,
child: HiddingselGallery(_article.otherImages.map((e) => e.image).toList()),
);
return ListView(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
children: [
ItemCard(
title,
image,
child,
_onShare,
onFavorite: _onFavorite,
initFavorite: _initFavorite,
onNotify: _onNotify,
initNotify: _initNotify,
right: _right,
gradientColor: UIGradiants.yellow,
),
otherImages
],
);
}
}
Function() sharePoi(PointOfInterestModel poi) => () {
EnvironmentConnector.share(
'Ich habe eine interessante Sehenswürdigkeit auf hiddingsel.de gefunden:\n${poi.name}');
};
Function() shareOrganisation(RepresentedOrganisationModel organisation) => () {
EnvironmentConnector.share(
'Ich habe einen interessanten Verein auf hiddingsel.de gefunden:\n${organisation.name}');
};
Function() shareCompany(CompanyModel company) => () {
String text = 'Ich habe ein interessantes Unternehmen auf hiddingsel.de gefunden:\n${company.name}';
if(company.contact.mail != null) {
text = text + '\nE-Mail: ${company.contact.mail}';
}
if(company.contact.phone != null) {
text = text + '\nTelefon: ${company.contact.phone}';
}
if(company.contact.website != null) {
text = text + '\nWebseite: ${company.contact.website}';
}
if(company.contact.instagram != null) {
text = text + '\nInstagram: ${company.contact.instagram}';
}
if(company.contact.facebook != null) {
text = text + '\nFacebook: ${company.contact.facebook}';
}
if(company.contact.twitter != null) {
text = text + '\nTwitter: ${company.contact.twitter}';
}
if(company.contact.location?.address != null) {
text = text + '\nAdresse: ${company.contact.location?.address}';
}
EnvironmentConnector.share(text);
};
Function() shareArticle(ArticleModel article) => () {
EnvironmentConnector.share(
'Ich habe einen interessanten Artikel auf hiddingsel.de gefunden:\n${article.url}');
};