diff --git a/lib/db/files_db.dart b/lib/db/files_db.dart index 5b052a52a..017f48f11 100644 --- a/lib/db/files_db.dart +++ b/lib/db/files_db.dart @@ -546,15 +546,29 @@ class FilesDB { List files, Set ignoredCollectionIDs, ) { - final uploadedFileIDs = {}; + final Set uploadedFileIDs = {}; + // ignoredFileUploadIDs is to keep a track of files which are part of + // archived collection + final Set ignoredFileUploadIDs = {}; final List deduplicatedFiles = []; for (final file in files) { final id = file.uploadedFileID; - if (ignoredCollectionIDs != null && - ignoredCollectionIDs.contains(file.collectionID)) { + final bool isFileUploaded = id != null && id != -1; + final bool isCollectionIgnored = ignoredCollectionIDs != null && + ignoredCollectionIDs.contains(file.collectionID); + if (isCollectionIgnored || ignoredFileUploadIDs.contains(id)) { + if (isFileUploaded) { + ignoredFileUploadIDs.add(id); + // remove the file from the list of deduplicated files + if (uploadedFileIDs.contains(id)) { + deduplicatedFiles + .removeWhere((element) => element.uploadedFileID == id); + uploadedFileIDs.remove(id); + } + } continue; } - if (id != null && id != -1 && uploadedFileIDs.contains(id)) { + if (isFileUploaded && uploadedFileIDs.contains(id)) { continue; } uploadedFileIDs.add(id); diff --git a/lib/services/user_remote_flag_service.dart b/lib/services/user_remote_flag_service.dart index 89c10cfa0..8643e243b 100644 --- a/lib/services/user_remote_flag_service.dart +++ b/lib/services/user_remote_flag_service.dart @@ -5,7 +5,9 @@ import 'package:collection/collection.dart'; import 'package:dio/dio.dart'; import 'package:logging/logging.dart'; import 'package:photos/core/configuration.dart'; +import 'package:photos/core/event_bus.dart'; import 'package:photos/core/network.dart'; +import 'package:photos/events/notification_event.dart'; import 'package:photos/services/user_service.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -33,8 +35,14 @@ class UserRemoteFlagService { // fetch the status from remote unawaited(_refreshRecoveryVerificationFlag()); return false; + } else { + final bool shouldShow = _prefs.getBool(needRecoveryKeyVerification)!; + if (shouldShow) { + // refresh the status to check if user marked it as done on another device + unawaited(_refreshRecoveryVerificationFlag()); + } + return shouldShow; } - return _prefs.getBool(needRecoveryKeyVerification)!; } // markRecoveryVerificationAsDone is used to track if user has verified their @@ -46,13 +54,22 @@ class UserRemoteFlagService { } Future _refreshRecoveryVerificationFlag() async { + _logger.finest('refresh recovery key verification flag'); final remoteStatusValue = await _getValue(recoveryVerificationFlag, "false"); + final bool isNeedVerificationFlagSet = + _prefs.containsKey(needRecoveryKeyVerification); if (remoteStatusValue.toLowerCase() == "true") { await _prefs.setBool(needRecoveryKeyVerification, false); - } else { - // check the session creationTime. If any active session is older than - // 1 day, set the need to verification as true + // If the user verified on different device, then we should refresh + // the UI to dismiss the Notification. + if (isNeedVerificationFlagSet) { + Bus.instance.fire(NotificationEvent()); + } + } else if (!isNeedVerificationFlagSet) { + // Verification is not done yet as remoteStatus is false and local flag to + // show notification isn't set. Set the flag to true if any active + // session is older than 1 day. final activeSessions = await UserService.instance.getActiveSessions(); final int microSecondsInADay = const Duration(days: 1).inMicroseconds; final bool anyActiveSessionOlderThanADay = @@ -64,6 +81,7 @@ class UserRemoteFlagService { null; if (anyActiveSessionOlderThanADay) { await _prefs.setBool(needRecoveryKeyVerification, true); + Bus.instance.fire(NotificationEvent()); } else { // continue defaulting to no verification prompt _logger.finest('No active session older than 1 day'); diff --git a/lib/ui/account/verify_recovery_page.dart b/lib/ui/account/verify_recovery_page.dart index 65253badf..2e94fb873 100644 --- a/lib/ui/account/verify_recovery_page.dart +++ b/lib/ui/account/verify_recovery_page.dart @@ -6,7 +6,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_sodium/flutter_sodium.dart'; import 'package:logging/logging.dart'; import 'package:photos/core/event_bus.dart'; -import 'package:photos/ente_theme_data.dart'; import 'package:photos/events/notification_event.dart'; import 'package:photos/services/local_authentication_service.dart'; import 'package:photos/services/user_remote_flag_service.dart'; @@ -206,23 +205,6 @@ class _VerifyRecoveryPageState extends State { iconData: Icons.shield_outlined, ), const SizedBox(height: 8), - SizedBox( - width: double.infinity, - child: Hero( - tag: "recovery_key", - child: ElevatedButton( - style: Theme.of(context) - .colorScheme - .optionalActionButtonStyle, - onPressed: _onViewRecoveryKeyClick, - child: const Text( - "View recovery key", - // same for both themes - style: TextStyle(color: Colors.black), - ), - ), - ), - ), ], ), ), diff --git a/lib/ui/payment/stripe_subscription_page.dart b/lib/ui/payment/stripe_subscription_page.dart index 371f2c55d..b1a23610c 100644 --- a/lib/ui/payment/stripe_subscription_page.dart +++ b/lib/ui/payment/stripe_subscription_page.dart @@ -222,6 +222,8 @@ class _StripeSubscriptionPageState extends State { alignment: Alignment.center, child: GestureDetector( onTap: () async { + final String paymentProvider = + _currentSubscription.paymentProvider; switch (_currentSubscription.paymentProvider) { case stripe: await _launchStripePortal(); @@ -237,9 +239,14 @@ class _StripeSubscriptionPageState extends State { launchUrlString("https://apps.apple.com/account/billing"); break; default: - _logger.severe( - "unexpected payment provider ", - _currentSubscription, + final String capitalizedWord = paymentProvider.isNotEmpty + ? '${paymentProvider[0].toUpperCase()}${paymentProvider.substring(1).toLowerCase()}' + : ''; + showErrorDialog( + context, + "Sorry", + "Please contact us at support@ente.io to manage your " + "$capitalizedWord subscription.", ); } }, @@ -249,16 +256,12 @@ class _StripeSubscriptionPageState extends State { children: [ RichText( text: TextSpan( - text: !_isStripeSubscriber - ? "visit ${_currentSubscription.paymentProvider} to manage your subscription" - : "Payment details", + text: "Payment details", style: TextStyle( color: Theme.of(context).colorScheme.onSurface, fontFamily: 'Inter-Medium', fontSize: 14, - decoration: _isStripeSubscriber - ? TextDecoration.underline - : TextDecoration.none, + decoration: TextDecoration.underline, ), ), textAlign: TextAlign.center, @@ -442,7 +445,8 @@ class _StripeSubscriptionPageState extends State { showErrorDialog( context, "Sorry", - "please cancel your existing subscription from ${_currentSubscription.paymentProvider} first", + "Please cancel your existing subscription from " + "${_currentSubscription.paymentProvider} first", ); return; } @@ -450,7 +454,7 @@ class _StripeSubscriptionPageState extends State { showErrorDialog( context, "Sorry", - "you cannot downgrade to this plan", + "You cannot downgrade to this plan", ); return; } diff --git a/lib/ui/payment/subscription_page.dart b/lib/ui/payment/subscription_page.dart index b2caad95b..3645cb84d 100644 --- a/lib/ui/payment/subscription_page.dart +++ b/lib/ui/payment/subscription_page.dart @@ -224,17 +224,32 @@ class _SubscriptionPageState extends State { alignment: Alignment.center, child: GestureDetector( onTap: () { - if (_isActiveStripeSubscriber) { - return; - } - if (Platform.isAndroid) { + final String paymentProvider = + _currentSubscription.paymentProvider; + if (paymentProvider == kAppStore && !Platform.isAndroid) { + launchUrlString("https://apps.apple.com/account/billing"); + } else if (paymentProvider == kPlayStore && Platform.isAndroid) { launchUrlString( "https://play.google.com/store/account/subscriptions?sku=" + _currentSubscription.productID + "&package=io.ente.photos", ); + } else if (paymentProvider == kStripe) { + showErrorDialog( + context, + "Sorry", + "Visit web.ente.io to manage your subscription", + ); } else { - launchUrlString("https://apps.apple.com/account/billing"); + final String capitalizedWord = paymentProvider.isNotEmpty + ? '${paymentProvider[0].toUpperCase()}${paymentProvider.substring(1).toLowerCase()}' + : ''; + showErrorDialog( + context, + "Sorry", + "Please contact us at support@ente.io to manage your " + "$capitalizedWord subscription.", + ); } }, child: Container( diff --git a/pubspec.yaml b/pubspec.yaml index ef4c016c8..94afb83ff 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -11,7 +11,7 @@ description: ente photos application # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 0.6.32+362 +version: 0.6.34+364 environment: sdk: '>=2.12.0 <3.0.0'