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 1a5e10d..4a4b8d0 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 @@ -1,21 +1,12 @@ import 'package:flutter/material.dart'; import 'package:lightmeter/generated/l10n.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/metering/components/shared/readings_container/components/shared/reading_value_container/widget_container_reading_value.dart'; -import 'package:lightmeter/screens/settings/utils/show_buy_pro_dialog.dart'; -import 'package:m3_lightmeter_iap/m3_lightmeter_iap.dart'; +import 'package:lightmeter/screens/shared/pro_features_dialog/widget_dialog_pro_features.dart'; -class LightmeterProAnimatedDialog extends StatefulWidget { +class LightmeterProAnimatedDialog extends StatelessWidget { const LightmeterProAnimatedDialog({super.key}); - @override - State createState() => _LightmeterProAnimatedDialogState(); -} - -class _LightmeterProAnimatedDialogState extends State { - final _key = GlobalKey(); - @override Widget build(BuildContext context) { return AnimatedDialog( @@ -28,44 +19,8 @@ class _LightmeterProAnimatedDialogState extends State = Widget Function(BuildContext context, T value); typedef DialogPickerItemTrailingBuilder = Widget? Function(T selected, T value); @@ -29,29 +30,13 @@ class DialogPicker extends StatefulWidget { super.key, }); - double height(BuildContext context) { - double textHeight(BuildContext context, String text, TextStyle? style) { - final TextPainter titlePainter = TextPainter( - text: TextSpan( - text: text, - style: style, - ), - textDirection: TextDirection.ltr, - )..layout(maxWidth: MediaQuery.of(context).size.width - Dimens.dialogIconTitlePadding.horizontal); - return titlePainter.size.height + Dimens.dialogIconTitlePadding.vertical; - } - - final titleHeight = textHeight(context, title, Theme.of(context).textTheme.headlineSmall); - final subtitleHeight = - subtitle != null ? textHeight(context, subtitle!, Theme.of(context).textTheme.bodyMedium) : 0; - - return (IconTheme.of(context).size! + Dimens.dialogTitlePadding.vertical) + // icon + icon padding - titleHeight + // title + title padding - subtitleHeight + // subtitle + subtitle padding - Dimens.grid56 * values.length + // values summary height - 1 + // dividers - (48 + Dimens.dialogActionsPadding.vertical); // actions + actions padding - } + double height(BuildContext context) => TransparentDialog.height( + context, + title: title, + subtitle: subtitle, + scrollableContent: true, + contextHeight: Dimens.grid56 * values.length, + ); @override State> createState() => _DialogPickerState(); @@ -70,78 +55,43 @@ class _DialogPickerState extends State> { @override Widget build(BuildContext context) { - return Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Padding( - padding: Dimens.dialogTitlePadding, - child: Icon(widget.icon), - ), - Padding( - padding: Dimens.dialogIconTitlePadding, - child: Text( - widget.title, - style: Theme.of(context).textTheme.headlineSmall, - textAlign: TextAlign.center, - ), - ), - if (widget.subtitle != null) - Padding( - padding: Dimens.dialogIconTitlePadding, - child: Text( - widget.subtitle!, - style: Theme.of(context).textTheme.bodyMedium, - textAlign: TextAlign.center, - ), - ), - ], - ), - const Divider(), - Expanded( - child: ListView.builder( - controller: _scrollController, - padding: EdgeInsets.zero, - itemCount: widget.values.length, - itemExtent: Dimens.grid56, - itemBuilder: (context, index) => RadioListTile( - value: widget.values[index], - groupValue: _selectedValue, - title: DefaultTextStyle( - style: Theme.of(context).textTheme.bodyLarge!, - child: widget.itemTitleBuilder(context, widget.values[index]), - ), - secondary: widget.itemTrailingBuilder?.call(_selectedValue, widget.values[index]), - onChanged: (value) { - if (value != null) { - setState(() { - _selectedValue = value; - }); - } - }, + return TransparentDialog( + icon: widget.icon, + title: widget.title, + subtitle: widget.subtitle, + content: Expanded( + child: ListView.builder( + controller: _scrollController, + padding: EdgeInsets.zero, + itemCount: widget.values.length, + itemExtent: Dimens.grid56, + itemBuilder: (context, index) => RadioListTile( + value: widget.values[index], + groupValue: _selectedValue, + title: DefaultTextStyle( + style: Theme.of(context).textTheme.bodyLarge!, + child: widget.itemTitleBuilder(context, widget.values[index]), ), + secondary: widget.itemTrailingBuilder?.call(_selectedValue, widget.values[index]), + onChanged: (value) { + if (value != null) { + setState(() { + _selectedValue = value; + }); + } + }, ), ), - const Divider(), - Padding( - padding: Dimens.dialogActionsPadding, - child: Row( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - const Spacer(), - TextButton( - onPressed: widget.onCancel, - child: Text(S.of(context).cancel), - ), - const SizedBox(width: Dimens.grid16), - TextButton( - onPressed: () => widget.onSelect(_selectedValue), - child: Text(S.of(context).select), - ), - ], - ), + ), + scrollableContent: true, + actions: [ + TextButton( + onPressed: widget.onCancel, + child: Text(S.of(context).cancel), + ), + TextButton( + onPressed: () => widget.onSelect(_selectedValue), + child: Text(S.of(context).select), ), ], ); diff --git a/lib/screens/settings/components/lightmeter_pro/components/buy_pro/widget_list_tile_buy_pro.dart b/lib/screens/settings/components/lightmeter_pro/components/buy_pro/widget_list_tile_buy_pro.dart index 9854a14..2e26da4 100644 --- a/lib/screens/settings/components/lightmeter_pro/components/buy_pro/widget_list_tile_buy_pro.dart +++ b/lib/screens/settings/components/lightmeter_pro/components/buy_pro/widget_list_tile_buy_pro.dart @@ -4,7 +4,7 @@ import 'package:lightmeter/generated/l10n.dart'; import 'package:lightmeter/providers/remote_config_provider.dart'; import 'package:lightmeter/providers/services_provider.dart'; import 'package:lightmeter/res/dimens.dart'; -import 'package:lightmeter/screens/settings/utils/show_buy_pro_dialog.dart'; +import 'package:lightmeter/screens/shared/pro_features_dialog/widget_dialog_pro_features.dart'; import 'package:m3_lightmeter_iap/m3_lightmeter_iap.dart'; class BuyProListTile extends StatelessWidget { @@ -20,7 +20,10 @@ class BuyProListTile extends StatelessWidget { title: Text(unlockFeaturesEnabled ? S.of(context).unlockProFeatures : S.of(context).buyLightmeterPro), onTap: !isPending ? () { - showBuyProDialog(context); + showDialog( + context: context, + builder: (_) => const Dialog(child: ProFeaturesDialog()), + ); ServicesProvider.of(context) .analytics .logUnlockProFeatures(unlockFeaturesEnabled ? 'Unlock Pro features' : 'Buy Lightmeter Pro'); diff --git a/lib/screens/settings/utils/show_buy_pro_dialog.dart b/lib/screens/shared/pro_features_dialog/widget_dialog_pro_features.dart similarity index 80% rename from lib/screens/settings/utils/show_buy_pro_dialog.dart rename to lib/screens/shared/pro_features_dialog/widget_dialog_pro_features.dart index 93e5ed7..c58e94d 100644 --- a/lib/screens/settings/utils/show_buy_pro_dialog.dart +++ b/lib/screens/shared/pro_features_dialog/widget_dialog_pro_features.dart @@ -3,20 +3,23 @@ import 'package:lightmeter/generated/l10n.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:lightmeter/utils/text_height.dart'; import 'package:m3_lightmeter_iap/m3_lightmeter_iap.dart'; -Future showBuyProDialog(BuildContext context) { - return showDialog( - context: context, - builder: (_) => Dialog( - child: const ProFeaturesDialog(), - ), - ); -} - class ProFeaturesDialog extends StatelessWidget { const ProFeaturesDialog({super.key}); + double height(BuildContext context) => TransparentDialog.height( + context, + title: S.of(context).proFeatures, + contextHeight: dialogTextHeight( + context, + S.of(context).unlockProFeaturesDescription, + Theme.of(context).textTheme.bodyMedium, + Dimens.paddingL * 2, + ), + ); + @override Widget build(BuildContext context) { return TransparentDialog( diff --git a/lib/screens/shared/transparent_dialog/widget_dialog_transparent.dart b/lib/screens/shared/transparent_dialog/widget_dialog_transparent.dart index 26b968e..ee3870e 100644 --- a/lib/screens/shared/transparent_dialog/widget_dialog_transparent.dart +++ b/lib/screens/shared/transparent_dialog/widget_dialog_transparent.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:lightmeter/res/dimens.dart'; +import 'package:lightmeter/utils/text_height.dart'; class TransparentDialog extends StatelessWidget { final IconData icon; @@ -19,6 +20,35 @@ class TransparentDialog extends StatelessWidget { super.key, }); + static double height( + BuildContext context, { + required String title, + String? subtitle, + required double contextHeight, + bool scrollableContent = false, + }) { + double height = IconTheme.of(context).size! + Dimens.dialogTitlePadding.vertical; + height += dialogTextHeight( + context, + title, + Theme.of(context).textTheme.headlineSmall, + Dimens.dialogIconTitlePadding.horizontal, + ) + + Dimens.dialogIconTitlePadding.vertical; + if (subtitle != null) { + height += dialogTextHeight( + context, + subtitle, + Theme.of(context).textTheme.bodyMedium, + Dimens.dialogIconTitlePadding.horizontal, + ) + + Dimens.dialogIconTitlePadding.vertical; + } + height += contextHeight; + if (scrollableContent) height += 1; + return height += 48 + Dimens.dialogActionsPadding.vertical; + } + @override Widget build(BuildContext context) { return Column( diff --git a/lib/utils/text_height.dart b/lib/utils/text_height.dart new file mode 100644 index 0000000..f5a0fe1 --- /dev/null +++ b/lib/utils/text_height.dart @@ -0,0 +1,29 @@ +import 'package:flutter/material.dart'; +import 'package:lightmeter/res/dimens.dart'; + +double dialogTextHeight( + BuildContext context, + String text, + TextStyle? style, + double textPadding, +) => + textHeight( + text, + style, + MediaQuery.sizeOf(context).width - Dimens.dialogMargin.horizontal - textPadding, + ); + +double textHeight( + String text, + TextStyle? style, + double maxWidth, +) { + final TextPainter titlePainter = TextPainter( + text: TextSpan( + text: text, + style: style, + ), + textDirection: TextDirection.ltr, + )..layout(maxWidth: maxWidth); + return titlePainter.height; +}