瀏覽代碼

Update Subscription UX based on add on pack (#1527)

Neeraj Gupta 1 年之前
父節點
當前提交
2a978bc9a4

+ 9 - 5
lib/generated/intl/messages_en.dart

@@ -23,6 +23,9 @@ class MessageLookup extends MessageLookupByLibrary {
   static String m0(count) =>
       "${Intl.plural(count, one: 'Add item', other: 'Add items')}";
 
+  static String m64(storageAmount, endDate) =>
+      "Your ${storageAmount} add-on is valid till ${endDate}";
+
   static String m1(emailOrName) => "Added by ${emailOrName}";
 
   static String m2(albumName) => "Added successfully to  ${albumName}";
@@ -135,9 +138,9 @@ class MessageLookup extends MessageLookupByLibrary {
   static String m40(userEmail) =>
       "${userEmail} will be removed from this shared album\n\nAny photos added by them will also be removed from the album";
 
-  static String m41(endDate) => "Renews on ${endDate}";
+  static String m41(endDate) => "Subscription renews on ${endDate}";
 
-  static String m64(count) =>
+  static String m65(count) =>
       "${Intl.plural(count, one: '${count} result found', other: '${count} results found')}";
 
   static String m42(count) => "${count} selected";
@@ -190,7 +193,7 @@ class MessageLookup extends MessageLookupByLibrary {
   static String m59(count) =>
       "${Intl.plural(count, zero: '', one: '1 day', other: '${count} days')}";
 
-  static String m65(endDate) => "Valid till ${endDate}";
+  static String m66(endDate) => "Valid till ${endDate}";
 
   static String m60(email) => "Verify ${email}";
 
@@ -226,6 +229,7 @@ class MessageLookup extends MessageLookupByLibrary {
         "addNew": MessageLookupByLibrary.simpleMessage("Add new"),
         "addOnPageSubtitle":
             MessageLookupByLibrary.simpleMessage("Details of add-ons"),
+        "addOnValidTill": m64,
         "addOns": MessageLookupByLibrary.simpleMessage("Add-ons"),
         "addPhotos": MessageLookupByLibrary.simpleMessage("Add photos"),
         "addSelected": MessageLookupByLibrary.simpleMessage("Add selected"),
@@ -1132,7 +1136,7 @@ class MessageLookup extends MessageLookupByLibrary {
             "Group photos that are taken within some radius of a photo"),
         "searchPeopleEmptySection": MessageLookupByLibrary.simpleMessage(
             "Invite people, and you\'ll see all photos shared by them here"),
-        "searchResultCount": m64,
+        "searchResultCount": m65,
         "security": MessageLookupByLibrary.simpleMessage("Security"),
         "selectAlbum": MessageLookupByLibrary.simpleMessage("Select album"),
         "selectAll": MessageLookupByLibrary.simpleMessage("Select all"),
@@ -1381,7 +1385,7 @@ class MessageLookup extends MessageLookupByLibrary {
         "useSelectedPhoto":
             MessageLookupByLibrary.simpleMessage("Use selected photo"),
         "usedSpace": MessageLookupByLibrary.simpleMessage("Used space"),
-        "validTill": m65,
+        "validTill": m66,
         "verificationFailedPleaseTryAgain":
             MessageLookupByLibrary.simpleMessage(
                 "Verification failed, please try again"),

+ 4 - 4
lib/generated/intl/messages_fr.dart

@@ -140,7 +140,7 @@ class MessageLookup extends MessageLookupByLibrary {
 
   static String m41(endDate) => "Renouvellement le ${endDate}";
 
-  static String m64(count) =>
+  static String m65(count) =>
       "${Intl.plural(count, one: '${count} résultat trouvé', other: '${count} résultats trouvés')}";
 
   static String m42(count) => "${count} sélectionné(s)";
@@ -192,7 +192,7 @@ class MessageLookup extends MessageLookupByLibrary {
   static String m59(count) =>
       "${Intl.plural(count, zero: '0 jour', one: '1 jour', other: '${count} jours')}";
 
-  static String m65(endDate) => "Valable jusqu\'au ${endDate}";
+  static String m66(endDate) => "Valable jusqu\'au ${endDate}";
 
   static String m60(email) => "Vérifier ${email}";
 
@@ -1193,7 +1193,7 @@ class MessageLookup extends MessageLookupByLibrary {
             "Grouper les photos qui sont prises dans un certain angle d\'une photo"),
         "searchPeopleEmptySection": MessageLookupByLibrary.simpleMessage(
             "Invitez des gens, et vous verrez ici toutes les photos qu\'ils partagent"),
-        "searchResultCount": m64,
+        "searchResultCount": m65,
         "security": MessageLookupByLibrary.simpleMessage("Sécurité"),
         "selectAlbum":
             MessageLookupByLibrary.simpleMessage("Sélectionner album"),
@@ -1463,7 +1463,7 @@ class MessageLookup extends MessageLookupByLibrary {
         "useSelectedPhoto": MessageLookupByLibrary.simpleMessage(
             "Utiliser la photo sélectionnée"),
         "usedSpace": MessageLookupByLibrary.simpleMessage("Mémoire utilisée"),
-        "validTill": m65,
+        "validTill": m66,
         "verificationFailedPleaseTryAgain":
             MessageLookupByLibrary.simpleMessage(
                 "La vérification a échouée, veuillez réessayer"),

+ 2 - 2
lib/generated/intl/messages_it.dart

@@ -187,7 +187,7 @@ class MessageLookup extends MessageLookupByLibrary {
   static String m59(count) =>
       "${Intl.plural(count, zero: '', one: '1 giorno', other: '${count} giorni')}";
 
-  static String m65(endDate) => "Valido fino al ${endDate}";
+  static String m66(endDate) => "Valido fino al ${endDate}";
 
   static String m60(email) => "Verifica ${email}";
 
@@ -1391,7 +1391,7 @@ class MessageLookup extends MessageLookupByLibrary {
         "useSelectedPhoto":
             MessageLookupByLibrary.simpleMessage("Usa la foto selezionata"),
         "usedSpace": MessageLookupByLibrary.simpleMessage("Spazio utilizzato"),
-        "validTill": m65,
+        "validTill": m66,
         "verificationFailedPleaseTryAgain":
             MessageLookupByLibrary.simpleMessage(
                 "Verifica fallita, per favore prova di nuovo"),

+ 7 - 4
lib/generated/intl/messages_zh.dart

@@ -127,7 +127,7 @@ class MessageLookup extends MessageLookupByLibrary {
 
   static String m41(endDate) => "在 ${endDate} 前续费";
 
-  static String m64(count) =>
+  static String m65(count) =>
       "${Intl.plural(count, other: '已找到 ${count} 个结果')}";
 
   static String m42(count) => "已选择 ${count} 个";
@@ -173,7 +173,7 @@ class MessageLookup extends MessageLookupByLibrary {
   static String m59(count) =>
       "${Intl.plural(count, zero: '', one: '1天', other: '${count} 天')}";
 
-  static String m65(endDate) => "有效期至 ${endDate}";
+  static String m66(endDate) => "有效期至 ${endDate}";
 
   static String m60(email) => "验证 ${email}";
 
@@ -749,6 +749,7 @@ class MessageLookup extends MessageLookupByLibrary {
             MessageLookupByLibrary.simpleMessage("没有隐藏的照片或视频"),
         "noImagesWithLocation":
             MessageLookupByLibrary.simpleMessage("没有带有位置的图像"),
+        "noInternetConnection": MessageLookupByLibrary.simpleMessage("无互联网连接"),
         "noPhotosAreBeingBackedUpRightNow":
             MessageLookupByLibrary.simpleMessage("目前没有照片正在备份"),
         "noPhotosFoundHere": MessageLookupByLibrary.simpleMessage("这里没有找到照片"),
@@ -807,6 +808,8 @@ class MessageLookup extends MessageLookupByLibrary {
         "playStoreFreeTrialValidTill": m35,
         "playstoreSubscription":
             MessageLookupByLibrary.simpleMessage("PlayStore 订阅"),
+        "pleaseCheckYourInternetConnectionAndTryAgain":
+            MessageLookupByLibrary.simpleMessage("请检查您的互联网连接,然后重试。"),
         "pleaseContactSupportAndWeWillBeHappyToHelp":
             MessageLookupByLibrary.simpleMessage(
                 "请用英语联系 support@ente.io ,我们将乐意提供帮助!"),
@@ -944,7 +947,7 @@ class MessageLookup extends MessageLookupByLibrary {
             MessageLookupByLibrary.simpleMessage("在照片的一定半径内拍摄的几组照片"),
         "searchPeopleEmptySection":
             MessageLookupByLibrary.simpleMessage("邀请他人,您将在此看到他们分享的所有照片"),
-        "searchResultCount": m64,
+        "searchResultCount": m65,
         "security": MessageLookupByLibrary.simpleMessage("安全"),
         "selectAlbum": MessageLookupByLibrary.simpleMessage("选择相册"),
         "selectAll": MessageLookupByLibrary.simpleMessage("全选"),
@@ -1155,7 +1158,7 @@ class MessageLookup extends MessageLookupByLibrary {
         "useRecoveryKey": MessageLookupByLibrary.simpleMessage("使用恢复密钥"),
         "useSelectedPhoto": MessageLookupByLibrary.simpleMessage("使用所选照片"),
         "usedSpace": MessageLookupByLibrary.simpleMessage("已用空间"),
-        "validTill": m65,
+        "validTill": m66,
         "verificationFailedPleaseTryAgain":
             MessageLookupByLibrary.simpleMessage("验证失败,请重试"),
         "verificationId": MessageLookupByLibrary.simpleMessage("验证 ID"),

+ 12 - 2
lib/generated/l10n.dart

@@ -3894,10 +3894,10 @@ class S {
     );
   }
 
-  /// `Renews on {endDate}`
+  /// `Subscription renews on {endDate}`
   String renewsOn(Object endDate) {
     return Intl.message(
-      'Renews on $endDate',
+      'Subscription renews on $endDate',
       name: 'renewsOn',
       desc: '',
       args: [endDate],
@@ -3924,6 +3924,16 @@ class S {
     );
   }
 
+  /// `Your {storageAmount} add-on is valid till {endDate}`
+  String addOnValidTill(Object storageAmount, Object endDate) {
+    return Intl.message(
+      'Your $storageAmount add-on is valid till $endDate',
+      name: 'addOnValidTill',
+      desc: '',
+      args: [storageAmount, endDate],
+    );
+  }
+
   /// `Free trial valid till {endDate}.\nYou can choose a paid plan afterwards.`
   String playStoreFreeTrialValidTill(Object endDate) {
     return Intl.message(

+ 2 - 1
lib/l10n/intl_en.arb

@@ -555,9 +555,10 @@
     "type": "text"
   },
   "faqs": "FAQs",
-  "renewsOn": "Renews on {endDate}",
+  "renewsOn": "Subscription renews on {endDate}",
   "freeTrialValidTill": "Free trial valid till {endDate}",
   "validTill": "Valid till {endDate}",
+  "addOnValidTill": "Your {storageAmount} add-on is valid till {endDate}",
   "playStoreFreeTrialValidTill": "Free trial valid till {endDate}.\nYou can choose a paid plan afterwards.",
   "subWillBeCancelledOn": "Your subscription will be cancelled on {endDate}",
   "subscription": "Subscription",

+ 6 - 2
lib/ui/payment/store_subscription_page.dart

@@ -52,6 +52,7 @@ class _StoreSubscriptionPageState extends State<StoreSubscriptionPage> {
   late ProgressDialog _dialog;
   late UserDetails _userDetails;
   late bool _hasActiveSubscription;
+  bool _hideCurrentPlanSelection = false;
   late FreePlan _freePlan;
   late List<BillingPlan> _plans;
   bool _hasLoadedData = false;
@@ -177,7 +178,10 @@ class _StoreSubscriptionPageState extends State<StoreSubscriptionPage> {
     _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 =
@@ -239,7 +243,7 @@ class _StoreSubscriptionPageState extends State<StoreSubscriptionPage> {
       widgets.add(_showSubscriptionToggle());
     }
 
-    if (_hasActiveSubscription) {
+    if (_currentSubscription != null) {
       widgets.add(
         ValidityWidget(
           currentSubscription: _currentSubscription,
@@ -458,7 +462,7 @@ class _StoreSubscriptionPageState extends State<StoreSubscriptionPage> {
               storage: plan.storage,
               price: plan.price,
               period: plan.period,
-              isActive: isActive,
+              isActive: isActive && !_hideCurrentPlanSelection,
             ),
           ),
         ),

+ 11 - 3
lib/ui/payment/stripe_subscription_page.dart

@@ -53,6 +53,7 @@ class _StripeSubscriptionPageState extends State<StripeSubscriptionPage> {
 
   // indicates if user's subscription plan is still active
   late bool _hasActiveSubscription;
+  bool _hideCurrentPlanSelection = false;
   late FreePlan _freePlan;
   List<BillingPlan> _plans = [];
   bool _hasLoadedData = false;
@@ -73,7 +74,11 @@ class _StripeSubscriptionPageState extends State<StripeSubscriptionPage> {
         .then((userDetails) async {
       _userDetails = userDetails;
       _currentSubscription = userDetails.subscription;
+
       _showYearlyPlan = _currentSubscription!.isYearlyPlan();
+      _hideCurrentPlanSelection =
+          (_currentSubscription?.attributes?.isCancelled ?? false) &&
+              userDetails.hasPaidAddon();
       _hasActiveSubscription = _currentSubscription!.isValid();
       _isStripeSubscriber = _currentSubscription!.paymentProvider == stripe;
       return _filterStripeForUI().then((value) {
@@ -210,7 +215,7 @@ class _StripeSubscriptionPageState extends State<StripeSubscriptionPage> {
 
     widgets.add(_showSubscriptionToggle());
 
-    if (_hasActiveSubscription) {
+    if (_currentSubscription != null) {
       widgets.add(
         ValidityWidget(
           currentSubscription: _currentSubscription,
@@ -340,6 +345,9 @@ class _StripeSubscriptionPageState extends State<StripeSubscriptionPage> {
   Widget _stripeRenewOrCancelButton() {
     final bool isRenewCancelled =
         _currentSubscription!.attributes?.isCancelled ?? false;
+    if (isRenewCancelled && _userDetails.hasPaidAddon()) {
+      return const SizedBox.shrink();
+    }
     final String title = isRenewCancelled
         ? S.of(context).renewSubscription
         : S.of(context).cancelSubscription;
@@ -503,7 +511,7 @@ class _StripeSubscriptionPageState extends State<StripeSubscriptionPage> {
               storage: plan.storage,
               price: plan.price,
               period: plan.period,
-              isActive: isActive,
+              isActive: isActive && !_hideCurrentPlanSelection,
             ),
           ),
         ),
@@ -594,7 +602,7 @@ class _StripeSubscriptionPageState extends State<StripeSubscriptionPage> {
             storage: _currentSubscription!.storage,
             price: _currentSubscription!.price,
             period: _currentSubscription!.period,
-            isActive: true,
+            isActive: !_hasActiveSubscription,
           ),
         ),
       ),

+ 43 - 4
lib/ui/payment/subscription_common_widgets.dart

@@ -98,9 +98,14 @@ class ValidityWidget extends StatelessWidget {
     if (currentSubscription == null) {
       return const SizedBox.shrink();
     }
+    final List<Bonus> addOnBonus = bonusData?.getAddOnBonuses() ?? <Bonus>[];
     final bool isFreeTrialSub = currentSubscription!.productID == freeProductID;
-    if (isFreeTrialSub && (bonusData?.getAddOnBonuses().isNotEmpty ?? false)) {
-      return const SizedBox.shrink();
+    bool hideSubValidityView = false;
+    if (isFreeTrialSub && addOnBonus.isNotEmpty) {
+      hideSubValidityView = true;
+    }
+    if (!currentSubscription!.isValid()) {
+      hideSubValidityView = true;
     }
     final endDate =
         DateFormat.yMMMd(Localizations.localeOf(context).languageCode).format(
@@ -114,11 +119,45 @@ class ValidityWidget extends StatelessWidget {
           : S.of(context).freeTrialValidTill(endDate);
     } else if (currentSubscription!.attributes?.isCancelled ?? false) {
       message = S.of(context).subWillBeCancelledOn(endDate);
+      if (addOnBonus.isNotEmpty) {
+        hideSubValidityView = true;
+      }
     }
+
+    return Padding(
+      padding: const EdgeInsets.only(top: 0),
+      child: Column(
+        children: [
+          if (!hideSubValidityView)
+            Text(
+              message,
+              style: Theme.of(context).textTheme.bodySmall,
+              textAlign: TextAlign.center,
+            ),
+          if (addOnBonus.isNotEmpty)
+            ...addOnBonus.map((bonus) => AddOnBonusValidity(bonus)).toList(),
+        ],
+      ),
+    );
+  }
+}
+
+class AddOnBonusValidity extends StatelessWidget {
+  final Bonus bonus;
+
+  const AddOnBonusValidity(this.bonus, {super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    final endDate =
+        DateFormat.yMMMd(Localizations.localeOf(context).languageCode).format(
+      DateTime.fromMicrosecondsSinceEpoch(bonus.validTill),
+    );
+    final String storage = convertBytesToReadableFormat(bonus.storage);
     return Padding(
-      padding: const EdgeInsets.only(top: 8),
+      padding: const EdgeInsets.only(top: 8, bottom: 8),
       child: Text(
-        message,
+        S.of(context).addOnValidTill(storage, endDate),
         style: Theme.of(context).textTheme.bodySmall,
         textAlign: TextAlign.center,
       ),

+ 1 - 1
pubspec.yaml

@@ -12,7 +12,7 @@ description: ente photos application
 # Read more about iOS versioning at
 # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
 
-version: 0.8.0+520
+version: 0.8.1+521
 
 environment:
   sdk: ">=3.0.0 <4.0.0"