674 lines
20 KiB
Dart
674 lines
20 KiB
Dart
|
|
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}');
|
|
};
|