From 613a0f18a6670f79c8cd101f47eff24d2637664d Mon Sep 17 00:00:00 2001 From: Vadim <44135514+vodemn@users.noreply.github.com> Date: Sun, 17 Sep 2023 16:05:01 +0200 Subject: [PATCH] disable only list tiles --- .../widget_list_tile_equipment_profiles.dart | 3 +- .../films/widget_list_tile_films.dart | 3 +- .../widget_settings_section_equipment.dart | 2 - .../buy_pro/widget_list_tile_buy_pro.dart | 2 + .../widget_section_expandable.dart | 242 ------------------ .../iap_list_tile/widget_list_tile_iap.dart | 39 +++ .../widget_settings_section.dart | 35 ++- 7 files changed, 60 insertions(+), 266 deletions(-) delete mode 100644 lib/screens/settings/components/shared/expandable_section/widget_section_expandable.dart create mode 100644 lib/screens/settings/components/shared/iap_list_tile/widget_list_tile_iap.dart diff --git a/lib/screens/settings/components/equipment/components/equipment_profiles/widget_list_tile_equipment_profiles.dart b/lib/screens/settings/components/equipment/components/equipment_profiles/widget_list_tile_equipment_profiles.dart index c48b685..0cb5631 100644 --- a/lib/screens/settings/components/equipment/components/equipment_profiles/widget_list_tile_equipment_profiles.dart +++ b/lib/screens/settings/components/equipment/components/equipment_profiles/widget_list_tile_equipment_profiles.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:lightmeter/generated/l10n.dart'; import 'package:lightmeter/screens/settings/components/equipment/components/equipment_profiles/components/equipment_profile_screen/screen_equipment_profile.dart'; +import 'package:lightmeter/screens/settings/components/shared/iap_list_tile/widget_list_tile_iap.dart'; import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart'; class EquipmentProfilesListTile extends StatelessWidget { @@ -8,7 +9,7 @@ class EquipmentProfilesListTile extends StatelessWidget { @override Widget build(BuildContext context) { - return ListTile( + return IAPListTile( leading: const Icon(Icons.camera), title: Text(S.of(context).equipmentProfiles), onTap: () { diff --git a/lib/screens/settings/components/equipment/components/films/widget_list_tile_films.dart b/lib/screens/settings/components/equipment/components/films/widget_list_tile_films.dart index 2ae40e9..c343e2b 100644 --- a/lib/screens/settings/components/equipment/components/films/widget_list_tile_films.dart +++ b/lib/screens/settings/components/equipment/components/films/widget_list_tile_films.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:lightmeter/generated/l10n.dart'; import 'package:lightmeter/screens/settings/components/shared/dialog_filter/widget_dialog_filter.dart'; +import 'package:lightmeter/screens/settings/components/shared/iap_list_tile/widget_list_tile_iap.dart'; import 'package:m3_lightmeter_iap/m3_lightmeter_iap.dart'; import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart'; @@ -9,7 +10,7 @@ class FilmsListTile extends StatelessWidget { @override Widget build(BuildContext context) { - return ListTile( + return IAPListTile( leading: const Icon(Icons.camera_roll), title: Text(S.of(context).filmsInUse), onTap: () { diff --git a/lib/screens/settings/components/equipment/widget_settings_section_equipment.dart b/lib/screens/settings/components/equipment/widget_settings_section_equipment.dart index 2c1a03f..ba3b975 100644 --- a/lib/screens/settings/components/equipment/widget_settings_section_equipment.dart +++ b/lib/screens/settings/components/equipment/widget_settings_section_equipment.dart @@ -3,7 +3,6 @@ import 'package:lightmeter/generated/l10n.dart'; import 'package:lightmeter/screens/settings/components/equipment/components/equipment_profiles/widget_list_tile_equipment_profiles.dart'; import 'package:lightmeter/screens/settings/components/equipment/components/films/widget_list_tile_films.dart'; import 'package:lightmeter/screens/settings/components/shared/settings_section/widget_settings_section.dart'; -import 'package:m3_lightmeter_iap/m3_lightmeter_iap.dart'; class EquipmentSettingsSection extends StatelessWidget { const EquipmentSettingsSection({super.key}); @@ -12,7 +11,6 @@ class EquipmentSettingsSection extends StatelessWidget { Widget build(BuildContext context) { return SettingsSection( title: S.of(context).equipment, - enabled: IAPProducts.isPurchased(context, IAPProductType.paidFeatures), children: const [ EquipmentProfilesListTile(), FilmsListTile(), 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 64f9b0e..6f0f458 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 @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:lightmeter/generated/l10n.dart'; import 'package:lightmeter/res/dimens.dart'; +import 'package:m3_lightmeter_iap/m3_lightmeter_iap.dart'; class BuyProListTile extends StatelessWidget { const BuyProListTile({super.key}); @@ -28,6 +29,7 @@ class BuyProListTile extends StatelessWidget { FilledButton( onPressed: () { Navigator.of(context).pop(); + IAPProductsProvider.of(context).buy(IAPProductType.paidFeatures); }, child: Text(S.of(context).buy), ), diff --git a/lib/screens/settings/components/shared/expandable_section/widget_section_expandable.dart b/lib/screens/settings/components/shared/expandable_section/widget_section_expandable.dart deleted file mode 100644 index d201987..0000000 --- a/lib/screens/settings/components/shared/expandable_section/widget_section_expandable.dart +++ /dev/null @@ -1,242 +0,0 @@ -import 'dart:math'; - -import 'package:flutter/material.dart'; -import 'package:flutter/scheduler.dart'; -import 'package:lightmeter/res/dimens.dart'; -import 'package:lightmeter/screens/settings/components/equipment/components/equipment_profiles/components/equipment_profile_screen/components/equipment_profile_container/components/equipment_list_tiles/widget_list_tiles_equipments.dart'; -import 'package:lightmeter/screens/settings/components/equipment/components/equipment_profiles/components/equipment_profile_screen/components/equipment_profile_name_dialog/widget_dialog_equipment_profile_name.dart'; -import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart'; - -class ExpandableSection extends StatefulWidget { - final EquipmentProfile data; - final ValueChanged onUpdate; - final VoidCallback onDelete; - final VoidCallback onExpand; - - const ExpandableSection({ - required this.data, - required this.onUpdate, - required this.onDelete, - required this.onExpand, - super.key, - }); - - @override - State createState() => ExpandableSectionState(); -} - -class ExpandableSectionState extends State - with TickerProviderStateMixin { - late EquipmentProfile _equipmentData = EquipmentProfile( - id: widget.data.id, - name: widget.data.name, - apertureValues: widget.data.apertureValues, - ndValues: widget.data.ndValues, - shutterSpeedValues: widget.data.shutterSpeedValues, - isoValues: widget.data.isoValues, - ); - - late final AnimationController _controller = AnimationController( - duration: Dimens.durationM, - vsync: this, - ); - bool get _expanded => _controller.isCompleted; - - @override - void didUpdateWidget(ExpandableSection oldWidget) { - super.didUpdateWidget(oldWidget); - _equipmentData = EquipmentProfile( - id: widget.data.id, - name: widget.data.name, - apertureValues: widget.data.apertureValues, - ndValues: widget.data.ndValues, - shutterSpeedValues: widget.data.shutterSpeedValues, - isoValues: widget.data.isoValues, - ); - } - - @override - void dispose() { - _controller.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return Card( - child: Padding( - padding: const EdgeInsets.symmetric(vertical: Dimens.paddingM), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - ListTile( - contentPadding: const EdgeInsets.symmetric(horizontal: Dimens.paddingM), - title: Row( - children: [ - _AnimatedNameLeading(controller: _controller), - const SizedBox(width: Dimens.grid8), - Flexible( - child: Text( - _equipmentData.name, - maxLines: 1, - overflow: TextOverflow.ellipsis, - ), - ), - ], - ), - trailing: Row( - mainAxisAlignment: MainAxisAlignment.end, - mainAxisSize: MainAxisSize.min, - children: [ - _AnimatedArrowButton( - controller: _controller, - onPressed: () => _expanded ? collapse() : expand(), - ), - IconButton( - onPressed: widget.onDelete, - icon: const Icon(Icons.delete), - ), - ], - ), - onTap: () => _expanded ? _showNameDialog() : expand(), - ), - _AnimatedEquipmentListTiles( - controller: _controller, - equipmentData: _equipmentData, - onApertureValuesSelected: (value) { - _equipmentData = _equipmentData.copyWith(apertureValues: value); - widget.onUpdate(_equipmentData); - }, - onIsoValuesSelecred: (value) { - _equipmentData = _equipmentData.copyWith(isoValues: value); - widget.onUpdate(_equipmentData); - }, - onNdValuesSelected: (value) { - _equipmentData = _equipmentData.copyWith(ndValues: value); - widget.onUpdate(_equipmentData); - }, - onShutterSpeedValuesSelected: (value) { - _equipmentData = _equipmentData.copyWith(shutterSpeedValues: value); - widget.onUpdate(_equipmentData); - }, - ), - ], - ), - ), - ); - } - - void _showNameDialog() { - showDialog( - context: context, - builder: (_) => EquipmentProfileNameDialog(initialValue: _equipmentData.name), - ).then((value) { - if (value != null) { - _equipmentData = _equipmentData.copyWith(name: value); - widget.onUpdate(_equipmentData); - } - }); - } - - void expand() { - widget.onExpand(); - _controller.forward(); - SchedulerBinding.instance.addPostFrameCallback((_) { - Future.delayed(_controller.duration!).then((_) { - Scrollable.ensureVisible( - context, - alignmentPolicy: ScrollPositionAlignmentPolicy.keepVisibleAtEnd, - duration: _controller.duration!, - ); - }); - }); - } - - void collapse() { - _controller.reverse(); - } -} - -class _AnimatedNameLeading extends AnimatedWidget { - const _AnimatedNameLeading({required AnimationController controller}) - : super(listenable: controller); - - Animation get _progress => listenable as Animation; - - @override - Widget build(BuildContext context) { - return Padding( - padding: EdgeInsets.only(right: _progress.value * Dimens.grid8), - child: Icon( - Icons.edit, - size: _progress.value * Dimens.grid24, - ), - ); - } -} - -class _AnimatedArrowButton extends AnimatedWidget { - final VoidCallback onPressed; - - const _AnimatedArrowButton({ - required AnimationController controller, - required this.onPressed, - }) : super(listenable: controller); - - Animation get _progress => listenable as Animation; - - @override - Widget build(BuildContext context) { - return IconButton( - onPressed: onPressed, - icon: Transform.rotate( - angle: _progress.value * pi, - child: const Icon(Icons.keyboard_arrow_down), - ), - ); - } -} - -class _AnimatedEquipmentListTiles extends AnimatedWidget { - final EquipmentProfile equipmentData; - final ValueChanged> onApertureValuesSelected; - final ValueChanged> onIsoValuesSelecred; - final ValueChanged> onNdValuesSelected; - final ValueChanged> onShutterSpeedValuesSelected; - - const _AnimatedEquipmentListTiles({ - required AnimationController controller, - required this.equipmentData, - required this.onApertureValuesSelected, - required this.onIsoValuesSelecred, - required this.onNdValuesSelected, - required this.onShutterSpeedValuesSelected, - }) : super(listenable: controller); - - Animation get _progress => listenable as Animation; - - @override - Widget build(BuildContext context) { - return SizedOverflowBox( - alignment: Alignment.topCenter, - size: Size( - double.maxFinite, - _progress.value * Dimens.grid56 * 4, - ), - child: Opacity( - opacity: _progress.value, - child: EquipmentListTiles( - selectedApertureValues: equipmentData.apertureValues, - selectedIsoValues: equipmentData.isoValues, - selectedNdValues: equipmentData.ndValues, - selectedShutterSpeedValues: equipmentData.shutterSpeedValues, - onApertureValuesSelected: onApertureValuesSelected, - onIsoValuesSelecred: onIsoValuesSelecred, - onNdValuesSelected: onNdValuesSelected, - onShutterSpeedValuesSelected: onShutterSpeedValuesSelected, - ), - ), - ); - } -} diff --git a/lib/screens/settings/components/shared/iap_list_tile/widget_list_tile_iap.dart b/lib/screens/settings/components/shared/iap_list_tile/widget_list_tile_iap.dart new file mode 100644 index 0000000..45b718d --- /dev/null +++ b/lib/screens/settings/components/shared/iap_list_tile/widget_list_tile_iap.dart @@ -0,0 +1,39 @@ +import 'package:flutter/material.dart'; +import 'package:lightmeter/res/dimens.dart'; +import 'package:m3_lightmeter_iap/m3_lightmeter_iap.dart'; + +/// Depends on the product status and replaces [onTap] with purchase callback +/// if the product is purchasable. +class IAPListTile extends StatelessWidget { + final IAPProductType product; + final Icon leading; + final Text title; + final VoidCallback onTap; + + const IAPListTile({ + this.product = IAPProductType.paidFeatures, + required this.leading, + required this.title, + required this.onTap, + super.key, + }); + + @override + Widget build(BuildContext context) { + return Opacity( + opacity: IAPProducts.isPurchased(context, product) + ? Dimens.enabledOpacity + : Dimens.disabledOpacity, + child: ListTile( + leading: leading, + title: title, + onTap: switch (IAPProducts.productOf(context, product)?.status) { + IAPProductStatus.purchasable => () => IAPProductsProvider.of(context).buy(product), + IAPProductStatus.pending => null, + IAPProductStatus.purchased => onTap, + null => null, + }, + ), + ); + } +} diff --git a/lib/screens/settings/components/shared/settings_section/widget_settings_section.dart b/lib/screens/settings/components/shared/settings_section/widget_settings_section.dart index 9f88d7d..be62847 100644 --- a/lib/screens/settings/components/shared/settings_section/widget_settings_section.dart +++ b/lib/screens/settings/components/shared/settings_section/widget_settings_section.dart @@ -4,12 +4,10 @@ import 'package:lightmeter/res/dimens.dart'; class SettingsSection extends StatelessWidget { final String title; final List children; - final bool enabled; const SettingsSection({ required this.title, required this.children, - this.enabled = true, super.key, }); @@ -25,25 +23,22 @@ class SettingsSection extends StatelessWidget { child: Card( child: Padding( padding: const EdgeInsets.symmetric(vertical: Dimens.paddingM), - child: Opacity( - opacity: enabled ? Dimens.enabledOpacity : Dimens.disabledOpacity, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - Padding( - padding: const EdgeInsets.symmetric(horizontal: Dimens.paddingM), - child: Text( - title, - style: Theme.of(context) - .textTheme - .labelLarge - ?.copyWith(color: Theme.of(context).colorScheme.onSurface), - ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: Dimens.paddingM), + child: Text( + title, + style: Theme.of(context) + .textTheme + .labelLarge + ?.copyWith(color: Theme.of(context).colorScheme.onSurface), ), - ...children, - ], - ), + ), + ...children, + ], ), ), ),