diff --git a/lib/screens/metering/components/shared/readings_container/components/lightmeter_pro/widget_lightmeter_pro.dart b/lib/screens/metering/components/shared/readings_container/components/lightmeter_pro/widget_lightmeter_pro.dart index 5360f41..1a5e10d 100644 --- a/lib/screens/metering/components/shared/readings_container/components/lightmeter_pro/widget_lightmeter_pro.dart +++ b/lib/screens/metering/components/shared/readings_container/components/lightmeter_pro/widget_lightmeter_pro.dart @@ -18,11 +18,8 @@ class _LightmeterProAnimatedDialogState extends State? maybeClose(BuildContext context) => + context.findAncestorWidgetOfExactType<_AnimatedOverlay>()?.onDismiss(); + @override State createState() => AnimatedDialogState(); } @@ -147,9 +150,9 @@ class AnimatedDialogState extends State with SingleTickerProvide _sizeTween = SizeTween( begin: _closedSize, end: Size( - min(widget.openedSize?.width ?? double.maxFinite, maxWidth), - min(widget.openedSize?.height ?? double.maxFinite, maxHeight), - ), + min(widget.openedSize?.width ?? double.maxFinite, maxWidth), + min(widget.openedSize?.height ?? double.maxFinite, maxHeight), + ), ); _sizeAnimation = _sizeTween.animate(_defaultCurvedAnimation); @@ -230,7 +233,7 @@ class _AnimatedOverlay extends StatelessWidget { final Animation borderRadiusAnimation; final Animation foregroundColorAnimation; final Animation elevationAnimation; - final VoidCallback onDismiss; + final Future Function() onDismiss; final Widget? child; final Widget Function(BuildContext context)? builder; diff --git a/lib/screens/settings/utils/show_buy_pro_dialog.dart b/lib/screens/settings/utils/show_buy_pro_dialog.dart index 181259f..93e5ed7 100644 --- a/lib/screens/settings/utils/show_buy_pro_dialog.dart +++ b/lib/screens/settings/utils/show_buy_pro_dialog.dart @@ -1,59 +1,53 @@ import 'package:flutter/material.dart'; -import 'package:lightmeter/data/models/feature.dart'; import 'package:lightmeter/generated/l10n.dart'; -import 'package:lightmeter/providers/remote_config_provider.dart'; import 'package:lightmeter/res/dimens.dart'; +import 'package:lightmeter/screens/metering/components/shared/readings_container/components/shared/animated_dialog_picker/components/animated_dialog/widget_dialog_animated.dart'; +import 'package:lightmeter/screens/shared/transparent_dialog/widget_dialog_transparent.dart'; import 'package:m3_lightmeter_iap/m3_lightmeter_iap.dart'; Future showBuyProDialog(BuildContext context) { - final unlockFeaturesEnabled = RemoteConfig.isEnabled(context, Feature.unlockProFeaturesText); - - Widget splitDescription() { - final description = - unlockFeaturesEnabled ? S.of(context).unlockProFeaturesDescription : S.of(context).lightmeterProDescription; - final paragraphs = description.split('\n\n'); - final features = paragraphs.first.split('\n \u2022 ').sublist(1); - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - Text(paragraphs.first.split('\n \u2022 ').first), - ...features.map( - (f) => Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text('\u2022 '), - Flexible(child: Text(f)), - ], - ), - ), - Text('\n${paragraphs.last}'), - ], - ); - } - return showDialog( context: context, - builder: (_) => AlertDialog( - icon: const Icon(Icons.star), - titlePadding: Dimens.dialogIconTitlePadding, - title: Text(unlockFeaturesEnabled ? S.of(context).proFeatures : S.of(context).lightmeterPro), - contentPadding: const EdgeInsets.symmetric(horizontal: Dimens.paddingL), - content: SingleChildScrollView(child: splitDescription()), - actionsPadding: Dimens.dialogActionsPadding, + builder: (_) => Dialog( + child: const ProFeaturesDialog(), + ), + ); +} + +class ProFeaturesDialog extends StatelessWidget { + const ProFeaturesDialog({super.key}); + + @override + Widget build(BuildContext context) { + return TransparentDialog( + icon: Icons.star, + title: S.of(context).proFeatures, + scrollableContent: false, + content: Flexible( + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: Dimens.paddingL), + child: Text( + S.of(context).unlockProFeaturesDescription, + style: Theme.of(context).textTheme.bodyMedium, + ), + ), + ), + ), actions: [ TextButton( - onPressed: Navigator.of(context).pop, + onPressed: () => _close(context), child: Text(S.of(context).cancel), ), FilledButton( onPressed: () { - Navigator.of(context).pop(); - IAPProductsProvider.maybeOf(context)?.buy(IAPProductType.paidFeatures); + _close(context).then((_) => IAPProductsProvider.maybeOf(context)?.buy(IAPProductType.paidFeatures)); }, - child: Text(unlockFeaturesEnabled ? S.of(context).unlock : S.of(context).buy), + child: Text(S.of(context).unlock), ), ], - ), - ); + ); + } + + Future _close(BuildContext context) async => AnimatedDialog.maybeClose(context) ?? Navigator.of(context).pop(); } diff --git a/lib/screens/shared/transparent_dialog/widget_dialog_transparent.dart b/lib/screens/shared/transparent_dialog/widget_dialog_transparent.dart new file mode 100644 index 0000000..26b968e --- /dev/null +++ b/lib/screens/shared/transparent_dialog/widget_dialog_transparent.dart @@ -0,0 +1,74 @@ +import 'package:flutter/material.dart'; +import 'package:lightmeter/res/dimens.dart'; + +class TransparentDialog extends StatelessWidget { + final IconData icon; + final String title; + final String? subtitle; + final Widget content; + final bool scrollableContent; + final List actions; + + const TransparentDialog({ + required this.icon, + required this.title, + this.subtitle, + required this.content, + required this.scrollableContent, + this.actions = const [], + super.key, + }); + + @override + Widget build(BuildContext context) { + return Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Padding( + padding: Dimens.dialogTitlePadding, + child: Icon(icon), + ), + Padding( + padding: Dimens.dialogIconTitlePadding, + child: Text( + title, + style: Theme.of(context).textTheme.headlineSmall, + textAlign: TextAlign.center, + ), + ), + if (subtitle != null) + Padding( + padding: Dimens.dialogIconTitlePadding, + child: Text( + subtitle!, + style: Theme.of(context).textTheme.bodyMedium, + textAlign: TextAlign.center, + ), + ), + ], + ), + if (scrollableContent) const Divider(), + content, + if (scrollableContent) const Divider(), + Padding( + padding: Dimens.dialogActionsPadding, + child: Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: _actions().toList(), + ), + ), + ], + ); + } + + Iterable _actions() sync* { + for (int i = 0; i < actions.length; i++) { + yield i == 0 ? const Spacer() : const SizedBox(width: Dimens.grid16); + yield actions[i]; + } + } +}