From c0f33de0c821f0e5f66993be9c669b3e85cd57b2 Mon Sep 17 00:00:00 2001 From: vishnukvmd Date: Wed, 13 Mar 2024 21:56:09 +0530 Subject: [PATCH] Remove dead code --- mobile/lib/services/push_service.dart | 103 --- .../ui/payment/store_subscription_page.dart | 603 ------------------ mobile/lib/ui/payment/subscription.dart | 23 +- 3 files changed, 1 insertion(+), 728 deletions(-) delete mode 100644 mobile/lib/services/push_service.dart delete mode 100644 mobile/lib/ui/payment/store_subscription_page.dart diff --git a/mobile/lib/services/push_service.dart b/mobile/lib/services/push_service.dart deleted file mode 100644 index 4ddd92c74..000000000 --- a/mobile/lib/services/push_service.dart +++ /dev/null @@ -1,103 +0,0 @@ -import 'package:firebase_core/firebase_core.dart'; -import 'package:firebase_messaging/firebase_messaging.dart'; -import 'package:logging/logging.dart'; -import 'package:photos/core/configuration.dart'; -import 'package:photos/core/constants.dart'; -import 'package:photos/core/event_bus.dart'; -import 'package:photos/core/network/network.dart'; -import 'package:photos/events/signed_in_event.dart'; -import 'package:photos/services/sync_service.dart'; -import 'package:shared_preferences/shared_preferences.dart'; - -class PushService { - static const kFCMPushToken = "fcm_push_token"; - static const kLastFCMTokenUpdationTime = "fcm_push_token_updation_time"; - static const kFCMTokenUpdationIntervalInMicroSeconds = 30 * microSecondsInDay; - static const kPushAction = "action"; - static const kSync = "sync"; - - static final PushService instance = PushService._privateConstructor(); - static final _logger = Logger("PushService"); - - late SharedPreferences _prefs; - - PushService._privateConstructor(); - - Future init() async { - _prefs = await SharedPreferences.getInstance(); - await Firebase.initializeApp(); - FirebaseMessaging.onMessage.listen((RemoteMessage message) { - _logger.info("Got a message whilst in the foreground!"); - _handleForegroundPushMessage(message); - }); - try { - if (Configuration.instance.hasConfiguredAccount()) { - await _configurePushToken(); - } else { - Bus.instance.on().listen((_) async { - // ignore: unawaited_futures - _configurePushToken(); - }); - } - } catch (e, s) { - _logger.severe("Could not configure push token", e, s); - } - } - - Future _configurePushToken() async { - final String? fcmToken = await FirebaseMessaging.instance.getToken(); - final shouldForceRefreshServerToken = - DateTime.now().microsecondsSinceEpoch - - (_prefs.getInt(kLastFCMTokenUpdationTime) ?? 0) > - kFCMTokenUpdationIntervalInMicroSeconds; - if (fcmToken != null && - (_prefs.getString(kFCMPushToken) != fcmToken || - shouldForceRefreshServerToken)) { - final String? apnsToken = await FirebaseMessaging.instance.getAPNSToken(); - try { - _logger.info("Updating token on server"); - await _setPushTokenOnServer(fcmToken, apnsToken); - await _prefs.setString(kFCMPushToken, fcmToken); - await _prefs.setInt( - kLastFCMTokenUpdationTime, - DateTime.now().microsecondsSinceEpoch, - ); - _logger.info("Push token updated on server"); - } catch (e) { - _logger.severe("Could not set push token", e, StackTrace.current); - } - } else { - _logger.info("Skipping token update"); - } - } - - Future _setPushTokenOnServer( - String fcmToken, - String? apnsToken, - ) async { - await NetworkClient.instance.enteDio.post( - "/push/token", - data: { - "fcmToken": fcmToken, - "apnsToken": apnsToken, - }, - ); - } - - void _handleForegroundPushMessage(RemoteMessage message) { - _logger.info("Message data: ${message.data}"); - if (message.notification != null) { - _logger.info( - "Message also contained a notification: ${message.notification}", - ); - } - if (shouldSync(message)) { - SyncService.instance.sync(); - } - } - - static bool shouldSync(RemoteMessage message) { - return message.data.containsKey(kPushAction) && - message.data[kPushAction] == kSync; - } -} diff --git a/mobile/lib/ui/payment/store_subscription_page.dart b/mobile/lib/ui/payment/store_subscription_page.dart deleted file mode 100644 index 4bcdd4d5b..000000000 --- a/mobile/lib/ui/payment/store_subscription_page.dart +++ /dev/null @@ -1,603 +0,0 @@ -import 'dart:async'; -import 'dart:io'; - -import "package:flutter/foundation.dart"; -import 'package:flutter/material.dart'; -import 'package:in_app_purchase/in_app_purchase.dart'; -import 'package:logging/logging.dart'; -import 'package:photos/core/errors.dart'; -import 'package:photos/core/event_bus.dart'; -import 'package:photos/events/subscription_purchased_event.dart'; -import "package:photos/generated/l10n.dart"; -import 'package:photos/models/billing_plan.dart'; -import 'package:photos/models/subscription.dart'; -import 'package:photos/models/user_details.dart'; -import 'package:photos/services/billing_service.dart'; -import "package:photos/services/update_service.dart"; -import 'package:photos/services/user_service.dart'; -import "package:photos/theme/colors.dart"; -import "package:photos/theme/ente_theme.dart"; -import 'package:photos/ui/common/loading_widget.dart'; -import 'package:photos/ui/common/progress_dialog.dart'; -import "package:photos/ui/components/captioned_text_widget.dart"; -import "package:photos/ui/components/menu_item_widget/menu_item_widget.dart"; -import 'package:photos/ui/payment/child_subscription_widget.dart'; -import 'package:photos/ui/payment/skip_subscription_widget.dart'; -import 'package:photos/ui/payment/subscription_common_widgets.dart'; -import 'package:photos/ui/payment/subscription_plan_widget.dart'; -import "package:photos/ui/payment/view_add_on_widget.dart"; -import "package:photos/utils/data_util.dart"; -import 'package:photos/utils/dialog_util.dart'; -import 'package:photos/utils/toast_util.dart'; -import 'package:url_launcher/url_launcher_string.dart'; - -class StoreSubscriptionPage extends StatefulWidget { - final bool isOnboarding; - - const StoreSubscriptionPage({ - this.isOnboarding = false, - Key? key, - }) : super(key: key); - - @override - State createState() => _StoreSubscriptionPageState(); -} - -class _StoreSubscriptionPageState extends State { - final _logger = Logger("SubscriptionPage"); - final _billingService = BillingService.instance; - final _userService = UserService.instance; - Subscription? _currentSubscription; - late StreamSubscription _purchaseUpdateSubscription; - late ProgressDialog _dialog; - late UserDetails _userDetails; - late bool _hasActiveSubscription; - bool _hideCurrentPlanSelection = false; - late FreePlan _freePlan; - late List _plans; - bool _hasLoadedData = false; - bool _isLoading = false; - late bool _isActiveStripeSubscriber; - EnteColorScheme colorScheme = darkScheme; - - // hasYearlyPlans is used to check if there are yearly plans for given store - bool hasYearlyPlans = false; - - // _showYearlyPlan is used to determine if we should show the yearly plans - bool showYearlyPlan = false; - - @override - void initState() { - _billingService.setIsOnSubscriptionPage(true); - _setupPurchaseUpdateStreamListener(); - super.initState(); - } - - void _setupPurchaseUpdateStreamListener() { - _purchaseUpdateSubscription = - InAppPurchase.instance.purchaseStream.listen((purchases) async { - if (!_dialog.isShowing()) { - await _dialog.show(); - } - for (final purchase in purchases) { - _logger.info("Purchase status " + purchase.status.toString()); - if (purchase.status == PurchaseStatus.purchased) { - try { - final newSubscription = await _billingService.verifySubscription( - purchase.productID, - purchase.verificationData.serverVerificationData, - ); - await InAppPurchase.instance.completePurchase(purchase); - String text = S.of(context).thankYouForSubscribing; - if (!widget.isOnboarding) { - final isUpgrade = _hasActiveSubscription && - newSubscription.storage > _currentSubscription!.storage; - final isDowngrade = _hasActiveSubscription && - newSubscription.storage < _currentSubscription!.storage; - if (isUpgrade) { - text = S.of(context).yourPlanWasSuccessfullyUpgraded; - } else if (isDowngrade) { - text = S.of(context).yourPlanWasSuccessfullyDowngraded; - } - } - showShortToast(context, text); - _currentSubscription = newSubscription; - _hasActiveSubscription = _currentSubscription!.isValid(); - setState(() {}); - await _dialog.hide(); - Bus.instance.fire(SubscriptionPurchasedEvent()); - if (widget.isOnboarding) { - Navigator.of(context).popUntil((route) => route.isFirst); - } - } on SubscriptionAlreadyClaimedError catch (e) { - _logger.warning("subscription is already claimed ", e); - await _dialog.hide(); - final String title = Platform.isAndroid - ? S.of(context).playstoreSubscription - : S.of(context).appstoreSubscription; - final String id = Platform.isAndroid - ? S.of(context).googlePlayId - : S.of(context).appleId; - final String message = S.of(context).subAlreadyLinkedErrMessage(id); - // ignore: unawaited_futures - showErrorDialog(context, title, message); - return; - } catch (e) { - _logger.warning("Could not complete payment ", e); - await _dialog.hide(); - // ignore: unawaited_futures - showErrorDialog( - context, - S.of(context).paymentFailed, - S.of(context).paymentFailedTalkToProvider( - Platform.isAndroid ? "PlayStore" : "AppStore", - ), - ); - return; - } - } else if (Platform.isIOS && purchase.pendingCompletePurchase) { - await InAppPurchase.instance.completePurchase(purchase); - await _dialog.hide(); - } else if (purchase.status == PurchaseStatus.error) { - await _dialog.hide(); - } - } - }); - } - - @override - void dispose() { - _purchaseUpdateSubscription.cancel(); - _billingService.setIsOnSubscriptionPage(false); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - colorScheme = getEnteColorScheme(context); - if (!_isLoading) { - _isLoading = true; - _fetchSubData(); - } - _dialog = createProgressDialog(context, S.of(context).pleaseWait); - final appBar = AppBar( - title: widget.isOnboarding - ? null - : Text("${S.of(context).subscription}${kDebugMode ? ' Store' : ''}"), - ); - return Scaffold( - appBar: appBar, - body: _getBody(), - ); - } - - bool _isFreePlanUser() { - return _currentSubscription != null && - freeProductID == _currentSubscription!.productID; - } - - Future _fetchSubData() async { - // ignore: unawaited_futures - _userService.getUserDetailsV2(memoryCount: false).then((userDetails) async { - _userDetails = userDetails; - _currentSubscription = userDetails.subscription; - - _hasActiveSubscription = _currentSubscription!.isValid(); - _hideCurrentPlanSelection = - _currentSubscription?.attributes?.isCancelled ?? false; - showYearlyPlan = _currentSubscription!.isYearlyPlan(); - final billingPlans = await _billingService.getBillingPlans(); - _isActiveStripeSubscriber = - _currentSubscription!.paymentProvider == stripe && - _currentSubscription!.isValid(); - _plans = billingPlans.plans.where((plan) { - final productID = _isActiveStripeSubscriber - ? plan.stripeID - : Platform.isAndroid - ? plan.androidID - : plan.iosID; - return productID.isNotEmpty; - }).toList(); - hasYearlyPlans = _plans.any((plan) => plan.period == 'year'); - if (showYearlyPlan && hasYearlyPlans) { - _plans = _plans.where((plan) => plan.period == 'year').toList(); - } else { - _plans = _plans.where((plan) => plan.period != 'year').toList(); - } - _freePlan = billingPlans.freePlan; - _hasLoadedData = true; - if (mounted) { - setState(() {}); - } - }); - } - - Widget _getBody() { - if (_hasLoadedData) { - if (_userDetails.isPartOfFamily() && !_userDetails.isFamilyAdmin()) { - return ChildSubscriptionWidget(userDetails: _userDetails); - } else { - return _buildPlans(); - } - } - return const EnteLoadingWidget(); - } - - Widget _buildPlans() { - final widgets = []; - widgets.add( - SubscriptionHeaderWidget( - isOnboarding: widget.isOnboarding, - currentUsage: _userDetails.getFamilyOrPersonalUsage(), - ), - ); - - widgets.addAll([ - Column( - mainAxisAlignment: MainAxisAlignment.center, - children: _isActiveStripeSubscriber - ? _getStripePlanWidgets() - : _getMobilePlanWidgets(), - ), - const Padding(padding: EdgeInsets.all(8)), - ]); - - if (hasYearlyPlans) { - widgets.add(_showSubscriptionToggle()); - } - - if (_currentSubscription != null) { - widgets.add( - ValidityWidget( - currentSubscription: _currentSubscription, - bonusData: _userDetails.bonusData, - ), - ); - } - - if (_currentSubscription!.productID == freeProductID) { - if (widget.isOnboarding) { - widgets.add(SkipSubscriptionWidget(freePlan: _freePlan)); - } - widgets.add( - SubFaqWidget(isOnboarding: widget.isOnboarding), - ); - } - - if (_hasActiveSubscription && - _currentSubscription!.productID != freeProductID) { - if (_isActiveStripeSubscriber) { - widgets.add( - Padding( - padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 20), - child: Text( - S.of(context).visitWebToManage, - style: getEnteTextTheme(context).small.copyWith( - color: colorScheme.textMuted, - ), - ), - ), - ); - } else { - widgets.add( - Padding( - padding: const EdgeInsets.fromLTRB(16, 40, 16, 4), - child: MenuItemWidget( - captionedTextWidget: CaptionedTextWidget( - title: S.of(context).paymentDetails, - ), - menuItemColor: colorScheme.fillFaint, - trailingWidget: Icon( - Icons.chevron_right_outlined, - color: colorScheme.strokeBase, - ), - singleBorderRadius: 4, - alignCaptionedTextToLeft: true, - onTap: () async { - _onPlatformRestrictedPaymentDetailsClick(); - }, - ), - ), - ); - } - } - if (!widget.isOnboarding) { - widgets.add( - Padding( - padding: const EdgeInsets.fromLTRB(16, 0, 16, 0), - child: MenuItemWidget( - captionedTextWidget: CaptionedTextWidget( - title: _isFreePlanUser() - ? S.of(context).familyPlans - : S.of(context).manageFamily, - ), - menuItemColor: colorScheme.fillFaint, - trailingWidget: Icon( - Icons.chevron_right_outlined, - color: colorScheme.strokeBase, - ), - singleBorderRadius: 4, - alignCaptionedTextToLeft: true, - onTap: () async { - unawaited( - _billingService.launchFamilyPortal(context, _userDetails), - ); - }, - ), - ), - ); - widgets.add(ViewAddOnButton(_userDetails.bonusData)); - widgets.add(const SizedBox(height: 80)); - } - return SingleChildScrollView( - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: widgets, - ), - ); - } - - void _onPlatformRestrictedPaymentDetailsClick() { - final String paymentProvider = _currentSubscription!.paymentProvider; - if (paymentProvider == appStore && !Platform.isAndroid) { - launchUrlString("https://apps.apple.com/account/billing"); - } else if (paymentProvider == playStore && Platform.isAndroid) { - launchUrlString( - "https://play.google.com/store/account/subscriptions?sku=" + - _currentSubscription!.productID + - "&package=io.ente.photos", - ); - } else if (paymentProvider == stripe) { - showErrorDialog( - context, - S.of(context).sorry, - S.of(context).visitWebToManage, - ); - } else { - final String capitalizedWord = paymentProvider.isNotEmpty - ? '${paymentProvider[0].toUpperCase()}${paymentProvider.substring(1).toLowerCase()}' - : ''; - showErrorDialog( - context, - S.of(context).sorry, - S.of(context).contactToManageSubscription(capitalizedWord), - ); - } - } - - Future _filterStorePlansForUi() async { - final billingPlans = await _billingService.getBillingPlans(); - _plans = billingPlans.plans.where((plan) { - final productID = _isActiveStripeSubscriber - ? plan.stripeID - : Platform.isAndroid - ? plan.androidID - : plan.iosID; - return productID.isNotEmpty; - }).toList(); - hasYearlyPlans = _plans.any((plan) => plan.period == 'year'); - if (showYearlyPlan) { - _plans = _plans.where((plan) => plan.period == 'year').toList(); - } else { - _plans = _plans.where((plan) => plan.period != 'year').toList(); - } - setState(() {}); - } - - Widget _showSubscriptionToggle() { - Widget planText(String title, bool reduceOpacity) { - return Padding( - padding: const EdgeInsets.only(left: 4, right: 4), - child: Text( - title, - style: TextStyle( - color: Theme.of(context) - .colorScheme - .onSurface - .withOpacity(reduceOpacity ? 0.5 : 1.0), - ), - ), - ); - } - - return Container( - padding: const EdgeInsets.only(left: 8, right: 8, top: 2, bottom: 2), - margin: const EdgeInsets.only(bottom: 6), - child: Column( - children: [ - RepaintBoundary( - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - planText(S.of(context).monthly, showYearlyPlan), - Switch( - value: showYearlyPlan, - activeColor: Colors.white, - inactiveThumbColor: Colors.white, - activeTrackColor: getEnteColorScheme(context).strokeMuted, - onChanged: (value) async { - showYearlyPlan = value; - await _filterStorePlansForUi(); - }, - ), - planText(S.of(context).yearly, !showYearlyPlan), - ], - ), - ), - _isFreePlanUser() && !UpdateService.instance.isPlayStoreFlavor() - ? Text( - S.of(context).twoMonthsFreeOnYearlyPlans, - style: getEnteTextTheme(context).miniMuted, - ) - : const SizedBox.shrink(), - const Padding(padding: EdgeInsets.all(8)), - ], - ), - ); - } - - List _getStripePlanWidgets() { - final List planWidgets = []; - bool foundActivePlan = false; - for (final plan in _plans) { - final productID = plan.stripeID; - if (productID.isEmpty) { - continue; - } - final isActive = _hasActiveSubscription && - _currentSubscription!.productID == productID; - if (isActive) { - foundActivePlan = true; - } - planWidgets.add( - Material( - color: Colors.transparent, - child: InkWell( - onTap: () async { - if (isActive) { - return; - } - // ignore: unawaited_futures - showErrorDialog( - context, - S.of(context).sorry, - S.of(context).visitWebToManage, - ); - }, - child: SubscriptionPlanWidget( - storage: plan.storage, - price: plan.price, - period: plan.period, - isActive: isActive && !_hideCurrentPlanSelection, - ), - ), - ), - ); - } - if (!foundActivePlan && _hasActiveSubscription) { - _addCurrentPlanWidget(planWidgets); - } - return planWidgets; - } - - List _getMobilePlanWidgets() { - bool foundActivePlan = false; - final List planWidgets = []; - if (_hasActiveSubscription && - _currentSubscription!.productID == freeProductID) { - foundActivePlan = true; - planWidgets.add( - SubscriptionPlanWidget( - storage: _freePlan.storage, - price: S.of(context).freeTrial, - period: "", - isActive: true, - ), - ); - } - for (final plan in _plans) { - final productID = Platform.isAndroid ? plan.androidID : plan.iosID; - final isActive = _hasActiveSubscription && - _currentSubscription!.productID == productID; - if (isActive) { - foundActivePlan = true; - } - planWidgets.add( - Material( - child: InkWell( - onTap: () async { - if (isActive) { - return; - } - final int addOnBonus = - _userDetails.bonusData?.totalAddOnBonus() ?? 0; - if (_userDetails.getFamilyOrPersonalUsage() > - (plan.storage + addOnBonus)) { - _logger.warning( - " familyUsage ${convertBytesToReadableFormat(_userDetails.getFamilyOrPersonalUsage())}" - " plan storage ${convertBytesToReadableFormat(plan.storage)} " - "addOnBonus ${convertBytesToReadableFormat(addOnBonus)}," - "overshooting by ${convertBytesToReadableFormat(_userDetails.getFamilyOrPersonalUsage() - (plan.storage + addOnBonus))}", - ); - // ignore: unawaited_futures - showErrorDialog( - context, - S.of(context).sorry, - S.of(context).youCannotDowngradeToThisPlan, - ); - return; - } - await _dialog.show(); - final ProductDetailsResponse response = - await InAppPurchase.instance.queryProductDetails({productID}); - if (response.notFoundIDs.isNotEmpty) { - final errMsg = "Could not find products: " + - response.notFoundIDs.toString(); - _logger.severe(errMsg); - await _dialog.hide(); - await showGenericErrorDialog( - context: context, - error: Exception(errMsg), - ); - return; - } - final isCrossGradingOnAndroid = Platform.isAndroid && - _hasActiveSubscription && - _currentSubscription!.productID != freeProductID && - _currentSubscription!.productID != plan.androidID; - if (isCrossGradingOnAndroid) { - await _dialog.hide(); - // ignore: unawaited_futures - showErrorDialog( - context, - S.of(context).couldNotUpdateSubscription, - S.of(context).pleaseContactSupportAndWeWillBeHappyToHelp, - ); - return; - } else { - await InAppPurchase.instance.buyNonConsumable( - purchaseParam: PurchaseParam( - productDetails: response.productDetails[0], - ), - ); - } - }, - child: SubscriptionPlanWidget( - storage: plan.storage, - price: plan.price, - period: plan.period, - isActive: isActive, - ), - ), - ), - ); - } - if (!foundActivePlan && _hasActiveSubscription) { - _addCurrentPlanWidget(planWidgets); - } - return planWidgets; - } - - void _addCurrentPlanWidget(List planWidgets) { - int activePlanIndex = 0; - for (; activePlanIndex < _plans.length; activePlanIndex++) { - if (_plans[activePlanIndex].storage > _currentSubscription!.storage) { - break; - } - } - planWidgets.insert( - activePlanIndex, - Material( - child: InkWell( - onTap: () {}, - child: SubscriptionPlanWidget( - storage: _currentSubscription!.storage, - price: _currentSubscription!.price, - period: _currentSubscription!.period, - isActive: true, - ), - ), - ), - ); - } -} diff --git a/mobile/lib/ui/payment/subscription.dart b/mobile/lib/ui/payment/subscription.dart index 8810cb476..6da7091fc 100644 --- a/mobile/lib/ui/payment/subscription.dart +++ b/mobile/lib/ui/payment/subscription.dart @@ -1,27 +1,6 @@ import 'package:flutter/cupertino.dart'; -import 'package:photos/core/configuration.dart'; -import 'package:photos/services/feature_flag_service.dart'; -import 'package:photos/services/update_service.dart'; -import "package:photos/ui/payment/store_subscription_page.dart"; import 'package:photos/ui/payment/stripe_subscription_page.dart'; StatefulWidget getSubscriptionPage({bool isOnBoarding = false}) { - if (UpdateService.instance.isIndependentFlavor() || - UpdateService.instance.isFdroidFlavor()) { - return StripeSubscriptionPage(isOnboarding: isOnBoarding); - } - if (FeatureFlagService.instance.enableStripe() && - _isUserCreatedPostStripeSupport()) { - return StripeSubscriptionPage(isOnboarding: isOnBoarding); - } else { - return StoreSubscriptionPage(isOnboarding: isOnBoarding); - } -} - -// return true if the user was created after we added support for stripe payment -// on frame. We do this check to avoid showing Stripe payment option for earlier -// users who might have paid via playStore. This method should be removed once -// we have better handling for active play/app store subscription & stripe plans. -bool _isUserCreatedPostStripeSupport() { - return Configuration.instance.getUserID()! > 1580559962386460; + return StripeSubscriptionPage(isOnboarding: isOnBoarding); }