mirror of
https://github.com/vodemn/m3_lightmeter.git
synced 2024-11-22 07:20:39 +00:00
close AnimatedDialog
through context
This commit is contained in:
parent
2a4d79e35a
commit
8fdbc102b6
4 changed files with 156 additions and 50 deletions
|
@ -18,11 +18,8 @@ class _LightmeterProAnimatedDialogState extends State<LightmeterProAnimatedDialo
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
IAPProductsProvider.maybeOf(context)?.buy(IAPProductType.paidFeatures);
|
||||
},
|
||||
child: ReadingValueContainer(
|
||||
return AnimatedDialog(
|
||||
closedChild: ReadingValueContainer(
|
||||
color: Theme.of(context).colorScheme.errorContainer,
|
||||
values: [
|
||||
ReadingValue(
|
||||
|
@ -31,6 +28,44 @@ class _LightmeterProAnimatedDialogState extends State<LightmeterProAnimatedDialo
|
|||
),
|
||||
],
|
||||
),
|
||||
openedChild: ProFeaturesDialog(),
|
||||
openedSize: Size.fromHeight(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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,9 @@ class AnimatedDialog extends StatefulWidget {
|
|||
super.key,
|
||||
});
|
||||
|
||||
static Future<void>? maybeClose(BuildContext context) =>
|
||||
context.findAncestorWidgetOfExactType<_AnimatedOverlay>()?.onDismiss();
|
||||
|
||||
@override
|
||||
State<AnimatedDialog> createState() => AnimatedDialogState();
|
||||
}
|
||||
|
@ -147,9 +150,9 @@ class AnimatedDialogState extends State<AnimatedDialog> 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<double> borderRadiusAnimation;
|
||||
final Animation<Color?> foregroundColorAnimation;
|
||||
final Animation<double> elevationAnimation;
|
||||
final VoidCallback onDismiss;
|
||||
final Future<void> Function() onDismiss;
|
||||
final Widget? child;
|
||||
final Widget Function(BuildContext context)? builder;
|
||||
|
||||
|
|
|
@ -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<void> 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<void> _close(BuildContext context) async => AnimatedDialog.maybeClose(context) ?? Navigator.of(context).pop();
|
||||
}
|
||||
|
|
|
@ -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<Widget> 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<Widget> _actions() sync* {
|
||||
for (int i = 0; i < actions.length; i++) {
|
||||
yield i == 0 ? const Spacer() : const SizedBox(width: Dimens.grid16);
|
||||
yield actions[i];
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue