This commit is contained in:
Vadim 2024-01-12 13:17:05 +01:00
parent 8fdbc102b6
commit 1d149425ab
6 changed files with 122 additions and 152 deletions

View file

@ -1,21 +1,12 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:lightmeter/generated/l10n.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/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/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:lightmeter/screens/shared/pro_features_dialog/widget_dialog_pro_features.dart';
import 'package:m3_lightmeter_iap/m3_lightmeter_iap.dart';
class LightmeterProAnimatedDialog extends StatefulWidget { class LightmeterProAnimatedDialog extends StatelessWidget {
const LightmeterProAnimatedDialog({super.key}); const LightmeterProAnimatedDialog({super.key});
@override
State<LightmeterProAnimatedDialog> createState() => _LightmeterProAnimatedDialogState();
}
class _LightmeterProAnimatedDialogState extends State<LightmeterProAnimatedDialog> {
final _key = GlobalKey<AnimatedDialogState>();
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return AnimatedDialog( return AnimatedDialog(
@ -28,44 +19,8 @@ class _LightmeterProAnimatedDialogState extends State<LightmeterProAnimatedDialo
), ),
], ],
), ),
openedChild: ProFeaturesDialog(), openedChild: const ProFeaturesDialog(),
openedSize: Size.fromHeight(height(context)), openedSize: Size.fromHeight(const ProFeaturesDialog().height(context)),
); );
} }
double height(BuildContext context) {
double textHeight(
BuildContext context,
String text,
TextStyle? style,
double horizontalPadding,
) {
final TextPainter titlePainter = TextPainter(
text: TextSpan(
text: text,
style: style,
),
textDirection: TextDirection.ltr,
)..layout(maxWidth: MediaQuery.of(context).size.width - Dimens.dialogMargin.horizontal - horizontalPadding);
return titlePainter.size.height;
}
final titleHeight = textHeight(
context,
S.of(context).unlockProFeatures,
Theme.of(context).textTheme.headlineSmall,
Dimens.dialogIconTitlePadding.horizontal,
);
final contentHeight = textHeight(
context,
S.of(context).unlockProFeaturesDescription,
Theme.of(context).textTheme.bodyMedium,
Dimens.paddingL * 2,
);
return (IconTheme.of(context).size! + Dimens.dialogTitlePadding.vertical) + // icon + icon padding
(titleHeight + Dimens.dialogIconTitlePadding.vertical) + // title + title padding
contentHeight +
(48 + Dimens.dialogActionsPadding.vertical); // actions + actions padding
}
} }

View file

@ -1,6 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:lightmeter/generated/l10n.dart'; import 'package:lightmeter/generated/l10n.dart';
import 'package:lightmeter/res/dimens.dart'; import 'package:lightmeter/res/dimens.dart';
import 'package:lightmeter/screens/shared/transparent_dialog/widget_dialog_transparent.dart';
typedef DialogPickerItemTitleBuilder<T> = Widget Function(BuildContext context, T value); typedef DialogPickerItemTitleBuilder<T> = Widget Function(BuildContext context, T value);
typedef DialogPickerItemTrailingBuilder<T> = Widget? Function(T selected, T value); typedef DialogPickerItemTrailingBuilder<T> = Widget? Function(T selected, T value);
@ -29,29 +30,13 @@ class DialogPicker<T> extends StatefulWidget {
super.key, super.key,
}); });
double height(BuildContext context) { double height(BuildContext context) => TransparentDialog.height(
double textHeight(BuildContext context, String text, TextStyle? style) { context,
final TextPainter titlePainter = TextPainter( title: title,
text: TextSpan( subtitle: subtitle,
text: text, scrollableContent: true,
style: style, contextHeight: Dimens.grid56 * values.length,
), );
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
}
@override @override
State<DialogPicker<T>> createState() => _DialogPickerState<T>(); State<DialogPicker<T>> createState() => _DialogPickerState<T>();
@ -70,37 +55,11 @@ class _DialogPickerState<T> extends State<DialogPicker<T>> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Column( return TransparentDialog(
crossAxisAlignment: CrossAxisAlignment.stretch, icon: widget.icon,
children: [ title: widget.title,
Column( subtitle: widget.subtitle,
crossAxisAlignment: CrossAxisAlignment.stretch, content: Expanded(
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( child: ListView.builder(
controller: _scrollController, controller: _scrollController,
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
@ -124,26 +83,17 @@ class _DialogPickerState<T> extends State<DialogPicker<T>> {
), ),
), ),
), ),
const Divider(), scrollableContent: true,
Padding( actions: [
padding: Dimens.dialogActionsPadding,
child: Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
const Spacer(),
TextButton( TextButton(
onPressed: widget.onCancel, onPressed: widget.onCancel,
child: Text(S.of(context).cancel), child: Text(S.of(context).cancel),
), ),
const SizedBox(width: Dimens.grid16),
TextButton( TextButton(
onPressed: () => widget.onSelect(_selectedValue), onPressed: () => widget.onSelect(_selectedValue),
child: Text(S.of(context).select), child: Text(S.of(context).select),
), ),
], ],
),
),
],
); );
} }
} }

View file

@ -4,7 +4,7 @@ import 'package:lightmeter/generated/l10n.dart';
import 'package:lightmeter/providers/remote_config_provider.dart'; import 'package:lightmeter/providers/remote_config_provider.dart';
import 'package:lightmeter/providers/services_provider.dart'; import 'package:lightmeter/providers/services_provider.dart';
import 'package:lightmeter/res/dimens.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'; import 'package:m3_lightmeter_iap/m3_lightmeter_iap.dart';
class BuyProListTile extends StatelessWidget { class BuyProListTile extends StatelessWidget {
@ -20,7 +20,10 @@ class BuyProListTile extends StatelessWidget {
title: Text(unlockFeaturesEnabled ? S.of(context).unlockProFeatures : S.of(context).buyLightmeterPro), title: Text(unlockFeaturesEnabled ? S.of(context).unlockProFeatures : S.of(context).buyLightmeterPro),
onTap: !isPending onTap: !isPending
? () { ? () {
showBuyProDialog(context); showDialog(
context: context,
builder: (_) => const Dialog(child: ProFeaturesDialog()),
);
ServicesProvider.of(context) ServicesProvider.of(context)
.analytics .analytics
.logUnlockProFeatures(unlockFeaturesEnabled ? 'Unlock Pro features' : 'Buy Lightmeter Pro'); .logUnlockProFeatures(unlockFeaturesEnabled ? 'Unlock Pro features' : 'Buy Lightmeter Pro');

View file

@ -3,20 +3,23 @@ import 'package:lightmeter/generated/l10n.dart';
import 'package:lightmeter/res/dimens.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/animated_dialog_picker/components/animated_dialog/widget_dialog_animated.dart';
import 'package:lightmeter/screens/shared/transparent_dialog/widget_dialog_transparent.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'; import 'package:m3_lightmeter_iap/m3_lightmeter_iap.dart';
Future<void> showBuyProDialog(BuildContext context) {
return showDialog(
context: context,
builder: (_) => Dialog(
child: const ProFeaturesDialog(),
),
);
}
class ProFeaturesDialog extends StatelessWidget { class ProFeaturesDialog extends StatelessWidget {
const ProFeaturesDialog({super.key}); 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 @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return TransparentDialog( return TransparentDialog(

View file

@ -1,5 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:lightmeter/res/dimens.dart'; import 'package:lightmeter/res/dimens.dart';
import 'package:lightmeter/utils/text_height.dart';
class TransparentDialog extends StatelessWidget { class TransparentDialog extends StatelessWidget {
final IconData icon; final IconData icon;
@ -19,6 +20,35 @@ class TransparentDialog extends StatelessWidget {
super.key, 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 @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Column( return Column(

View file

@ -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;
}