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: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<LightmeterProAnimatedDialog> createState() => _LightmeterProAnimatedDialogState();
}
class _LightmeterProAnimatedDialogState extends State<LightmeterProAnimatedDialog> {
final _key = GlobalKey<AnimatedDialogState>();
@override
Widget build(BuildContext context) {
return AnimatedDialog(
@ -28,44 +19,8 @@ class _LightmeterProAnimatedDialogState extends State<LightmeterProAnimatedDialo
),
],
),
openedChild: ProFeaturesDialog(),
openedSize: Size.fromHeight(height(context)),
openedChild: const ProFeaturesDialog(),
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:lightmeter/generated/l10n.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 DialogPickerItemTrailingBuilder<T> = Widget? Function(T selected, T value);
@ -29,29 +30,13 @@ class DialogPicker<T> 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<DialogPicker<T>> createState() => _DialogPickerState<T>();
@ -70,78 +55,43 @@ class _DialogPickerState<T> extends State<DialogPicker<T>> {
@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),
),
],
);

View file

@ -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');

View file

@ -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<void> 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(

View file

@ -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(

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