Explorar o código

resolve conflicts and merge main

ashilkn hai 1 ano
pai
achega
7e15691c30

+ 4 - 0
lib/generated/intl/messages_en.dart

@@ -347,6 +347,8 @@ class MessageLookup extends MessageLookupByLibrary {
         "backupSettings":
         "backupSettings":
             MessageLookupByLibrary.simpleMessage("Backup settings"),
             MessageLookupByLibrary.simpleMessage("Backup settings"),
         "backupVideos": MessageLookupByLibrary.simpleMessage("Backup videos"),
         "backupVideos": MessageLookupByLibrary.simpleMessage("Backup videos"),
+        "blackFridaySale":
+            MessageLookupByLibrary.simpleMessage("Black Friday Sale"),
         "blog": MessageLookupByLibrary.simpleMessage("Blog"),
         "blog": MessageLookupByLibrary.simpleMessage("Blog"),
         "cachedData": MessageLookupByLibrary.simpleMessage("Cached data"),
         "cachedData": MessageLookupByLibrary.simpleMessage("Cached data"),
         "calculating": MessageLookupByLibrary.simpleMessage("Calculating..."),
         "calculating": MessageLookupByLibrary.simpleMessage("Calculating..."),
@@ -1338,6 +1340,8 @@ class MessageLookup extends MessageLookupByLibrary {
         "upgrade": MessageLookupByLibrary.simpleMessage("Upgrade"),
         "upgrade": MessageLookupByLibrary.simpleMessage("Upgrade"),
         "uploadingFilesToAlbum":
         "uploadingFilesToAlbum":
             MessageLookupByLibrary.simpleMessage("Uploading files to album..."),
             MessageLookupByLibrary.simpleMessage("Uploading files to album..."),
+        "upto50OffUntil4thDec": MessageLookupByLibrary.simpleMessage(
+            "Upto 50% off, until 4th Dec."),
         "usableReferralStorageInfo": MessageLookupByLibrary.simpleMessage(
         "usableReferralStorageInfo": MessageLookupByLibrary.simpleMessage(
             "Usable storage is limited by your current plan. Excess claimed storage will automatically become usable when you upgrade your plan."),
             "Usable storage is limited by your current plan. Excess claimed storage will automatically become usable when you upgrade your plan."),
         "usePublicLinksForPeopleNotOnEnte":
         "usePublicLinksForPeopleNotOnEnte":

+ 20 - 0
lib/generated/l10n.dart

@@ -7895,6 +7895,16 @@ class S {
     );
     );
   }
   }
 
 
+  /// `Black Friday Sale`
+  String get blackFridaySale {
+    return Intl.message(
+      'Black Friday Sale',
+      name: 'blackFridaySale',
+      desc: '',
+      args: [],
+    );
+  }
+
   /// `Modify your query, or try searching for`
   /// `Modify your query, or try searching for`
   String get modifyYourQueryOrTrySearchingFor {
   String get modifyYourQueryOrTrySearchingFor {
     return Intl.message(
     return Intl.message(
@@ -7904,6 +7914,16 @@ class S {
       args: [],
       args: [],
     );
     );
   }
   }
+
+  /// `Upto 50% off, until 4th Dec.`
+  String get upto50OffUntil4thDec {
+    return Intl.message(
+      'Upto 50% off, until 4th Dec.',
+      name: 'upto50OffUntil4thDec',
+      desc: '',
+      args: [],
+    );
+  }
 }
 }
 
 
 class AppLocalizationDelegate extends LocalizationsDelegate<S> {
 class AppLocalizationDelegate extends LocalizationsDelegate<S> {

+ 4 - 2
lib/l10n/intl_en.arb

@@ -1122,5 +1122,7 @@
   "addOns": "Add-ons",
   "addOns": "Add-ons",
   "addOnPageSubtitle": "Details of add-ons",
   "addOnPageSubtitle": "Details of add-ons",
   "yourMap": "Your map",
   "yourMap": "Your map",
-  "modifyYourQueryOrTrySearchingFor": "Modify your query, or try searching for"
-}
+  "modifyYourQueryOrTrySearchingFor": "Modify your query, or try searching for",
+  "blackFridaySale": "Black Friday Sale",
+  "upto50OffUntil4thDec": "Upto 50% off, until 4th Dec."
+}

+ 4 - 0
lib/models/user_details.dart

@@ -33,6 +33,10 @@ class UserDetails {
     return familyData?.members?.isNotEmpty ?? false;
     return familyData?.members?.isNotEmpty ?? false;
   }
   }
 
 
+  bool hasPaidAddon() {
+    return bonusData?.getAddOnBonuses().isNotEmpty ?? false;
+  }
+
   bool isFamilyAdmin() {
   bool isFamilyAdmin() {
     assert(isPartOfFamily(), "verify user is part of family before calling");
     assert(isPartOfFamily(), "verify user is part of family before calling");
     final FamilyMember currentUserMember = familyData!.members!
     final FamilyMember currentUserMember = familyData!.members!

+ 2 - 1
lib/services/billing_service.dart

@@ -166,7 +166,8 @@ class BillingService {
     BuildContext context,
     BuildContext context,
     UserDetails userDetails,
     UserDetails userDetails,
   ) async {
   ) async {
-    if (userDetails.subscription.productID == freeProductID) {
+    if (userDetails.subscription.productID == freeProductID &&
+        !userDetails.hasPaidAddon()) {
       await showErrorDialog(
       await showErrorDialog(
         context,
         context,
         S.of(context).familyPlans,
         S.of(context).familyPlans,

+ 31 - 5
lib/ui/components/notification_widget.dart

@@ -1,4 +1,5 @@
 import 'package:flutter/material.dart';
 import 'package:flutter/material.dart';
+import "package:flutter_animate/flutter_animate.dart";
 import "package:photos/ente_theme_data.dart";
 import "package:photos/ente_theme_data.dart";
 import 'package:photos/theme/colors.dart';
 import 'package:photos/theme/colors.dart';
 import "package:photos/theme/ente_theme.dart";
 import "package:photos/theme/ente_theme.dart";
@@ -20,6 +21,7 @@ class NotificationWidget extends StatelessWidget {
   final String? subText;
   final String? subText;
   final GestureTapCallback onTap;
   final GestureTapCallback onTap;
   final NotificationType type;
   final NotificationType type;
+  final bool isBlackFriday;
 
 
   const NotificationWidget({
   const NotificationWidget({
     Key? key,
     Key? key,
@@ -27,6 +29,7 @@ class NotificationWidget extends StatelessWidget {
     required this.actionIcon,
     required this.actionIcon,
     required this.text,
     required this.text,
     required this.onTap,
     required this.onTap,
+    this.isBlackFriday = false,
     this.subText,
     this.subText,
     this.type = NotificationType.warning,
     this.type = NotificationType.warning,
   }) : super(key: key);
   }) : super(key: key);
@@ -89,11 +92,34 @@ class NotificationWidget extends StatelessWidget {
             child: Row(
             child: Row(
               mainAxisAlignment: MainAxisAlignment.spaceBetween,
               mainAxisAlignment: MainAxisAlignment.spaceBetween,
               children: [
               children: [
-                Icon(
-                  startIcon,
-                  size: 36,
-                  color: strokeColorScheme.strokeBase,
-                ),
+                isBlackFriday
+                    ? Icon(
+                        startIcon,
+                        size: 36,
+                        color: strokeColorScheme.strokeBase,
+                      )
+                        .animate(
+                          onPlay: (controller) =>
+                              controller.repeat(reverse: true),
+                          delay: 2000.ms,
+                        )
+                        .shake(
+                          duration: 500.ms,
+                          hz: 6,
+                          delay: 1600.ms,
+                        )
+                        .scale(
+                          duration: 500.ms,
+                          begin: const Offset(0.9, 0.9),
+                          end: const Offset(1.1, 1.1),
+                          delay: 1600.ms,
+                          // curve: Curves.easeInOut,
+                        )
+                    : Icon(
+                        startIcon,
+                        size: 36,
+                        color: strokeColorScheme.strokeBase,
+                      ),
                 const SizedBox(width: 12),
                 const SizedBox(width: 12),
                 Expanded(
                 Expanded(
                   child: Column(
                   child: Column(

+ 6 - 4
lib/ui/payment/stripe_subscription_page.dart

@@ -211,10 +211,12 @@ class _StripeSubscriptionPageState extends State<StripeSubscriptionPage> {
     widgets.add(_showSubscriptionToggle());
     widgets.add(_showSubscriptionToggle());
 
 
     if (_hasActiveSubscription) {
     if (_hasActiveSubscription) {
-      widgets.add(ValidityWidget(
-        currentSubscription: _currentSubscription,
-        bonusData: _userDetails.bonusData,
-      ));
+      widgets.add(
+        ValidityWidget(
+          currentSubscription: _currentSubscription,
+          bonusData: _userDetails.bonusData,
+        ),
+      );
     }
     }
 
 
     if (_currentSubscription!.productID == freeProductID) {
     if (_currentSubscription!.productID == freeProductID) {

+ 50 - 12
lib/ui/settings_page.dart

@@ -9,6 +9,7 @@ import 'package:photos/events/opened_settings_event.dart';
 import "package:photos/generated/l10n.dart";
 import "package:photos/generated/l10n.dart";
 import 'package:photos/services/feature_flag_service.dart';
 import 'package:photos/services/feature_flag_service.dart';
 import "package:photos/services/storage_bonus_service.dart";
 import "package:photos/services/storage_bonus_service.dart";
+import "package:photos/services/user_service.dart";
 import 'package:photos/theme/colors.dart';
 import 'package:photos/theme/colors.dart';
 import 'package:photos/theme/ente_theme.dart';
 import 'package:photos/theme/ente_theme.dart';
 import "package:photos/ui/components/notification_widget.dart";
 import "package:photos/ui/components/notification_widget.dart";
@@ -28,6 +29,7 @@ import 'package:photos/ui/settings/support_section_widget.dart';
 import 'package:photos/ui/settings/theme_switch_widget.dart';
 import 'package:photos/ui/settings/theme_switch_widget.dart';
 import "package:photos/ui/sharing/verify_identity_dialog.dart";
 import "package:photos/ui/sharing/verify_identity_dialog.dart";
 import "package:photos/utils/navigation_util.dart";
 import "package:photos/utils/navigation_util.dart";
+import "package:url_launcher/url_launcher_string.dart";
 
 
 class SettingsPage extends StatelessWidget {
 class SettingsPage extends StatelessWidget {
   final ValueNotifier<String?> emailNotifier;
   final ValueNotifier<String?> emailNotifier;
@@ -84,23 +86,42 @@ class SettingsPage extends StatelessWidget {
     const sectionSpacing = SizedBox(height: 8);
     const sectionSpacing = SizedBox(height: 8);
     contents.add(const SizedBox(height: 8));
     contents.add(const SizedBox(height: 8));
     if (hasLoggedIn) {
     if (hasLoggedIn) {
+      final shouldShowBFBanner = shouldShowBfBanner();
+      final showStorageBonusBanner =
+          StorageBonusService.instance.shouldShowStorageBonus();
       contents.addAll([
       contents.addAll([
         const StorageCardWidget(),
         const StorageCardWidget(),
-        StorageBonusService.instance.shouldShowStorageBonus()
+        (shouldShowBFBanner || showStorageBonusBanner)
             ? RepaintBoundary(
             ? RepaintBoundary(
                 child: Padding(
                 child: Padding(
                   padding: const EdgeInsets.symmetric(vertical: 8.0),
                   padding: const EdgeInsets.symmetric(vertical: 8.0),
-                  child: NotificationWidget(
-                    startIcon: Icons.auto_awesome,
-                    actionIcon: Icons.arrow_forward_outlined,
-                    text: S.of(context).doubleYourStorage,
-                    subText: S.of(context).referFriendsAnd2xYourPlan,
-                    type: NotificationType.goldenBanner,
-                    onTap: () async {
-                      StorageBonusService.instance.markStorageBonusAsDone();
-                      routeToPage(context, const ReferralScreen());
-                    },
-                  ),
+                  child: shouldShowBFBanner
+                      ? NotificationWidget(
+                          isBlackFriday: true,
+                          startIcon: Icons.celebration,
+                          actionIcon: Icons.arrow_forward_outlined,
+                          text: S.of(context).blackFridaySale,
+                          subText: S.of(context).upto50OffUntil4thDec,
+                          type: NotificationType.goldenBanner,
+                          onTap: () async {
+                            launchUrlString(
+                              "https://ente.io/blackfriday",
+                              mode: LaunchMode.platformDefault,
+                            );
+                          },
+                        )
+                      : NotificationWidget(
+                          startIcon: Icons.auto_awesome,
+                          actionIcon: Icons.arrow_forward_outlined,
+                          text: S.of(context).doubleYourStorage,
+                          subText: S.of(context).referFriendsAnd2xYourPlan,
+                          type: NotificationType.goldenBanner,
+                          onTap: () async {
+                            StorageBonusService.instance
+                                .markStorageBonusAsDone();
+                            routeToPage(context, const ReferralScreen());
+                          },
+                        ),
                 ).animate(onPlay: (controller) => controller.repeat()).shimmer(
                 ).animate(onPlay: (controller) => controller.repeat()).shimmer(
                       duration: 1000.ms,
                       duration: 1000.ms,
                       delay: 3200.ms,
                       delay: 3200.ms,
@@ -167,6 +188,23 @@ class SettingsPage extends StatelessWidget {
     );
     );
   }
   }
 
 
+  bool shouldShowBfBanner() {
+    if (!Platform.isAndroid && !kDebugMode) {
+      return false;
+    }
+    // if date is after 5th of December 2023, 00:00:00, hide banner
+    if (DateTime.now().isAfter(DateTime(2023, 12, 5))) {
+      return false;
+    }
+    // if coupon is already applied, can hide the banner
+    return (UserService.instance
+            .getCachedUserDetails()
+            ?.bonusData
+            ?.getAddOnBonuses()
+            .isEmpty ??
+        true);
+  }
+
   Future<void> _showVerifyIdentityDialog(BuildContext context) async {
   Future<void> _showVerifyIdentityDialog(BuildContext context) async {
     await showDialog(
     await showDialog(
       context: context,
       context: context,

+ 1 - 1
pubspec.yaml

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