diff --git a/lib/pangea/common/constants/local.key.dart b/lib/pangea/common/constants/local.key.dart index 9d722ca6c..1aae92846 100644 --- a/lib/pangea/common/constants/local.key.dart +++ b/lib/pangea/common/constants/local.key.dart @@ -5,6 +5,7 @@ class PLocalKey { static const String dismissedPaywall = 'dismissedPaywall'; static const String paywallBackoff = 'paywallBackoff'; static const String clickedCancelSubscription = 'clickedCancelSubscription'; + static const String subscriptionEndDate = 'subscriptionWillEnd'; static const String messagesSinceUpdate = 'messagesSinceLastUpdate'; static const String completedActivities = 'completedActivities'; static const String justInputtedCode = 'justInputtedCode'; diff --git a/lib/pangea/subscription/pages/settings_subscription.dart b/lib/pangea/subscription/pages/settings_subscription.dart index a1f54d8ca..37145333a 100644 --- a/lib/pangea/subscription/pages/settings_subscription.dart +++ b/lib/pangea/subscription/pages/settings_subscription.dart @@ -1,5 +1,6 @@ import 'dart:async'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:url_launcher/url_launcher_string.dart'; @@ -22,7 +23,8 @@ class SubscriptionManagement extends StatefulWidget { SubscriptionManagementController(); } -class SubscriptionManagementController extends State { +class SubscriptionManagementController extends State + with WidgetsBindingObserver { final SubscriptionController subscriptionController = MatrixState.pangeaController.subscriptionController; @@ -31,6 +33,9 @@ class SubscriptionManagementController extends State { @override void initState() { + WidgetsBinding.instance.addObserver(this); + _refreshSubscription(); + if (!subscriptionController.initCompleter.isCompleted) { subscriptionController.initialize().then((_) => setState(() {})); } @@ -43,11 +48,20 @@ class SubscriptionManagementController extends State { @override void dispose() { + WidgetsBinding.instance.removeObserver(this); subscriptionController.subscriptionNotifier.removeListener(_onSubscribe); subscriptionController.removeListener(_onSubscriptionUpdate); super.dispose(); } + @override + void didChangeAppLifecycleState(AppLifecycleState state) { + if (state == AppLifecycleState.resumed) { + _refreshSubscription(); + } + super.didChangeAppLifecycleState(state); + } + bool get subscriptionsAvailable => subscriptionController .availableSubscriptionInfo?.availableSubscriptions.isNotEmpty ?? @@ -103,6 +117,33 @@ class SubscriptionManagementController extends State { void _onSubscriptionUpdate() => setState(() {}); void _onSubscribe() => showSubscribedSnackbar(context); + Future _refreshSubscription() async { + if (!kIsWeb) return; + + // if the user previously clicked cancel, check if the subscription end date has changed + final prevEndDate = SubscriptionManagementRepo.getSubscriptionEndDate(); + final clickedCancel = + SubscriptionManagementRepo.getClickedCancelSubscription(); + if (clickedCancel == null) return; + + await subscriptionController.reinitialize(); + final newEndDate = + subscriptionController.currentSubscriptionInfo?.subscriptionEndDate; + + if (prevEndDate != newEndDate) { + SubscriptionManagementRepo.removeClickedCancelSubscription(); + SubscriptionManagementRepo.setSubscriptionEndDate(newEndDate); + if (mounted) setState(() {}); + return; + } + + // if more than 10 minutes have passed since the user clicked cancel, remove the click flag + if (DateTime.now().difference(clickedCancel).inMinutes >= 10) { + SubscriptionManagementRepo.removeClickedCancelSubscription(); + if (mounted) setState(() {}); + } + } + Future submitChange( SubscriptionDetails subscription, { bool isPromo = false, @@ -130,6 +171,9 @@ class SubscriptionManagementController extends State { Future onClickCancelSubscription() async { await SubscriptionManagementRepo.setClickedCancelSubscription(); + await SubscriptionManagementRepo.setSubscriptionEndDate( + subscriptionEndDate, + ); await launchMangementUrl(ManagementOption.cancel); if (mounted) setState(() {}); } diff --git a/lib/pangea/subscription/pages/settings_subscription_view.dart b/lib/pangea/subscription/pages/settings_subscription_view.dart index c5b3bb506..b48ab2fcf 100644 --- a/lib/pangea/subscription/pages/settings_subscription_view.dart +++ b/lib/pangea/subscription/pages/settings_subscription_view.dart @@ -16,6 +16,8 @@ class SettingsSubscriptionView extends StatelessWidget { @override Widget build(BuildContext context) { + final clickedCancelDate = + SubscriptionManagementRepo.getClickedCancelSubscription(); final List managementButtons = [ if (controller.currentSubscriptionAvailable) ListTile( @@ -70,7 +72,8 @@ class SettingsSubscriptionView extends StatelessWidget { ), ), ), - if (SubscriptionManagementRepo.getClickedCancelSubscription()) + if (clickedCancelDate != null && + DateTime.now().difference(clickedCancelDate).inMinutes < 10) Padding( padding: const EdgeInsets.all(16.0), child: Row( diff --git a/lib/pangea/subscription/repo/subscription_management_repo.dart b/lib/pangea/subscription/repo/subscription_management_repo.dart index f0b96a678..673a1103b 100644 --- a/lib/pangea/subscription/repo/subscription_management_repo.dart +++ b/lib/pangea/subscription/repo/subscription_management_repo.dart @@ -77,14 +77,26 @@ class SubscriptionManagementRepo { ); } - static bool getClickedCancelSubscription() { + static DateTime? getClickedCancelSubscription() { final entry = _cache.read(PLocalKey.clickedCancelSubscription); - if (entry == null) return false; - final val = DateTime.tryParse(entry); - return val != null && DateTime.now().difference(val).inSeconds < 60; + if (entry == null) return null; + return DateTime.tryParse(entry); } static Future removeClickedCancelSubscription() async { await _cache.remove(PLocalKey.clickedCancelSubscription); } + + static Future setSubscriptionEndDate(DateTime? date) async { + await _cache.write( + PLocalKey.subscriptionEndDate, + date?.toIso8601String(), + ); + } + + static DateTime? getSubscriptionEndDate() { + final entry = _cache.read(PLocalKey.subscriptionEndDate); + if (entry == null) return null; + return DateTime.tryParse(entry); + } }