瀏覽代碼

Execute `dart format lib`

vishnukvmd 3 年之前
父節點
當前提交
47505ae102
共有 100 個文件被更改,包括 3080 次插入2091 次删除
  1. 31 18
      lib/app.dart
  2. 14 9
      lib/core/cache/thumbnail_cache.dart
  3. 46 27
      lib/core/configuration.dart
  4. 6 2
      lib/core/error-reporting/tunneled_transport.dart
  5. 10 5
      lib/core/network.dart
  6. 15 7
      lib/db/collections_db.dart
  7. 11 6
      lib/db/file_migration_db.dart
  8. 103 47
      lib/db/files_db.dart
  9. 17 8
      lib/db/ignored_files_db.dart
  10. 9 4
      lib/db/memories_db.dart
  11. 16 9
      lib/db/public_keys_db.dart
  12. 27 14
      lib/db/trash_db.dart
  13. 4 2
      lib/db/upload_locks_db.dart
  14. 34 27
      lib/ente_theme_data.dart
  15. 50 35
      lib/main.dart
  16. 2 1
      lib/models/billing_plan.dart
  17. 26 23
      lib/models/collection.dart
  18. 2 1
      lib/models/duplicate_files.dart
  19. 6 5
      lib/models/file.dart
  20. 6 2
      lib/models/ignored_file.dart
  21. 2 1
      lib/models/magic_metadata.dart
  22. 3 3
      lib/models/subscription.dart
  23. 0 1
      lib/models/trash_file.dart
  24. 1 0
      lib/models/update_share_url_request.dart
  25. 7 5
      lib/models/user_details.dart
  26. 15 9
      lib/services/billing_service.dart
  27. 153 85
      lib/services/collections_service.dart
  28. 6 3
      lib/services/deduplication_service.dart
  29. 19 16
      lib/services/favorites_service.dart
  30. 11 9
      lib/services/feature_flag_service.dart
  31. 35 16
      lib/services/file_magic_service.dart
  32. 8 4
      lib/services/file_migration_service.dart
  33. 10 5
      lib/services/ignored_files_service.dart
  34. 23 14
      lib/services/local_sync_service.dart
  35. 10 4
      lib/services/memories_service.dart
  36. 9 3
      lib/services/notification_service.dart
  37. 5 2
      lib/services/push_service.dart
  38. 71 33
      lib/services/remote_sync_service.dart
  39. 37 15
      lib/services/sync_service.dart
  40. 2 1
      lib/services/trash_sync_service.dart
  41. 3 1
      lib/services/update_service.dart
  42. 116 56
      lib/services/user_service.dart
  43. 5 3
      lib/ui/app_lock.dart
  44. 24 17
      lib/ui/app_update_dialog.dart
  45. 20 13
      lib/ui/archive_page.dart
  46. 44 31
      lib/ui/backup_folder_selection_page.dart
  47. 15 11
      lib/ui/billing_questions_widget.dart
  48. 5 2
      lib/ui/change_email_dialog.dart
  49. 13 8
      lib/ui/collection_page.dart
  50. 122 85
      lib/ui/collections_gallery_widget.dart
  51. 7 7
      lib/ui/common/bottomShadow.dart
  52. 24 24
      lib/ui/common/dynamicFAB.dart
  53. 11 8
      lib/ui/common/onlyOuterShadow.dart
  54. 6 2
      lib/ui/common/report_bug_popup.dart
  55. 41 20
      lib/ui/create_collection_page.dart
  56. 28 22
      lib/ui/deduplicate_page.dart
  57. 34 19
      lib/ui/detail_page.dart
  58. 11 6
      lib/ui/device_folder_page.dart
  59. 15 11
      lib/ui/editor/filtered_image.dart
  60. 45 32
      lib/ui/email_entry_page.dart
  61. 16 15
      lib/ui/expansion_card.dart
  62. 23 9
      lib/ui/extents_page_view.dart
  63. 116 103
      lib/ui/fading_app_bar.dart
  64. 10 8
      lib/ui/fading_bottom_bar.dart
  65. 6 3
      lib/ui/file_info_dialog.dart
  66. 3 2
      lib/ui/free_space_page.dart
  67. 33 19
      lib/ui/gallery.dart
  68. 41 37
      lib/ui/gallery_app_bar_widget.dart
  69. 159 109
      lib/ui/gallery_overlay_widget.dart
  70. 23 15
      lib/ui/grant_permissions_widget.dart
  71. 171 145
      lib/ui/home_widget.dart
  72. 28 20
      lib/ui/huge_listview/draggable_scrollbar.dart
  73. 8 4
      lib/ui/huge_listview/huge_listview.dart
  74. 31 20
      lib/ui/huge_listview/lazy_loading_gallery.dart
  75. 17 9
      lib/ui/huge_listview/scroll_bar_thumb.dart
  76. 5 3
      lib/ui/image_editor_page.dart
  77. 4 2
      lib/ui/landing_page_widget.dart
  78. 25 22
      lib/ui/loading_photos_widget.dart
  79. 37 32
      lib/ui/location_search_widget.dart
  80. 30 27
      lib/ui/lock_screen.dart
  81. 16 8
      lib/ui/login_page.dart
  82. 56 30
      lib/ui/manage_links_widget.dart
  83. 57 44
      lib/ui/memories_widget.dart
  84. 90 87
      lib/ui/nav_bar.dart
  85. 24 11
      lib/ui/ott_verification_page.dart
  86. 127 98
      lib/ui/password_entry_page.dart
  87. 24 18
      lib/ui/password_reentry_page.dart
  88. 93 86
      lib/ui/payment/payment_web_page.dart
  89. 102 69
      lib/ui/payment/stripe_subscription_page.dart
  90. 10 6
      lib/ui/payment/subscription_common_widgets.dart
  91. 46 28
      lib/ui/payment/subscription_page.dart
  92. 7 3
      lib/ui/payment/subscription_plan_widget.dart
  93. 41 31
      lib/ui/progress_dialog.dart
  94. 73 57
      lib/ui/recovery_key_page.dart
  95. 43 40
      lib/ui/recovery_page.dart
  96. 9 3
      lib/ui/rename_dialog.dart
  97. 4 1
      lib/ui/sessions_page.dart
  98. 3 1
      lib/ui/set_wallpaper_dialog.dart
  99. 16 6
      lib/ui/settings/account_section_widget.dart
  100. 2 1
      lib/ui/settings/app_version_widget.dart

+ 31 - 18
lib/app.dart

@@ -24,7 +24,9 @@ final lightThemeData = ThemeData(
   iconTheme: IconThemeData(color: Colors.black),
   primaryIconTheme: IconThemeData(color: Colors.red, opacity: 1.0, size: 50.0),
   colorScheme: ColorScheme.light(
-      primary: Colors.black, secondary: Color.fromARGB(255, 163, 163, 163),),
+    primary: Colors.black,
+    secondary: Color.fromARGB(255, 163, 163, 163),
+  ),
   accentColor: Color.fromRGBO(0, 0, 0, 0.6),
   buttonColor: Color.fromRGBO(45, 194, 98, 1.0),
   outlinedButtonTheme: buildOutlinedButtonThemeData(
@@ -34,7 +36,9 @@ final lightThemeData = ThemeData(
     fgEnabled: Colors.white,
   ),
   elevatedButtonTheme: buildElevatedButtonThemeData(
-      onPrimary: Colors.white, primary: Colors.black,),
+    onPrimary: Colors.white,
+    primary: Colors.black,
+  ),
   toggleableActiveColor: Colors.green[400],
   scaffoldBackgroundColor: Colors.white,
   backgroundColor: Colors.white,
@@ -47,19 +51,25 @@ final lightThemeData = ThemeData(
   //https://api.flutter.dev/flutter/material/TextTheme-class.html
   textTheme: _buildTextTheme(Colors.black),
   primaryTextTheme: TextTheme().copyWith(
-      bodyText2: TextStyle(color: Colors.yellow),
-      bodyText1: TextStyle(color: Colors.orange),),
+    bodyText2: TextStyle(color: Colors.yellow),
+    bodyText1: TextStyle(color: Colors.orange),
+  ),
   cardColor: Color.fromRGBO(250, 250, 250, 1.0),
   dialogTheme: DialogTheme().copyWith(
-      backgroundColor: Color.fromRGBO(250, 250, 250, 1.0), //
-      titleTextStyle: TextStyle(
-          color: Colors.black, fontSize: 24, fontWeight: FontWeight.w600,),
-      contentTextStyle: TextStyle(
-          fontFamily: 'Inter-Medium',
-          color: Colors.black,
-          fontSize: 16,
-          fontWeight: FontWeight.w500,),
-      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),),
+    backgroundColor: Color.fromRGBO(250, 250, 250, 1.0), //
+    titleTextStyle: TextStyle(
+      color: Colors.black,
+      fontSize: 24,
+      fontWeight: FontWeight.w600,
+    ),
+    contentTextStyle: TextStyle(
+      fontFamily: 'Inter-Medium',
+      color: Colors.black,
+      fontSize: 16,
+      fontWeight: FontWeight.w500,
+    ),
+    shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
+  ),
   inputDecorationTheme: InputDecorationTheme().copyWith(
     focusedBorder: UnderlineInputBorder(
       borderSide: BorderSide(
@@ -101,12 +111,15 @@ final darkThemeData = ThemeData(
   textTheme: _buildTextTheme(Colors.white),
   toggleableActiveColor: Colors.green[400],
   outlinedButtonTheme: buildOutlinedButtonThemeData(
-      bgDisabled: Colors.grey.shade500,
-      bgEnabled: Colors.white,
-      fgDisabled: Colors.white,
-      fgEnabled: Colors.black,),
+    bgDisabled: Colors.grey.shade500,
+    bgEnabled: Colors.white,
+    fgDisabled: Colors.white,
+    fgEnabled: Colors.black,
+  ),
   elevatedButtonTheme: buildElevatedButtonThemeData(
-      onPrimary: Colors.black, primary: Colors.white,),
+    onPrimary: Colors.black,
+    primary: Colors.white,
+  ),
   scaffoldBackgroundColor: Colors.black,
   backgroundColor: Colors.black,
   appBarTheme: AppBarTheme().copyWith(

+ 14 - 9
lib/core/cache/thumbnail_cache.dart

@@ -8,9 +8,11 @@ class ThumbnailLruCache {
   static final LRUMap<String, Uint8List> _map = LRUMap(1000);
 
   static Uint8List get(File photo, [int size]) {
-    return _map.get(photo.generatedID.toString() +
-        "_" +
-        (size != null ? size.toString() : kThumbnailLargeSize.toString()),);
+    return _map.get(
+      photo.generatedID.toString() +
+          "_" +
+          (size != null ? size.toString() : kThumbnailLargeSize.toString()),
+    );
   }
 
   static void put(
@@ -19,16 +21,19 @@ class ThumbnailLruCache {
     int size,
   ]) {
     _map.put(
-        photo.generatedID.toString() +
-            "_" +
-            (size != null ? size.toString() : kThumbnailLargeSize.toString()),
-        imageData,);
+      photo.generatedID.toString() +
+          "_" +
+          (size != null ? size.toString() : kThumbnailLargeSize.toString()),
+      imageData,
+    );
   }
 
   static void clearCache(File file) {
     _map.remove(
-        file.generatedID.toString() + "_" + kThumbnailLargeSize.toString(),);
+      file.generatedID.toString() + "_" + kThumbnailLargeSize.toString(),
+    );
     _map.remove(
-        file.generatedID.toString() + "_" + kThumbnailSmallSize.toString(),);
+      file.generatedID.toString() + "_" + kThumbnailSmallSize.toString(),
+    );
   }
 }

+ 46 - 27
lib/core/configuration.dart

@@ -187,8 +187,11 @@ class Configuration {
       Sodium.bin2base64(encryptedRecoveryKey.encryptedData),
       Sodium.bin2base64(encryptedRecoveryKey.nonce),
     );
-    final privateAttributes = PrivateKeyAttributes(Sodium.bin2base64(masterKey),
-        Sodium.bin2hex(recoveryKey), Sodium.bin2base64(keyPair.sk),);
+    final privateAttributes = PrivateKeyAttributes(
+      Sodium.bin2base64(masterKey),
+      Sodium.bin2hex(recoveryKey),
+      Sodium.bin2base64(keyPair.sk),
+    );
     return KeyGenResult(attributes, privateAttributes);
   }
 
@@ -218,7 +221,9 @@ class Configuration {
   }
 
   Future<void> decryptAndSaveSecrets(
-      String password, KeyAttributes attributes,) async {
+    String password,
+    KeyAttributes attributes,
+  ) async {
     final kek = await CryptoUtil.deriveKey(
       utf8.encode(password),
       Sodium.base642bin(attributes.kekSalt),
@@ -227,23 +232,29 @@ class Configuration {
     );
     Uint8List key;
     try {
-      key = CryptoUtil.decryptSync(Sodium.base642bin(attributes.encryptedKey),
-          kek, Sodium.base642bin(attributes.keyDecryptionNonce),);
+      key = CryptoUtil.decryptSync(
+        Sodium.base642bin(attributes.encryptedKey),
+        kek,
+        Sodium.base642bin(attributes.keyDecryptionNonce),
+      );
     } catch (e) {
       throw Exception("Incorrect password");
     }
     await setKey(Sodium.bin2base64(key));
     final secretKey = CryptoUtil.decryptSync(
-        Sodium.base642bin(attributes.encryptedSecretKey),
-        key,
-        Sodium.base642bin(attributes.secretKeyDecryptionNonce),);
+      Sodium.base642bin(attributes.encryptedSecretKey),
+      key,
+      Sodium.base642bin(attributes.secretKeyDecryptionNonce),
+    );
     await setSecretKey(Sodium.bin2base64(secretKey));
     final token = CryptoUtil.openSealSync(
-        Sodium.base642bin(getEncryptedToken()),
-        Sodium.base642bin(attributes.publicKey),
-        secretKey,);
+      Sodium.base642bin(getEncryptedToken()),
+      Sodium.base642bin(attributes.publicKey),
+      secretKey,
+    );
     await setToken(
-        Sodium.bin2base64(token, variant: Sodium.base64VariantUrlsafe),);
+      Sodium.bin2base64(token, variant: Sodium.base64VariantUrlsafe),
+    );
   }
 
   Future<KeyAttributes> createNewRecoveryKey() async {
@@ -272,7 +283,8 @@ class Configuration {
     if (recoveryKey.contains(' ')) {
       if (recoveryKey.split(' ').length != kMnemonicKeyWordCount) {
         throw AssertionError(
-            'recovery code should have $kMnemonicKeyWordCount words',);
+          'recovery code should have $kMnemonicKeyWordCount words',
+        );
       }
       recoveryKey = bip39.mnemonicToEntropy(recoveryKey);
     }
@@ -280,25 +292,29 @@ class Configuration {
     Uint8List masterKey;
     try {
       masterKey = await CryptoUtil.decrypt(
-          Sodium.base642bin(attributes.masterKeyEncryptedWithRecoveryKey),
-          Sodium.hex2bin(recoveryKey),
-          Sodium.base642bin(attributes.masterKeyDecryptionNonce),);
+        Sodium.base642bin(attributes.masterKeyEncryptedWithRecoveryKey),
+        Sodium.hex2bin(recoveryKey),
+        Sodium.base642bin(attributes.masterKeyDecryptionNonce),
+      );
     } catch (e) {
       _logger.severe(e);
       rethrow;
     }
     await setKey(Sodium.bin2base64(masterKey));
     final secretKey = CryptoUtil.decryptSync(
-        Sodium.base642bin(attributes.encryptedSecretKey),
-        masterKey,
-        Sodium.base642bin(attributes.secretKeyDecryptionNonce),);
+      Sodium.base642bin(attributes.encryptedSecretKey),
+      masterKey,
+      Sodium.base642bin(attributes.secretKeyDecryptionNonce),
+    );
     await setSecretKey(Sodium.bin2base64(secretKey));
     final token = CryptoUtil.openSealSync(
-        Sodium.base642bin(getEncryptedToken()),
-        Sodium.base642bin(attributes.publicKey),
-        secretKey,);
+      Sodium.base642bin(getEncryptedToken()),
+      Sodium.base642bin(attributes.publicKey),
+      secretKey,
+    );
     await setToken(
-        Sodium.bin2base64(token, variant: Sodium.base64VariantUrlsafe),);
+      Sodium.bin2base64(token, variant: Sodium.base64VariantUrlsafe),
+    );
   }
 
   String getHttpEndpoint() {
@@ -428,9 +444,10 @@ class Configuration {
   Uint8List getRecoveryKey() {
     final keyAttributes = getKeyAttributes();
     return CryptoUtil.decryptSync(
-        Sodium.base642bin(keyAttributes.recoveryKeyEncryptedWithMasterKey),
-        getKey(),
-        Sodium.base642bin(keyAttributes.recoveryKeyDecryptionNonce),);
+      Sodium.base642bin(keyAttributes.recoveryKeyEncryptedWithMasterKey),
+      getKey(),
+      Sodium.base642bin(keyAttributes.recoveryKeyDecryptionNonce),
+    );
   }
 
   String getDocumentsDirectory() {
@@ -551,7 +568,9 @@ class Configuration {
         iOptions: _secureStorageOptionsIOS,
       );
       await _preferences.setBool(
-          hasMigratedSecureStorageToFirstUnlockKey, true,);
+        hasMigratedSecureStorageToFirstUnlockKey,
+        true,
+      );
     }
   }
 

+ 6 - 2
lib/core/error-reporting/tunneled_transport.dart

@@ -63,7 +63,8 @@ class TunneledTransport implements Transport {
   }
 
   Future<StreamedRequest> _createStreamedRequest(
-      SentryEnvelope envelope,) async {
+    SentryEnvelope envelope,
+  ) async {
     final streamedRequest = StreamedRequest('POST', _tunnel);
     envelope
         .envelopeStream(_options)
@@ -88,7 +89,10 @@ class _CredentialBuilder {
         _clock = clock;
 
   factory _CredentialBuilder(
-      Dsn dsn, String sdkIdentifier, ClockProvider clock,) {
+    Dsn dsn,
+    String sdkIdentifier,
+    ClockProvider clock,
+  ) {
     final authHeader = _buildAuthHeader(
       publicKey: dsn.publicKey,
       secretKey: dsn.secretKey,

+ 10 - 5
lib/core/network.dart

@@ -17,11 +17,16 @@ class Network {
     _alice = Alice(darkTheme: true, showNotification: kDebugMode);
     await FkUserAgent.init();
     final packageInfo = await PackageInfo.fromPlatform();
-    _dio = Dio(BaseOptions(connectTimeout: kConnectTimeout, headers: {
-      HttpHeaders.userAgentHeader: FkUserAgent.userAgent,
-      'X-Client-Version': packageInfo.version,
-      'X-Client-Package': packageInfo.packageName,
-    },),);
+    _dio = Dio(
+      BaseOptions(
+        connectTimeout: kConnectTimeout,
+        headers: {
+          HttpHeaders.userAgentHeader: FkUserAgent.userAgent,
+          'X-Client-Version': packageInfo.version,
+          'X-Client-Package': packageInfo.packageName,
+        },
+      ),
+    );
     _dio.interceptors.add(RequestIdInterceptor());
     _dio.interceptors.add(_alice.getDioInterceptor());
   }

+ 15 - 7
lib/db/collections_db.dart

@@ -44,7 +44,9 @@ class CollectionsDB {
   ];
 
   final dbConfig = MigrationConfig(
-      initializationScript: intitialScript, migrationScripts: migrationScripts,);
+    initializationScript: intitialScript,
+    migrationScripts: migrationScripts,
+  );
 
   CollectionsDB._privateConstructor();
 
@@ -157,8 +159,11 @@ class CollectionsDB {
     final db = await instance.database;
     var batch = db.batch();
     for (final collection in collections) {
-      batch.insert(table, _getRowForCollection(collection),
-          conflictAlgorithm: ConflictAlgorithm.replace,);
+      batch.insert(
+        table,
+        _getRowForCollection(collection),
+        conflictAlgorithm: ConflictAlgorithm.replace,
+      );
     }
     return await batch.commit();
   }
@@ -239,12 +244,15 @@ class CollectionsDB {
         pathDecryptionNonce: row[columnPathDecryptionNonce],
         version: row[columnVersion],
       ),
-      List<User>.from((json.decode(row[columnSharees]) as List)
-          .map((x) => User.fromMap(x)),),
+      List<User>.from(
+        (json.decode(row[columnSharees]) as List).map((x) => User.fromMap(x)),
+      ),
       row[columnPublicURLs] == null
           ? []
-          : List<PublicURL>.from((json.decode(row[columnPublicURLs]) as List)
-              .map((x) => PublicURL.fromMap(x)),),
+          : List<PublicURL>.from(
+              (json.decode(row[columnPublicURLs]) as List)
+                  .map((x) => PublicURL.fromMap(x)),
+            ),
       int.parse(row[columnUpdationTime]),
       // default to False is columnIsDeleted is not set
       isDeleted: (row[columnIsDeleted] ?? _sqlBoolFalse) == _sqlBoolTrue,

+ 11 - 6
lib/db/file_migration_db.dart

@@ -14,12 +14,14 @@ class FilesMigrationDB {
   static final columnLocalID = 'local_id';
 
   Future _onCreate(Database db, int version) async {
-    await db.execute('''
+    await db.execute(
+      '''
         CREATE TABLE $tableName (
         $columnLocalID TEXT NOT NULL,
           UNIQUE($columnLocalID)
         );
-      ''',);
+      ''',
+    );
   }
 
   FilesMigrationDB._privateConstructor();
@@ -73,10 +75,13 @@ class FilesMigrationDB {
     await batch.commit(noResult: true);
     final endTime = DateTime.now();
     final duration = Duration(
-        microseconds:
-            endTime.microsecondsSinceEpoch - startTime.microsecondsSinceEpoch,);
-    _logger.info("Batch insert of ${fileLocalIDs.length} "
-        "took ${duration.inMilliseconds} ms.",);
+      microseconds:
+          endTime.microsecondsSinceEpoch - startTime.microsecondsSinceEpoch,
+    );
+    _logger.info(
+      "Batch insert of ${fileLocalIDs.length} "
+      "took ${duration.inMilliseconds} ms.",
+    );
   }
 
   Future<int> deleteByLocalIDs(List<String> localIDs) async {

+ 103 - 47
lib/db/files_db.dart

@@ -76,8 +76,9 @@ class FilesDB {
   ];
 
   final dbConfig = MigrationConfig(
-      initializationScript: initializationScript,
-      migrationScripts: migrationScripts,);
+    initializationScript: initializationScript,
+    migrationScripts: migrationScripts,
+  );
 
   // make this a singleton class
   FilesDB._privateConstructor();
@@ -319,13 +320,16 @@ class FilesDB {
     await batch.commit(noResult: true);
     final endTime = DateTime.now();
     final duration = Duration(
-        microseconds:
-            endTime.microsecondsSinceEpoch - startTime.microsecondsSinceEpoch,);
-    _logger.info("Batch insert of " +
-        files.length.toString() +
-        " took " +
-        duration.inMilliseconds.toString() +
-        "ms.",);
+      microseconds:
+          endTime.microsecondsSinceEpoch - startTime.microsecondsSinceEpoch,
+    );
+    _logger.info(
+      "Batch insert of " +
+          files.length.toString() +
+          " took " +
+          duration.inMilliseconds.toString() +
+          "ms.",
+    );
   }
 
   Future<int> insert(File file) async {
@@ -339,8 +343,11 @@ class FilesDB {
 
   Future<File> getFile(int generatedID) async {
     final db = await instance.database;
-    final results = await db.query(table,
-        where: '$columnGeneratedID = ?', whereArgs: [generatedID],);
+    final results = await db.query(
+      table,
+      where: '$columnGeneratedID = ?',
+      whereArgs: [generatedID],
+    );
     if (results.isEmpty) {
       return null;
     }
@@ -398,11 +405,14 @@ class FilesDB {
   }
 
   Future<FileLoadResult> getAllUploadedFiles(
-      int startTime, int endTime, int ownerID,
-      {int limit,
-      bool asc,
-      int visibility = kVisibilityVisible,
-      Set<int> ignoredCollectionIDs,}) async {
+    int startTime,
+    int endTime,
+    int ownerID, {
+    int limit,
+    bool asc,
+    int visibility = kVisibilityVisible,
+    Set<int> ignoredCollectionIDs,
+  }) async {
     final db = await instance.database;
     final order = (asc ?? false ? 'ASC' : 'DESC');
     final results = await db.query(
@@ -422,8 +432,13 @@ class FilesDB {
   }
 
   Future<FileLoadResult> getAllLocalAndUploadedFiles(
-      int startTime, int endTime, int ownerID,
-      {int limit, bool asc, Set<int> ignoredCollectionIDs,}) async {
+    int startTime,
+    int endTime,
+    int ownerID, {
+    int limit,
+    bool asc,
+    Set<int> ignoredCollectionIDs,
+  }) async {
     final db = await instance.database;
     final order = (asc ?? false ? 'ASC' : 'DESC');
     final results = await db.query(
@@ -443,8 +458,14 @@ class FilesDB {
   }
 
   Future<FileLoadResult> getImportantFiles(
-      int startTime, int endTime, int ownerID, List<String> paths,
-      {int limit, bool asc, Set<int> ignoredCollectionIDs,}) async {
+    int startTime,
+    int endTime,
+    int ownerID,
+    List<String> paths, {
+    int limit,
+    bool asc,
+    Set<int> ignoredCollectionIDs,
+  }) async {
     final db = await instance.database;
     String inParam = "";
     for (final path in paths) {
@@ -469,7 +490,9 @@ class FilesDB {
   }
 
   List<File> _deduplicatedAndFilterIgnoredFiles(
-      List<File> files, Set<int> ignoredCollectionIDs,) {
+    List<File> files,
+    Set<int> ignoredCollectionIDs,
+  ) {
     final uploadedFileIDs = <int>{};
     final List<File> deduplicatedFiles = [];
     for (final file in files) {
@@ -488,8 +511,12 @@ class FilesDB {
   }
 
   Future<FileLoadResult> getFilesInCollection(
-      int collectionID, int startTime, int endTime,
-      {int limit, bool asc,}) async {
+    int collectionID,
+    int startTime,
+    int endTime, {
+    int limit,
+    bool asc,
+  }) async {
     final db = await instance.database;
     final order = (asc ?? false ? 'ASC' : 'DESC');
     final results = await db.query(
@@ -506,8 +533,13 @@ class FilesDB {
     return FileLoadResult(files, files.length == limit);
   }
 
-  Future<FileLoadResult> getFilesInPath(String path, int startTime, int endTime,
-      {int limit, bool asc,}) async {
+  Future<FileLoadResult> getFilesInPath(
+    String path,
+    int startTime,
+    int endTime, {
+    int limit,
+    bool asc,
+  }) async {
     final db = await instance.database;
     final order = (asc ?? false ? 'ASC' : 'DESC');
     final results = await db.query(
@@ -547,7 +579,8 @@ class FilesDB {
   }
 
   Future<List<File>> getFilesCreatedWithinDurations(
-      List<List<int>> durations,) async {
+    List<List<int>> durations,
+  ) async {
     final db = await instance.database;
     String whereClause = "";
     for (int index = 0; index < durations.length; index++) {
@@ -569,7 +602,8 @@ class FilesDB {
   }
 
   Future<List<File>> getFilesToBeUploadedWithinFolders(
-      Set<String> folders,) async {
+    Set<String> folders,
+  ) async {
     if (folders.isEmpty) {
       return [];
     }
@@ -604,10 +638,12 @@ class FilesDB {
     var files = _convertToFiles(results);
     // future-safe filter just to ensure that the query doesn't end up  returning files
     // which should not be backed up
-    files.removeWhere((e) =>
-        e.collectionID == null ||
-        e.localID == null ||
-        e.uploadedFileID != null,);
+    files.removeWhere(
+      (e) =>
+          e.collectionID == null ||
+          e.localID == null ||
+          e.uploadedFileID != null,
+    );
     return files;
   }
 
@@ -801,11 +837,13 @@ class FilesDB {
     }
     inParam = inParam.substring(0, inParam.length - 1);
     final db = await instance.database;
-    await db.rawQuery('''
+    await db.rawQuery(
+      '''
       UPDATE $table
       SET $columnLocalID = NULL
       WHERE $columnLocalID IN ($inParam);
-    ''',);
+    ''',
+    );
   }
 
   Future<List<File>> getLocalFiles(List<String> localIDs) async {
@@ -846,7 +884,9 @@ class FilesDB {
   }
 
   Future<int> deleteFilesFromCollection(
-      int collectionID, List<int> uploadedFileIDs,) async {
+    int collectionID,
+    List<int> uploadedFileIDs,
+  ) async {
     final db = await instance.database;
     return db.delete(
       table,
@@ -858,15 +898,21 @@ class FilesDB {
 
   Future<int> collectionFileCount(int collectionID) async {
     final db = await instance.database;
-    var count = Sqflite.firstIntValue(await db.rawQuery(
-        'SELECT COUNT(*) FROM $table where $columnCollectionID = $collectionID',),);
+    var count = Sqflite.firstIntValue(
+      await db.rawQuery(
+        'SELECT COUNT(*) FROM $table where $columnCollectionID = $collectionID',
+      ),
+    );
     return count;
   }
 
   Future<int> fileCountWithVisibility(int visibility, int ownerID) async {
     final db = await instance.database;
-    var count = Sqflite.firstIntValue(await db.rawQuery(
-        'SELECT COUNT(*) FROM $table where $columnMMdVisibility = $visibility AND $columnOwnerID = $ownerID',),);
+    var count = Sqflite.firstIntValue(
+      await db.rawQuery(
+        'SELECT COUNT(*) FROM $table where $columnMMdVisibility = $visibility AND $columnOwnerID = $ownerID',
+      ),
+    );
     return count;
   }
 
@@ -891,7 +937,8 @@ class FilesDB {
 
   Future<List<File>> getLatestLocalFiles() async {
     final db = await instance.database;
-    final rows = await db.rawQuery('''
+    final rows = await db.rawQuery(
+      '''
       SELECT $table.*
       FROM $table
       INNER JOIN
@@ -903,7 +950,8 @@ class FilesDB {
         ) latest_files
         ON $table.$columnDeviceFolder = latest_files.$columnDeviceFolder
         AND $table.$columnCreationTime = latest_files.max_creation_time;
-    ''',);
+    ''',
+    );
     final files = _convertToFiles(rows);
     // TODO: Do this de-duplication within the SQL Query
     final folderMap = <String, File>{};
@@ -920,7 +968,8 @@ class FilesDB {
 
   Future<List<File>> getLatestCollectionFiles() async {
     final db = await instance.database;
-    final rows = await db.rawQuery('''
+    final rows = await db.rawQuery(
+      '''
       SELECT $table.*
       FROM $table
       INNER JOIN
@@ -932,7 +981,8 @@ class FilesDB {
         ) latest_files
         ON $table.$columnCollectionID = latest_files.$columnCollectionID
         AND $table.$columnCreationTime = latest_files.max_creation_time;
-    ''',);
+    ''',
+    );
     final files = _convertToFiles(rows);
     // TODO: Do this de-duplication within the SQL Query
     final collectionMap = <int, File>{};
@@ -965,12 +1015,14 @@ class FilesDB {
 
   Future<Map<String, int>> getFileCountInDeviceFolders() async {
     final db = await instance.database;
-    final rows = await db.rawQuery('''
+    final rows = await db.rawQuery(
+      '''
       SELECT COUNT($columnGeneratedID) as count, $columnDeviceFolder
       FROM $table
       WHERE $columnLocalID IS NOT NULL
       GROUP BY $columnDeviceFolder
-    ''',);
+    ''',
+    );
     final result = <String, int>{};
     for (final row in rows) {
       result[row[columnDeviceFolder]] = row["count"];
@@ -1005,16 +1057,20 @@ class FilesDB {
     }
     inParam = inParam.substring(0, inParam.length - 1);
     final db = await instance.database;
-    await db.rawUpdate('''
+    await db.rawUpdate(
+      '''
       UPDATE $table
       SET $columnUpdationTime = NULL
       WHERE $columnLocalID IN ($inParam)
       AND ($columnLatitude IS NULL OR $columnLongitude IS NULL OR $columnLongitude = 0.0 or $columnLongitude = 0.0);
-    ''',);
+    ''',
+    );
   }
 
   Future<bool> doesFileExistInCollection(
-      int uploadedFileID, int collectionID,) async {
+    int uploadedFileID,
+    int collectionID,
+  ) async {
     final db = await instance.database;
     final rows = await db.query(
       table,

+ 17 - 8
lib/db/ignored_files_db.dart

@@ -22,7 +22,8 @@ class IgnoredFilesDB {
   static final columnReason = 'reason';
 
   Future _onCreate(Database db, int version) async {
-    await db.execute('''
+    await db.execute(
+      '''
         CREATE TABLE $tableName (
           $columnLocalID TEXT NOT NULL,
           $columnTitle TEXT NOT NULL,
@@ -32,7 +33,8 @@ class IgnoredFilesDB {
         );
       CREATE INDEX IF NOT EXISTS local_id_index ON $tableName($columnLocalID);
       CREATE INDEX IF NOT EXISTS device_folder_index ON $tableName($columnDeviceFolder);
-      ''',);
+      ''',
+    );
   }
 
   IgnoredFilesDB._privateConstructor();
@@ -85,10 +87,13 @@ class IgnoredFilesDB {
     await batch.commit(noResult: true);
     final endTime = DateTime.now();
     final duration = Duration(
-        microseconds:
-            endTime.microsecondsSinceEpoch - startTime.microsecondsSinceEpoch,);
-    _logger.info("Batch insert of ${ignoredFiles.length} "
-        "took ${duration.inMilliseconds} ms.",);
+      microseconds:
+          endTime.microsecondsSinceEpoch - startTime.microsecondsSinceEpoch,
+    );
+    _logger.info(
+      "Batch insert of ${ignoredFiles.length} "
+      "took ${duration.inMilliseconds} ms.",
+    );
   }
 
   Future<List<IgnoredFile>> getAll() async {
@@ -102,8 +107,12 @@ class IgnoredFilesDB {
   }
 
   IgnoredFile _getIgnoredFileFromRow(Map<String, dynamic> row) {
-    return IgnoredFile(row[columnLocalID], row[columnTitle],
-        row[columnDeviceFolder], row[columnReason],);
+    return IgnoredFile(
+      row[columnLocalID],
+      row[columnTitle],
+      row[columnDeviceFolder],
+      row[columnReason],
+    );
   }
 
   Map<String, dynamic> _getRowForIgnoredFile(IgnoredFile ignoredFile) {

+ 9 - 4
lib/db/memories_db.dart

@@ -35,12 +35,14 @@ class MemoriesDB {
   }
 
   Future _onCreate(Database db, int version) async {
-    await db.execute('''
+    await db.execute(
+      '''
                 CREATE TABLE $table (
                   $columnFileID INTEGER PRIMARY KEY NOT NULL,
                   $columnSeenTime TEXT NOT NULL
                 )
-                ''',);
+                ''',
+    );
   }
 
   Future<void> clearTable() async {
@@ -59,8 +61,11 @@ class MemoriesDB {
 
   Future<int> markMemoryAsSeen(Memory memory, int timestamp) async {
     final db = await instance.database;
-    return await db.insert(table, _getRowForSeenMemory(memory, timestamp),
-        conflictAlgorithm: ConflictAlgorithm.replace,);
+    return await db.insert(
+      table,
+      _getRowForSeenMemory(memory, timestamp),
+      conflictAlgorithm: ConflictAlgorithm.replace,
+    );
   }
 
   Future<Map<int, int>> getSeenTimes() async {

+ 16 - 9
lib/db/public_keys_db.dart

@@ -36,12 +36,14 @@ class PublicKeysDB {
   }
 
   Future _onCreate(Database db, int version) async {
-    await db.execute('''
+    await db.execute(
+      '''
                 CREATE TABLE $table (
                   $columnEmail TEXT PRIMARY KEY NOT NULL,
                   $columnPublicKey TEXT NOT NULL
                 )
-                ''',);
+                ''',
+    );
   }
 
   Future<void> clearTable() async {
@@ -51,17 +53,22 @@ class PublicKeysDB {
 
   Future<int> setKey(PublicKey key) async {
     final db = await instance.database;
-    return db.insert(table, _getRow(key),
-        conflictAlgorithm: ConflictAlgorithm.replace,);
+    return db.insert(
+      table,
+      _getRow(key),
+      conflictAlgorithm: ConflictAlgorithm.replace,
+    );
   }
 
   Future<List<PublicKey>> searchByEmail(String email) async {
     final db = await instance.database;
-    return _convertRows(await db.query(
-      table,
-      where: '$columnEmail LIKE ?',
-      whereArgs: ['%$email%'],
-    ),);
+    return _convertRows(
+      await db.query(
+        table,
+        where: '$columnEmail LIKE ?',
+        whereArgs: ['%$email%'],
+      ),
+    );
   }
 
   Map<String, dynamic> _getRow(PublicKey key) {

+ 27 - 14
lib/db/trash_db.dart

@@ -42,7 +42,8 @@ class TrashDB {
   static final columnPubMMdVersion = 'pub_mmd_ver';
 
   Future _onCreate(Database db, int version) async {
-    await db.execute('''
+    await db.execute(
+      '''
         CREATE TABLE $tableName (
           $columnUploadedFileID INTEGER PRIMARY KEY NOT NULL,
           $columnCollectionID INTEGER NOT NULL,
@@ -65,7 +66,8 @@ class TrashDB {
       CREATE INDEX IF NOT EXISTS creation_time_index ON $tableName($columnCreationTime); 
       CREATE INDEX IF NOT EXISTS delete_by_time_index ON $tableName($columnTrashDeleteBy);
       CREATE INDEX IF NOT EXISTS updated_at_time_index ON $tableName($columnTrashUpdatedAt);
-      ''',);
+      ''',
+    );
   }
 
   TrashDB._privateConstructor();
@@ -101,8 +103,11 @@ class TrashDB {
   // getRecentlyTrashedFile returns the file which was trashed recently
   Future<TrashFile> getRecentlyTrashedFile() async {
     final db = await instance.database;
-    var rows = await db.query(tableName,
-        orderBy: '$columnTrashDeleteBy DESC', limit: 1,);
+    var rows = await db.query(
+      tableName,
+      orderBy: '$columnTrashDeleteBy DESC',
+      limit: 1,
+    );
     if (rows == null || rows.isEmpty) {
       return null;
     }
@@ -112,7 +117,8 @@ class TrashDB {
   Future<int> count() async {
     final db = await instance.database;
     var count = Sqflite.firstIntValue(
-        await db.rawQuery('SELECT COUNT(*) FROM $tableName'),);
+      await db.rawQuery('SELECT COUNT(*) FROM $tableName'),
+    );
     return count;
   }
 
@@ -137,13 +143,16 @@ class TrashDB {
     await batch.commit(noResult: true);
     final endTime = DateTime.now();
     final duration = Duration(
-        microseconds:
-            endTime.microsecondsSinceEpoch - startTime.microsecondsSinceEpoch,);
-    _logger.info("Batch insert of " +
-        trashFiles.length.toString() +
-        " took " +
-        duration.inMilliseconds.toString() +
-        "ms.",);
+      microseconds:
+          endTime.microsecondsSinceEpoch - startTime.microsecondsSinceEpoch,
+    );
+    _logger.info(
+      "Batch insert of " +
+          trashFiles.length.toString() +
+          " took " +
+          duration.inMilliseconds.toString() +
+          "ms.",
+    );
   }
 
   Future<int> insert(TrashFile trash) async {
@@ -173,8 +182,12 @@ class TrashDB {
     );
   }
 
-  Future<FileLoadResult> getTrashedFiles(int startTime, int endTime,
-      {int limit, bool asc,}) async {
+  Future<FileLoadResult> getTrashedFiles(
+    int startTime,
+    int endTime, {
+    int limit,
+    bool asc,
+  }) async {
     final db = await instance.database;
     final order = (asc ?? false ? 'ASC' : 'DESC');
     final results = await db.query(

+ 4 - 2
lib/db/upload_locks_db.dart

@@ -34,13 +34,15 @@ class UploadLocksDB {
   }
 
   Future _onCreate(Database db, int version) async {
-    await db.execute('''
+    await db.execute(
+      '''
                 CREATE TABLE $_table (
                   $_columnID TEXT PRIMARY KEY NOT NULL,
                   $_columnOwner TEXT NOT NULL,
                   $_columnTime TEXT NOT NULL
                 )
-                ''',);
+                ''',
+    );
   }
 
   Future<void> clearTable() async {

+ 34 - 27
lib/ente_theme_data.dart

@@ -31,10 +31,10 @@ extension CustomColorScheme on ColorScheme {
 
   // todo: use brightness == Brightness.light for changing color for dark/light theme
   ButtonStyle get optionalActionButtonStyle => buildElevatedButtonThemeData(
-          onPrimary: Color(0xFF777777),
-          primary: Color(0xFFF0F0F0),
-          elevation: 0,)
-      .style;
+        onPrimary: Color(0xFF777777),
+        primary: Color(0xFFF0F0F0),
+        elevation: 0,
+      ).style;
 
   Color get recoveryKeyBoxColor => brightness == Brightness.light
       ? Color.fromRGBO(49, 155, 86, 0.2)
@@ -65,11 +65,13 @@ extension CustomColorScheme on ColorScheme {
       ? DatePickerTheme(
           backgroundColor: Colors.white,
           itemStyle: TextStyle(color: Colors.black),
-          cancelStyle: TextStyle(color: Colors.black),)
+          cancelStyle: TextStyle(color: Colors.black),
+        )
       : DatePickerTheme(
           backgroundColor: Colors.black,
           itemStyle: TextStyle(color: Colors.white),
-          cancelStyle: TextStyle(color: Colors.white),);
+          cancelStyle: TextStyle(color: Colors.white),
+        );
 
   Color get stepProgressUnselectedColor => brightness == Brightness.light
       ? Color.fromRGBO(196, 196, 196, 0.6)
@@ -123,8 +125,12 @@ extension CustomColorScheme on ColorScheme {
       : Color.fromRGBO(100, 100, 100, 1);
 }
 
-OutlinedButtonThemeData buildOutlinedButtonThemeData(
-    {Color bgDisabled, Color bgEnabled, Color fgDisabled, Color fgEnabled,}) {
+OutlinedButtonThemeData buildOutlinedButtonThemeData({
+  Color bgDisabled,
+  Color bgEnabled,
+  Color fgDisabled,
+  Color fgEnabled,
+}) {
   return OutlinedButtonThemeData(
     style: OutlinedButton.styleFrom(
       shape: RoundedRectangleBorder(
@@ -159,27 +165,28 @@ OutlinedButtonThemeData buildOutlinedButtonThemeData(
   );
 }
 
-ElevatedButtonThemeData buildElevatedButtonThemeData(
-    {@required Color onPrimary, // text button color
-    @required Color primary,
-    double elevation = 2, // background color of button
-    }) {
+ElevatedButtonThemeData buildElevatedButtonThemeData({
+  @required Color onPrimary, // text button color
+  @required Color primary,
+  double elevation = 2, // background color of button
+}) {
   return ElevatedButtonThemeData(
-      style: ElevatedButton.styleFrom(
-    elevation: elevation,
-    onPrimary: onPrimary,
-    primary: primary,
-    alignment: Alignment.center,
-    textStyle: TextStyle(
-      fontWeight: FontWeight.w600,
-      fontFamily: 'Inter-SemiBold',
-      fontSize: 18,
-    ),
-    padding: EdgeInsets.symmetric(vertical: 18),
-    shape: const RoundedRectangleBorder(
-      borderRadius: BorderRadius.all(Radius.circular(8)),
+    style: ElevatedButton.styleFrom(
+      elevation: elevation,
+      onPrimary: onPrimary,
+      primary: primary,
+      alignment: Alignment.center,
+      textStyle: TextStyle(
+        fontWeight: FontWeight.w600,
+        fontFamily: 'Inter-SemiBold',
+        fontSize: 18,
+      ),
+      padding: EdgeInsets.symmetric(vertical: 18),
+      shape: const RoundedRectangleBorder(
+        borderRadius: BorderRadius.all(Radius.circular(8)),
+      ),
     ),
-  ),);
+  );
 }
 
 TextStyle gradientButtonTextTheme() {

+ 50 - 35
lib/main.dart

@@ -58,13 +58,15 @@ Future<void> _runInForeground() async {
     _logger.info("Starting app in foreground");
     await _init(false, via: 'mainMethod');
     _scheduleFGSync('appStart in FG');
-    runApp(AppLock(
-      builder: (args) => EnteApp(_runBackgroundTask, _killBGTask),
-      lockScreen: LockScreen(),
-      enabled: Configuration.instance.shouldShowLockScreen(),
-      lightTheme: lightThemeData,
-      darkTheme: darkThemeData,
-    ),);
+    runApp(
+      AppLock(
+        builder: (args) => EnteApp(_runBackgroundTask, _killBGTask),
+        lockScreen: LockScreen(),
+        enabled: Configuration.instance.shouldShowLockScreen(),
+        lightTheme: lightThemeData,
+        darkTheme: darkThemeData,
+      ),
+    );
   });
 }
 
@@ -74,10 +76,13 @@ Future<void> _runBackgroundTask(String taskId) async {
     await _sync('bgTaskActiveProcess');
     BackgroundFetch.finish(taskId);
   } else {
-    _runWithLogs(() async {
-      _logger.info("run background task");
-      _runInBackground(taskId);
-    }, prefix: "[bg]",);
+    _runWithLogs(
+      () async {
+        _logger.info("run background task");
+        _runInBackground(taskId);
+      },
+      prefix: "[bg]",
+    );
   }
 }
 
@@ -139,7 +144,8 @@ Future<void> _init(bool isBackground, {String via = ''}) async {
   if (Platform.isIOS) {
     PushService.instance.init().then((_) {
       FirebaseMessaging.onBackgroundMessage(
-          _firebaseMessagingBackgroundHandler,);
+        _firebaseMessagingBackgroundHandler,
+      );
     });
   }
   FeatureFlagService.instance.init();
@@ -160,22 +166,25 @@ Future<void> _sync(String caller) async {
 }
 
 Future _runWithLogs(Function() function, {String prefix = ""}) async {
-  await SuperLogging.main(LogConfig(
-    body: function,
-    logDirPath: (await getTemporaryDirectory()).path + "/logs",
-    maxLogFiles: 5,
-    sentryDsn: kDebugMode ? kSentryDebugDSN : kSentryDSN,
-    tunnel: kSentryTunnel,
-    enableInDebugMode: true,
-    prefix: prefix,
-  ),);
+  await SuperLogging.main(
+    LogConfig(
+      body: function,
+      logDirPath: (await getTemporaryDirectory()).path + "/logs",
+      maxLogFiles: 5,
+      sentryDsn: kDebugMode ? kSentryDebugDSN : kSentryDSN,
+      tunnel: kSentryTunnel,
+      enableInDebugMode: true,
+      prefix: prefix,
+    ),
+  );
 }
 
 Future<void> _scheduleHeartBeat(bool isBackground) async {
   final prefs = await SharedPreferences.getInstance();
   await prefs.setInt(
-      isBackground ? kLastBGTaskHeartBeatTime : kLastFGTaskHeartBeatTime,
-      DateTime.now().microsecondsSinceEpoch,);
+    isBackground ? kLastBGTaskHeartBeatTime : kLastFGTaskHeartBeatTime,
+    DateTime.now().microsecondsSinceEpoch,
+  );
   Future.delayed(kHeartBeatFrequency, () async {
     _scheduleHeartBeat(isBackground);
   });
@@ -209,7 +218,9 @@ Future<bool> _isRunningInForeground() async {
 
 Future<void> _killBGTask([String taskId]) async {
   await UploadLocksDB.instance.releaseLocksAcquiredByOwnerBefore(
-      ProcessType.background.toString(), DateTime.now().microsecondsSinceEpoch,);
+    ProcessType.background.toString(),
+    DateTime.now().microsecondsSinceEpoch,
+  );
   final prefs = await SharedPreferences.getInstance();
   prefs.remove(kLastBGTaskHeartBeatTime);
   if (taskId != null) {
@@ -222,22 +233,26 @@ Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
   bool isInForeground = AppLifecycleService.instance.isForeground;
   if (_isProcessRunning) {
     _logger.info(
-        "Background push received when app is alive and runningInFS: $isRunningInFG inForeground: $isInForeground",);
+      "Background push received when app is alive and runningInFS: $isRunningInFG inForeground: $isInForeground",
+    );
     if (PushService.shouldSync(message)) {
       await _sync('firebaseBgSyncActiveProcess');
     }
   } else {
     // App is dead
-    _runWithLogs(() async {
-      _logger.info("Background push received");
-      if (Platform.isIOS) {
-        _scheduleSuicide(kBGPushTimeout); // To prevent OS from punishing us
-      }
-      await _init(true, via: 'firebasePush');
-      if (PushService.shouldSync(message)) {
-        await _sync('firebaseBgSyncNoActiveProcess');
-      }
-    }, prefix: "[fbg]",);
+    _runWithLogs(
+      () async {
+        _logger.info("Background push received");
+        if (Platform.isIOS) {
+          _scheduleSuicide(kBGPushTimeout); // To prevent OS from punishing us
+        }
+        await _init(true, via: 'firebasePush');
+        if (PushService.shouldSync(message)) {
+          await _sync('firebaseBgSyncNoActiveProcess');
+        }
+      },
+      prefix: "[fbg]",
+    );
   }
 }
 

+ 2 - 1
lib/models/billing_plan.dart

@@ -33,7 +33,8 @@ class BillingPlans {
 
     return BillingPlans(
       plans: List<BillingPlan>.from(
-          map['plans']?.map((x) => BillingPlan.fromMap(x)),),
+        map['plans']?.map((x) => BillingPlan.fromMap(x)),
+      ),
       freePlan: FreePlan.fromMap(map['freePlan']),
     );
   }

+ 26 - 23
lib/models/collection.dart

@@ -68,22 +68,23 @@ class Collection {
     }
   }
 
-  Collection copyWith(
-      {int id,
-      User owner,
-      String encryptedKey,
-      String keyDecryptionNonce,
-      String name,
-      String encryptedName,
-      String nameDecryptionNonce,
-      CollectionType type,
-      CollectionAttributes attributes,
-      List<User> sharees,
-      List<PublicURL> publicURLs,
-      int updationTime,
-      bool isDeleted,
-      String mMdEncodedJson,
-      int mMdVersion,}) {
+  Collection copyWith({
+    int id,
+    User owner,
+    String encryptedKey,
+    String keyDecryptionNonce,
+    String name,
+    String encryptedName,
+    String nameDecryptionNonce,
+    CollectionType type,
+    CollectionAttributes attributes,
+    List<User> sharees,
+    List<PublicURL> publicURLs,
+    int updationTime,
+    bool isDeleted,
+    String mMdEncodedJson,
+    int mMdVersion,
+  }) {
     Collection result = Collection(
       id ?? this.id,
       owner ?? this.owner,
@@ -131,7 +132,8 @@ class Collection {
         (map['publicURLs'] == null || map['publicURLs'].length == 0)
             ? <PublicURL>[]
             : List<PublicURL>.from(
-                map['publicURLs'].map((x) => PublicURL.fromMap(x)),);
+                map['publicURLs'].map((x) => PublicURL.fromMap(x)),
+              );
     return Collection(
       map['id'],
       User.fromMap(map['owner']),
@@ -338,12 +340,13 @@ class PublicURL {
   bool enableDownload = true;
   bool passwordEnabled = false;
 
-  PublicURL(
-      {this.url,
-      this.deviceLimit,
-      this.validTill,
-      this.enableDownload,
-      this.passwordEnabled,});
+  PublicURL({
+    this.url,
+    this.deviceLimit,
+    this.validTill,
+    this.enableDownload,
+    this.passwordEnabled,
+  });
 
   Map<String, dynamic> toMap() {
     return {

+ 2 - 1
lib/models/duplicate_files.dart

@@ -9,7 +9,8 @@ class DuplicateFilesResponse {
   factory DuplicateFilesResponse.fromMap(Map<String, dynamic> map) {
     return DuplicateFilesResponse(
       List<DuplicateItems>.from(
-          map['duplicates']?.map((x) => DuplicateItems.fromMap(x)),),
+        map['duplicates']?.map((x) => DuplicateItems.fromMap(x)),
+      ),
     );
   }
 

+ 6 - 5
lib/models/file.dart

@@ -71,11 +71,12 @@ class File {
     if (file.creationTime == 0) {
       try {
         final parsedDateTime = DateTime.parse(
-            basenameWithoutExtension(file.title)
-                .replaceAll("IMG_", "")
-                .replaceAll("VID_", "")
-                .replaceAll("DCIM_", "")
-                .replaceAll("_", " "),);
+          basenameWithoutExtension(file.title)
+              .replaceAll("IMG_", "")
+              .replaceAll("VID_", "")
+              .replaceAll("DCIM_", "")
+              .replaceAll("_", " "),
+        );
         file.creationTime = parsedDateTime.microsecondsSinceEpoch;
       } catch (e) {
         file.creationTime = asset.modifiedDateTime.microsecondsSinceEpoch;

+ 6 - 2
lib/models/ignored_file.dart

@@ -22,7 +22,11 @@ class IgnoredFile {
       return null;
     }
 
-    return IgnoredFile(trashFile.localID, trashFile.title,
-        trashFile.deviceFolder, kIgnoreReasonTrash,);
+    return IgnoredFile(
+      trashFile.localID,
+      trashFile.title,
+      trashFile.deviceFolder,
+      kIgnoreReasonTrash,
+    );
   }
 }

+ 2 - 1
lib/models/magic_metadata.dart

@@ -74,7 +74,8 @@ class CollectionMagicMetadata {
   factory CollectionMagicMetadata.fromEncodedJson(String encodedJson) =>
       CollectionMagicMetadata.fromJson(jsonDecode(encodedJson));
 
-  factory CollectionMagicMetadata.fromJson(dynamic json) => CollectionMagicMetadata.fromMap(json);
+  factory CollectionMagicMetadata.fromJson(dynamic json) =>
+      CollectionMagicMetadata.fromMap(json);
 
   Map<String, dynamic> toJson() {
     final map = <String, dynamic>{};

+ 3 - 3
lib/models/subscription.dart

@@ -135,7 +135,8 @@ class Attributes {
 
   Attributes({
     this.isCancelled,
-    this.customerID,});
+    this.customerID,
+  });
 
   Attributes.fromJson(dynamic json) {
     isCancelled = json["isCancelled"];
@@ -153,5 +154,4 @@ class Attributes {
   String toString() {
     return 'Attributes{isCancelled: $isCancelled, customerID: $customerID}';
   }
-
-}
+}

+ 0 - 1
lib/models/trash_file.dart

@@ -1,7 +1,6 @@
 import 'package:photos/models/file.dart';
 
 class TrashFile extends File {
-
   // time when file was put in the trash for first time
   int createdAt;
 

+ 1 - 0
lib/models/update_share_url_request.dart

@@ -0,0 +1 @@
+

+ 7 - 5
lib/models/user_details.dart

@@ -40,10 +40,11 @@ class UserDetails {
 
   int getFreeStorage() {
     return max(
-        isPartOfFamily()
-            ? (familyData.storage - familyData.getTotalUsage())
-            : (subscription.storage - (usage)),
-        0,);
+      isPartOfFamily()
+          ? (familyData.storage - familyData.getTotalUsage())
+          : (subscription.storage - (usage)),
+      0,
+    );
   }
 
   int getTotalStorage() {
@@ -118,7 +119,8 @@ class FamilyData {
     }
     assert(map['members'] != null && map['members'].length >= 0);
     final members = List<FamilyMember>.from(
-        map['members'].map((x) => FamilyMember.fromMap(x)),);
+      map['members'].map((x) => FamilyMember.fromMap(x)),
+    );
     return FamilyData(
       members,
       map['storage'] as int,

+ 15 - 9
lib/services/billing_service.dart

@@ -11,11 +11,15 @@ import 'package:photos/models/billing_plan.dart';
 import 'package:photos/models/subscription.dart';
 
 const kWebPaymentRedirectUrl = "https://payments.ente.io/frameRedirect";
-const kWebPaymentBaseEndpoint = String.fromEnvironment("web-payment",
-    defaultValue: "https://payments.ente.io",);
+const kWebPaymentBaseEndpoint = String.fromEnvironment(
+  "web-payment",
+  defaultValue: "https://payments.ente.io",
+);
 
-const kFamilyPlanManagementUrl = String.fromEnvironment("web-family",
-    defaultValue: "https://family.ente.io",);
+const kFamilyPlanManagementUrl = String.fromEnvironment(
+  "web-family",
+  defaultValue: "https://family.ente.io",
+);
 
 class BillingService {
   BillingService._privateConstructor();
@@ -42,9 +46,10 @@ class BillingService {
       }
       for (final purchase in purchases) {
         if (purchase.status == PurchaseStatus.purchased) {
-          verifySubscription(purchase.productID,
-                  purchase.verificationData.serverVerificationData,)
-              .then((response) {
+          verifySubscription(
+            purchase.productID,
+            purchase.verificationData.serverVerificationData,
+          ).then((response) {
             if (response != null) {
               InAppPurchaseConnection.instance.completePurchase(purchase);
             }
@@ -166,8 +171,9 @@ class BillingService {
     }
   }
 
-  Future<String> getStripeCustomerPortalUrl(
-      {String endpoint = kWebPaymentRedirectUrl,}) async {
+  Future<String> getStripeCustomerPortalUrl({
+    String endpoint = kWebPaymentRedirectUrl,
+  }) async {
     try {
       final response = await _dio.get(
         _config.getHttpEndpoint() + "/billing/stripe/customer-portal",

+ 153 - 85
lib/services/collections_service.dart

@@ -192,7 +192,9 @@ class CollectionsService {
 
   Future<void> share(int collectionID, String email, String publicKey) async {
     final encryptedKey = CryptoUtil.sealSync(
-        getCollectionKey(collectionID), Sodium.base642bin(publicKey),);
+      getCollectionKey(collectionID),
+      Sodium.base642bin(publicKey),
+    );
     try {
       await _dio.post(
         Configuration.instance.getHttpEndpoint() + "/collections/share",
@@ -202,7 +204,8 @@ class CollectionsService {
           "encryptedKey": Sodium.bin2base64(encryptedKey),
         },
         options: Options(
-            headers: {"X-Auth-Token": Configuration.instance.getToken()},),
+          headers: {"X-Auth-Token": Configuration.instance.getToken()},
+        ),
       );
     } on DioError catch (e) {
       if (e.response.statusCode == 402) {
@@ -222,7 +225,8 @@ class CollectionsService {
           "email": email,
         },
         options: Options(
-            headers: {"X-Auth-Token": Configuration.instance.getToken()},),
+          headers: {"X-Auth-Token": Configuration.instance.getToken()},
+        ),
       );
       _collectionIDToCollections[collectionID]
           .sharees
@@ -253,20 +257,26 @@ class CollectionsService {
   Uint8List _getDecryptedKey(Collection collection) {
     final encryptedKey = Sodium.base642bin(collection.encryptedKey);
     if (collection.owner.id == _config.getUserID()) {
-      return CryptoUtil.decryptSync(encryptedKey, _config.getKey(),
-          Sodium.base642bin(collection.keyDecryptionNonce),);
+      return CryptoUtil.decryptSync(
+        encryptedKey,
+        _config.getKey(),
+        Sodium.base642bin(collection.keyDecryptionNonce),
+      );
     } else {
       return CryptoUtil.openSealSync(
-          encryptedKey,
-          Sodium.base642bin(_config.getKeyAttributes().publicKey),
-          _config.getSecretKey(),);
+        encryptedKey,
+        Sodium.base642bin(_config.getKeyAttributes().publicKey),
+        _config.getSecretKey(),
+      );
     }
   }
 
   Future<void> rename(Collection collection, String newName) async {
     try {
       final encryptedName = CryptoUtil.encryptSync(
-          utf8.encode(newName), getCollectionKey(collection.id),);
+        utf8.encode(newName),
+        getCollectionKey(collection.id),
+      );
       await _dio.post(
         Configuration.instance.getHttpEndpoint() + "/collections/rename",
         data: {
@@ -275,7 +285,8 @@ class CollectionsService {
           "nameDecryptionNonce": Sodium.bin2base64(encryptedName.nonce)
         },
         options: Options(
-            headers: {"X-Auth-Token": Configuration.instance.getToken()},),
+          headers: {"X-Auth-Token": Configuration.instance.getToken()},
+        ),
       );
       // trigger sync to fetch the latest name from server
       sync();
@@ -286,7 +297,9 @@ class CollectionsService {
   }
 
   Future<void> updateMagicMetadata(
-      Collection collection, Map<String, dynamic> newMetadataUpdate,) async {
+    Collection collection,
+    Map<String, dynamic> newMetadataUpdate,
+  ) async {
     final int ownerID = Configuration.instance.getUserID();
     try {
       if (collection.owner.id != ownerID) {
@@ -307,7 +320,9 @@ class CollectionsService {
 
       final key = getCollectionKey(collection.id);
       final encryptedMMd = await CryptoUtil.encryptChaCha(
-          utf8.encode(jsonEncode(jsonToUpdate)), key,);
+        utf8.encode(jsonEncode(jsonToUpdate)),
+        key,
+      );
       // for required field, the json validator on golang doesn't treat 0 as valid
       // value. Instead of changing version to ptr, decided to start version with 1.
       int currentVersion = max(collection.mMdVersion, 1);
@@ -325,7 +340,8 @@ class CollectionsService {
             "/collections/magic-metadata",
         data: params,
         options: Options(
-            headers: {"X-Auth-Token": Configuration.instance.getToken()},),
+          headers: {"X-Auth-Token": Configuration.instance.getToken()},
+        ),
       );
       collection.mMdVersion = currentVersion + 1;
       _cacheCollectionAttributes(collection);
@@ -351,7 +367,8 @@ class CollectionsService {
           "collectionID": collection.id,
         },
         options: Options(
-            headers: {"X-Auth-Token": Configuration.instance.getToken()},),
+          headers: {"X-Auth-Token": Configuration.instance.getToken()},
+        ),
       );
       collection.publicURLs?.add(PublicURL.fromMap(response.data["result"]));
       await _db.insert(List.from([collection]));
@@ -369,14 +386,17 @@ class CollectionsService {
   }
 
   Future<void> updateShareUrl(
-      Collection collection, Map<String, dynamic> prop,) async {
+    Collection collection,
+    Map<String, dynamic> prop,
+  ) async {
     prop.putIfAbsent('collectionID', () => collection.id);
     try {
       final response = await _dio.put(
         Configuration.instance.getHttpEndpoint() + "/collections/share-url",
         data: json.encode(prop),
         options: Options(
-            headers: {"X-Auth-Token": Configuration.instance.getToken()},),
+          headers: {"X-Auth-Token": Configuration.instance.getToken()},
+        ),
       );
       // remove existing url information
       collection.publicURLs?.clear();
@@ -426,7 +446,8 @@ class CollectionsService {
           "source": AppLifecycleService.instance.isForeground ? "fg" : "bg",
         },
         options: Options(
-            headers: {"X-Auth-Token": Configuration.instance.getToken()},),
+          headers: {"X-Auth-Token": Configuration.instance.getToken()},
+        ),
       );
       final List<Collection> collections = [];
       if (response != null) {
@@ -436,13 +457,15 @@ class CollectionsService {
           if (collectionData['magicMetadata'] != null) {
             final decryptionKey = _getDecryptedKey(collection);
             final utfEncodedMmd = await CryptoUtil.decryptChaCha(
-                Sodium.base642bin(collectionData['magicMetadata']['data']),
-                decryptionKey,
-                Sodium.base642bin(collectionData['magicMetadata']['header']),);
+              Sodium.base642bin(collectionData['magicMetadata']['data']),
+              decryptionKey,
+              Sodium.base642bin(collectionData['magicMetadata']['header']),
+            );
             collection.mMdEncodedJson = utf8.decode(utfEncodedMmd);
             collection.mMdVersion = collectionData['magicMetadata']['version'];
             collection.magicMetadata = CollectionMagicMetadata.fromEncodedJson(
-                collection.mMdEncodedJson,);
+              collection.mMdEncodedJson,
+            );
           }
           collections.add(collection);
         }
@@ -464,20 +487,22 @@ class CollectionsService {
     final key = CryptoUtil.generateKey();
     final encryptedKeyData = CryptoUtil.encryptSync(key, _config.getKey());
     final encryptedName = CryptoUtil.encryptSync(utf8.encode(albumName), key);
-    final collection = await createAndCacheCollection(Collection(
-      null,
-      null,
-      Sodium.bin2base64(encryptedKeyData.encryptedData),
-      Sodium.bin2base64(encryptedKeyData.nonce),
-      null,
-      Sodium.bin2base64(encryptedName.encryptedData),
-      Sodium.bin2base64(encryptedName.nonce),
-      CollectionType.album,
-      CollectionAttributes(),
-      null,
-      null,
-      null,
-    ),);
+    final collection = await createAndCacheCollection(
+      Collection(
+        null,
+        null,
+        Sodium.bin2base64(encryptedKeyData.encryptedData),
+        Sodium.bin2base64(encryptedKeyData.nonce),
+        null,
+        Sodium.bin2base64(encryptedName.encryptedData),
+        Sodium.bin2base64(encryptedName.nonce),
+        CollectionType.album,
+        CollectionAttributes(),
+        null,
+        null,
+        null,
+      ),
+    );
     return collection;
   }
 
@@ -487,7 +512,8 @@ class CollectionsService {
       final response = await _dio.get(
         Configuration.instance.getHttpEndpoint() + "/collections/$collectionID",
         options: Options(
-            headers: {"X-Auth-Token": Configuration.instance.getToken()},),
+          headers: {"X-Auth-Token": Configuration.instance.getToken()},
+        ),
       );
       assert(response != null && response.data != null);
       final collectionData = response.data["collection"];
@@ -495,9 +521,10 @@ class CollectionsService {
       if (collectionData['magicMetadata'] != null) {
         final decryptionKey = _getDecryptedKey(collection);
         final utfEncodedMmd = await CryptoUtil.decryptChaCha(
-            Sodium.base642bin(collectionData['magicMetadata']['data']),
-            decryptionKey,
-            Sodium.base642bin(collectionData['magicMetadata']['header']),);
+          Sodium.base642bin(collectionData['magicMetadata']['data']),
+          decryptionKey,
+          Sodium.base642bin(collectionData['magicMetadata']['header']),
+        );
         collection.mMdEncodedJson = utf8.decode(utfEncodedMmd);
         collection.mMdVersion = collectionData['magicMetadata']['version'];
         collection.magicMetadata =
@@ -523,38 +550,43 @@ class CollectionsService {
     final key = CryptoUtil.generateKey();
     final encryptedKeyData = CryptoUtil.encryptSync(key, _config.getKey());
     final encryptedPath = CryptoUtil.encryptSync(utf8.encode(path), key);
-    final collection = await createAndCacheCollection(Collection(
-      null,
-      null,
-      Sodium.bin2base64(encryptedKeyData.encryptedData),
-      Sodium.bin2base64(encryptedKeyData.nonce),
-      null,
-      Sodium.bin2base64(encryptedPath.encryptedData),
-      Sodium.bin2base64(encryptedPath.nonce),
-      CollectionType.folder,
-      CollectionAttributes(
-        encryptedPath: Sodium.bin2base64(encryptedPath.encryptedData),
-        pathDecryptionNonce: Sodium.bin2base64(encryptedPath.nonce),
-        version: 1,
+    final collection = await createAndCacheCollection(
+      Collection(
+        null,
+        null,
+        Sodium.bin2base64(encryptedKeyData.encryptedData),
+        Sodium.bin2base64(encryptedKeyData.nonce),
+        null,
+        Sodium.bin2base64(encryptedPath.encryptedData),
+        Sodium.bin2base64(encryptedPath.nonce),
+        CollectionType.folder,
+        CollectionAttributes(
+          encryptedPath: Sodium.bin2base64(encryptedPath.encryptedData),
+          pathDecryptionNonce: Sodium.bin2base64(encryptedPath.nonce),
+          version: 1,
+        ),
+        null,
+        null,
+        null,
       ),
-      null,
-      null,
-      null,
-    ),);
+    );
     return collection;
   }
 
   Future<void> addToCollection(int collectionID, List<File> files) async {
     final containsUploadedFile = files.firstWhere(
-            (element) => element.uploadedFileID != null,
-            orElse: () => null,) !=
+          (element) => element.uploadedFileID != null,
+          orElse: () => null,
+        ) !=
         null;
     if (containsUploadedFile) {
       final existingFileIDsInCollection =
           await FilesDB.instance.getUploadedFileIDs(collectionID);
-      files.removeWhere((element) =>
-          element.uploadedFileID != null &&
-          existingFileIDsInCollection.contains(element.uploadedFileID),);
+      files.removeWhere(
+        (element) =>
+            element.uploadedFileID != null &&
+            existingFileIDsInCollection.contains(element.uploadedFileID),
+      );
     }
     if (files.isEmpty || !containsUploadedFile) {
       _logger.info("nothing to add to the collection");
@@ -574,9 +606,13 @@ class CollectionsService {
       if (params["files"] == null) {
         params["files"] = [];
       }
-      params["files"].add(CollectionFileItem(
-              file.uploadedFileID, file.encryptedKey, file.keyDecryptionNonce,)
-          .toMap(),);
+      params["files"].add(
+        CollectionFileItem(
+          file.uploadedFileID,
+          file.encryptedKey,
+          file.keyDecryptionNonce,
+        ).toMap(),
+      );
     }
 
     try {
@@ -584,7 +620,8 @@ class CollectionsService {
         Configuration.instance.getHttpEndpoint() + "/collections/add-files",
         data: params,
         options: Options(
-            headers: {"X-Auth-Token": Configuration.instance.getToken()},),
+          headers: {"X-Auth-Token": Configuration.instance.getToken()},
+        ),
       );
       await _filesDB.insertMultiple(files);
       Bus.instance.fire(CollectionUpdatedEvent(collectionID, files));
@@ -605,16 +642,21 @@ class CollectionsService {
       final encryptedKeyData = CryptoUtil.encryptSync(key, toCollectionKey);
       file.encryptedKey = Sodium.bin2base64(encryptedKeyData.encryptedData);
       file.keyDecryptionNonce = Sodium.bin2base64(encryptedKeyData.nonce);
-      params["files"].add(CollectionFileItem(
-              file.uploadedFileID, file.encryptedKey, file.keyDecryptionNonce,)
-          .toMap(),);
+      params["files"].add(
+        CollectionFileItem(
+          file.uploadedFileID,
+          file.encryptedKey,
+          file.keyDecryptionNonce,
+        ).toMap(),
+      );
     }
     try {
       await _dio.post(
         Configuration.instance.getHttpEndpoint() + "/collections/restore-files",
         data: params,
         options: Options(
-            headers: {"X-Auth-Token": Configuration.instance.getToken()},),
+          headers: {"X-Auth-Token": Configuration.instance.getToken()},
+        ),
       );
       await _filesDB.insertMultiple(files);
       await TrashDB.instance
@@ -641,7 +683,10 @@ class CollectionsService {
   }
 
   Future<void> move(
-      int toCollectionID, int fromCollectionID, List<File> files,) async {
+    int toCollectionID,
+    int fromCollectionID,
+    List<File> files,
+  ) async {
     _validateMoveRequest(toCollectionID, fromCollectionID, files);
     files.removeWhere((element) => element.uploadedFileID == null);
     if (files.isEmpty) {
@@ -660,9 +705,13 @@ class CollectionsService {
           CryptoUtil.encryptSync(fileKey, getCollectionKey(toCollectionID));
       file.encryptedKey = Sodium.bin2base64(encryptedKeyData.encryptedData);
       file.keyDecryptionNonce = Sodium.bin2base64(encryptedKeyData.nonce);
-      params["files"].add(CollectionFileItem(
-              file.uploadedFileID, file.encryptedKey, file.keyDecryptionNonce,)
-          .toMap(),);
+      params["files"].add(
+        CollectionFileItem(
+          file.uploadedFileID,
+          file.encryptedKey,
+          file.keyDecryptionNonce,
+        ).toMap(),
+      );
     }
     await _dio.post(
       Configuration.instance.getHttpEndpoint() + "/collections/move-files",
@@ -673,20 +722,31 @@ class CollectionsService {
 
     // remove files from old collection
     await _filesDB.removeFromCollection(
-        fromCollectionID, files.map((e) => e.uploadedFileID).toList(),);
-    Bus.instance.fire(CollectionUpdatedEvent(fromCollectionID, files,
-        type: EventType.deletedFromRemote,),);
+      fromCollectionID,
+      files.map((e) => e.uploadedFileID).toList(),
+    );
+    Bus.instance.fire(
+      CollectionUpdatedEvent(
+        fromCollectionID,
+        files,
+        type: EventType.deletedFromRemote,
+      ),
+    );
     // insert new files in the toCollection which are not part of the toCollection
     final existingUploadedIDs =
         await FilesDB.instance.getUploadedFileIDs(toCollectionID);
     files.removeWhere(
-        (element) => existingUploadedIDs.contains(element.uploadedFileID),);
+      (element) => existingUploadedIDs.contains(element.uploadedFileID),
+    );
     await _filesDB.insertMultiple(files);
     Bus.instance.fire(CollectionUpdatedEvent(toCollectionID, files));
   }
 
   void _validateMoveRequest(
-      int toCollectionID, int fromCollectionID, List<File> files,) {
+    int toCollectionID,
+    int fromCollectionID,
+    List<File> files,
+  ) {
     if (toCollectionID == fromCollectionID) {
       throw AssertionError("can't move to same album");
     }
@@ -754,10 +814,13 @@ class CollectionsService {
     final key = collection.attributes.version == 1
         ? _getDecryptedKey(collection)
         : _config.getKey();
-    return utf8.decode(CryptoUtil.decryptSync(
+    return utf8.decode(
+      CryptoUtil.decryptSync(
         Sodium.base642bin(collection.attributes.encryptedPath),
         key,
-        Sodium.base642bin(collection.attributes.pathDecryptionNonce),),);
+        Sodium.base642bin(collection.attributes.pathDecryptionNonce),
+      ),
+    );
   }
 
   bool hasSyncedCollections() {
@@ -770,13 +833,17 @@ class CollectionsService {
       String name;
       try {
         final result = CryptoUtil.decryptSync(
-            Sodium.base642bin(collection.encryptedName),
-            _getDecryptedKey(collection),
-            Sodium.base642bin(collection.nameDecryptionNonce),);
+          Sodium.base642bin(collection.encryptedName),
+          _getDecryptedKey(collection),
+          Sodium.base642bin(collection.nameDecryptionNonce),
+        );
         name = utf8.decode(result);
       } catch (e, s) {
         _logger.severe(
-            "failed to decrypt collection name: ${collection.id}", e, s,);
+          "failed to decrypt collection name: ${collection.id}",
+          e,
+          s,
+        );
         name = "Unknown Album";
       }
       return collection.copyWith(name: name);
@@ -830,7 +897,8 @@ class AddFilesRequest {
     return AddFilesRequest(
       map['collectionID'],
       List<CollectionFileItem>.from(
-          map['files']?.map((x) => CollectionFileItem.fromMap(x)),),
+        map['files']?.map((x) => CollectionFileItem.fromMap(x)),
+      ),
     );
   }
 

+ 6 - 3
lib/services/deduplication_service.dart

@@ -52,11 +52,14 @@ class DeduplicationService {
       }
       if (missingFileIDs.isNotEmpty) {
         _logger.severe(
-            "Missing files",
-            InvalidStateError("Could not find " +
+          "Missing files",
+          InvalidStateError(
+            "Could not find " +
                 missingFileIDs.length.toString() +
                 " files in local DB: " +
-                missingFileIDs.toString(),),);
+                missingFileIDs.toString(),
+          ),
+        );
       }
       return result;
     } catch (e) {

+ 19 - 16
lib/services/favorites_service.dart

@@ -37,7 +37,9 @@ class FavoritesService {
       return false;
     }
     return _filesDB.doesFileExistInCollection(
-        file.uploadedFileID, collection.id,);
+      file.uploadedFileID,
+      collection.id,
+    );
   }
 
   Future<void> addToFavorites(File file) async {
@@ -84,21 +86,22 @@ class FavoritesService {
     final key = CryptoUtil.generateKey();
     final encryptedKeyData = CryptoUtil.encryptSync(key, _config.getKey());
     final encryptedName = CryptoUtil.encryptSync(utf8.encode("Favorites"), key);
-    final collection =
-        await _collectionsService.createAndCacheCollection(Collection(
-      null,
-      null,
-      Sodium.bin2base64(encryptedKeyData.encryptedData),
-      Sodium.bin2base64(encryptedKeyData.nonce),
-      null,
-      Sodium.bin2base64(encryptedName.encryptedData),
-      Sodium.bin2base64(encryptedName.nonce),
-      CollectionType.favorites,
-      CollectionAttributes(),
-      null,
-      null,
-      null,
-    ),);
+    final collection = await _collectionsService.createAndCacheCollection(
+      Collection(
+        null,
+        null,
+        Sodium.bin2base64(encryptedKeyData.encryptedData),
+        Sodium.bin2base64(encryptedKeyData.nonce),
+        null,
+        Sodium.bin2base64(encryptedName.encryptedData),
+        Sodium.bin2base64(encryptedName.nonce),
+        CollectionType.favorites,
+        CollectionAttributes(),
+        null,
+        null,
+        null,
+      ),
+    );
     _cachedFavoritesCollectionID = collection.id;
     return collection.id;
   }

+ 11 - 9
lib/services/feature_flag_service.dart

@@ -101,21 +101,23 @@ class FeatureFlagService {
 
 class FeatureFlags {
   static FeatureFlags defaultFlags = FeatureFlags(
-      disableCFWorker: FFDefault.disableCFWorker,
-      disableUrlSharing: FFDefault.disableUrlSharing,
-      enableStripe: FFDefault.enableStripe,
-      enableMissingLocationMigration: FFDefault.enableMissingLocationMigration,);
+    disableCFWorker: FFDefault.disableCFWorker,
+    disableUrlSharing: FFDefault.disableUrlSharing,
+    enableStripe: FFDefault.enableStripe,
+    enableMissingLocationMigration: FFDefault.enableMissingLocationMigration,
+  );
 
   final bool disableCFWorker;
   final bool disableUrlSharing;
   final bool enableStripe;
   final bool enableMissingLocationMigration;
 
-  FeatureFlags(
-      {@required this.disableCFWorker,
-      @required this.disableUrlSharing,
-      @required this.enableStripe,
-      @required this.enableMissingLocationMigration,});
+  FeatureFlags({
+    @required this.disableCFWorker,
+    @required this.disableUrlSharing,
+    @required this.enableStripe,
+    @required this.enableMissingLocationMigration,
+  });
 
   Map<String, dynamic> toMap() {
     return {

+ 35 - 16
lib/services/file_magic_service.dart

@@ -44,7 +44,9 @@ class FileMagicService {
   }
 
   Future<void> updatePublicMagicMetadata(
-      List<File> files, Map<String, dynamic> newMetadataUpdate,) async {
+    List<File> files,
+    Map<String, dynamic> newMetadataUpdate,
+  ) async {
     final params = <String, dynamic>{};
     params['metadataList'] = [];
     final int ownerID = Configuration.instance.getUserID();
@@ -52,7 +54,8 @@ class FileMagicService {
       for (final file in files) {
         if (file.uploadedFileID == null) {
           throw AssertionError(
-              "operation is only supported on backed up files",);
+            "operation is only supported on backed up files",
+          );
         } else if (file.ownerID != ownerID) {
           throw AssertionError("cannot modify memories not owned by you");
         }
@@ -70,15 +73,20 @@ class FileMagicService {
 
         final fileKey = decryptFileKey(file);
         final encryptedMMd = await CryptoUtil.encryptChaCha(
-            utf8.encode(jsonEncode(jsonToUpdate)), fileKey,);
-        params['metadataList'].add(UpdateMagicMetadataRequest(
+          utf8.encode(jsonEncode(jsonToUpdate)),
+          fileKey,
+        );
+        params['metadataList'].add(
+          UpdateMagicMetadataRequest(
             id: file.uploadedFileID,
             magicMetadata: MetadataRequest(
               version: file.pubMmdVersion,
               count: jsonToUpdate.length,
               data: Sodium.bin2base64(encryptedMMd.encryptedData),
               header: Sodium.bin2base64(encryptedMMd.header),
-            ),),);
+            ),
+          ),
+        );
         file.pubMmdVersion = file.pubMmdVersion + 1;
       }
 
@@ -87,7 +95,8 @@ class FileMagicService {
             "/files/public-magic-metadata",
         data: params,
         options: Options(
-            headers: {"X-Auth-Token": Configuration.instance.getToken()},),
+          headers: {"X-Auth-Token": Configuration.instance.getToken()},
+        ),
       );
       // update the state of the selected file. Same file in other collection
       // should be eventually synced after remote sync has completed
@@ -105,7 +114,9 @@ class FileMagicService {
   }
 
   Future<void> _updateMagicData(
-      List<File> files, Map<String, dynamic> newMetadataUpdate,) async {
+    List<File> files,
+    Map<String, dynamic> newMetadataUpdate,
+  ) async {
     final params = <String, dynamic>{};
     params['metadataList'] = [];
     final int ownerID = Configuration.instance.getUserID();
@@ -113,7 +124,8 @@ class FileMagicService {
       for (final file in files) {
         if (file.uploadedFileID == null) {
           throw AssertionError(
-              "operation is only supported on backed up files",);
+            "operation is only supported on backed up files",
+          );
         } else if (file.ownerID != ownerID) {
           throw AssertionError("cannot modify memories not owned by you");
         }
@@ -131,15 +143,20 @@ class FileMagicService {
 
         final fileKey = decryptFileKey(file);
         final encryptedMMd = await CryptoUtil.encryptChaCha(
-            utf8.encode(jsonEncode(jsonToUpdate)), fileKey,);
-        params['metadataList'].add(UpdateMagicMetadataRequest(
+          utf8.encode(jsonEncode(jsonToUpdate)),
+          fileKey,
+        );
+        params['metadataList'].add(
+          UpdateMagicMetadataRequest(
             id: file.uploadedFileID,
             magicMetadata: MetadataRequest(
               version: file.mMdVersion,
               count: jsonToUpdate.length,
               data: Sodium.bin2base64(encryptedMMd.encryptedData),
               header: Sodium.bin2base64(encryptedMMd.header),
-            ),),);
+            ),
+          ),
+        );
         file.mMdVersion = file.mMdVersion + 1;
       }
 
@@ -147,7 +164,8 @@ class FileMagicService {
         Configuration.instance.getHttpEndpoint() + "/files/magic-metadata",
         data: params,
         options: Options(
-            headers: {"X-Auth-Token": Configuration.instance.getToken()},),
+          headers: {"X-Auth-Token": Configuration.instance.getToken()},
+        ),
       );
       // update the state of the selected file. Same file in other collection
       // should be eventually synced after remote sync has completed
@@ -173,10 +191,11 @@ class UpdateMagicMetadataRequest {
 
   factory UpdateMagicMetadataRequest.fromJson(dynamic json) {
     return UpdateMagicMetadataRequest(
-        id: json['id'],
-        magicMetadata: json['magicMetadata'] != null
-            ? MetadataRequest.fromJson(json['magicMetadata'])
-            : null,);
+      id: json['id'],
+      magicMetadata: json['magicMetadata'] != null
+          ? MetadataRequest.fromJson(json['magicMetadata'])
+          : null,
+    );
   }
 
   Map<String, dynamic> toJson() {

+ 8 - 4
lib/services/file_migration_service.dart

@@ -81,13 +81,15 @@ class FileMigrationService {
       final eTime = DateTime.now().microsecondsSinceEpoch;
       final d = Duration(microseconds: eTime - sTime);
       _logger.info(
-          'filesWithMissingLocation migration completed in ${d.inSeconds.toString()} seconds',);
+        'filesWithMissingLocation migration completed in ${d.inSeconds.toString()} seconds',
+      );
     }
     await _markLocationMigrationAsCompleted();
   }
 
   Future<void> _checkAndMarkFilesForReUpload(
-      List<String> localIDsToProcess,) async {
+    List<String> localIDsToProcess,
+  ) async {
     _logger.info("files to process ${localIDsToProcess.length}");
     var localIDsWithLocation = <String>[];
     for (var localID in localIDsToProcess) {
@@ -101,7 +103,8 @@ class FileMigrationService {
         if ((latLng.longitude ?? 0.0) != 0.0 ||
             (latLng.longitude ?? 0.0) != 0.0) {
           _logger.finest(
-              'found lat/long ${latLng.longitude}/${latLng.longitude} for  ${assetEntity.title} ${assetEntity.relativePath} with id : $localID',);
+            'found lat/long ${latLng.longitude}/${latLng.longitude} for  ${assetEntity.title} ${assetEntity.relativePath} with id : $localID',
+          );
           hasLocation = true;
         }
       } catch (e, s) {
@@ -127,7 +130,8 @@ class FileMigrationService {
     final eTime = DateTime.now().microsecondsSinceEpoch;
     final d = Duration(microseconds: eTime - sTime);
     _logger.info(
-        'importing completed, total files count ${fileLocalIDs.length} and took ${d.inSeconds.toString()} seconds',);
+      'importing completed, total files count ${fileLocalIDs.length} and took ${d.inSeconds.toString()} seconds',
+    );
     _prefs.setBool(isLocalImportDone, true);
   }
 }

+ 10 - 5
lib/services/ignored_files_service.dart

@@ -25,10 +25,12 @@ class IgnoredFilesService {
 
   Future<void> cacheAndInsert(List<IgnoredFile> ignoredFiles) async {
     final existingIDs = await ignoredIDs;
-    existingIDs.addAll(ignoredFiles
-        .map((e) => _idForIgnoredFile(e))
-        .where((id) => id != null)
-        .toSet(),);
+    existingIDs.addAll(
+      ignoredFiles
+          .map((e) => _idForIgnoredFile(e))
+          .where((id) => id != null)
+          .toSet(),
+    );
     return _db.insertMultiple(ignoredFiles);
   }
 
@@ -56,7 +58,10 @@ class IgnoredFilesService {
 
   String _idForIgnoredFile(IgnoredFile ignoredFile) {
     return _getIgnoreID(
-        ignoredFile.localID, ignoredFile.deviceFolder, ignoredFile.title,);
+      ignoredFile.localID,
+      ignoredFile.deviceFolder,
+      ignoredFile.title,
+    );
   }
 
   // _computeIgnoreID will return null if don't have sufficient information

+ 23 - 14
lib/services/local_sync_service.dart

@@ -55,8 +55,10 @@ class LocalSyncService {
     if (Platform.isAndroid && AppLifecycleService.instance.isForeground) {
       final permissionState = await PhotoManager.requestPermissionExtend();
       if (permissionState != PermissionState.authorized) {
-        _logger.severe("sync requested with invalid permission",
-            permissionState.toString(),);
+        _logger.severe(
+          "sync requested with invalid permission",
+          permissionState.toString(),
+        );
         return;
       }
     }
@@ -67,7 +69,8 @@ class LocalSyncService {
     _existingSync = Completer<void>();
     final existingLocalFileIDs = await _db.getExistingLocalFileIDs();
     _logger.info(
-        existingLocalFileIDs.length.toString() + " localIDs were discovered",);
+      existingLocalFileIDs.length.toString() + " localIDs were discovered",
+    );
     final editedFileIDs = getEditedFileIDs().toSet();
     final downloadedFileIDs = getDownloadedFileIDs().toSet();
     final syncStartTime = DateTime.now().microsecondsSinceEpoch;
@@ -127,11 +130,13 @@ class LocalSyncService {
     final localAssets = await getAllLocalAssets();
     final eTime = DateTime.now().microsecondsSinceEpoch;
     final d = Duration(microseconds: eTime - sTime);
-    _logger.info("Loading from the beginning returned " +
-        localAssets.length.toString() +
-        " assets and took " +
-        d.inMilliseconds.toString() +
-        "ms",);
+    _logger.info(
+      "Loading from the beginning returned " +
+          localAssets.length.toString() +
+          " assets and took " +
+          d.inMilliseconds.toString() +
+          "ms",
+    );
     final existingIDs = await _db.getExistingLocalFileIDs();
     final invalidIDs = getInvalidFileIDs().toSet();
     final unsyncedFiles =
@@ -139,7 +144,8 @@ class LocalSyncService {
     if (unsyncedFiles.isNotEmpty) {
       await _db.insertMultiple(unsyncedFiles);
       _logger.info(
-          "Inserted " + unsyncedFiles.length.toString() + " unsynced files.",);
+        "Inserted " + unsyncedFiles.length.toString() + " unsynced files.",
+      );
       _updatePathsToBackup(unsyncedFiles);
       Bus.instance.fire(LocalPhotosUpdatedEvent(unsyncedFiles));
       return true;
@@ -218,10 +224,12 @@ class LocalSyncService {
     Set<String> editedFileIDs,
     Set<String> downloadedFileIDs,
   ) async {
-    _logger.info("Loading photos from " +
-        DateTime.fromMicrosecondsSinceEpoch(fromTime).toString() +
-        " to " +
-        DateTime.fromMicrosecondsSinceEpoch(toTime).toString(),);
+    _logger.info(
+      "Loading photos from " +
+          DateTime.fromMicrosecondsSinceEpoch(fromTime).toString() +
+          " to " +
+          DateTime.fromMicrosecondsSinceEpoch(toTime).toString(),
+    );
     final files = await getDeviceFiles(fromTime, toTime, _computer);
     if (files.isNotEmpty) {
       _logger.info("Fetched " + files.length.toString() + " files.");
@@ -233,7 +241,8 @@ class LocalSyncService {
           .removeWhere((file) => downloadedFileIDs.contains(file.localID));
       if (updatedFiles.isNotEmpty) {
         _logger.info(
-            updatedFiles.length.toString() + " local files were updated.",);
+          updatedFiles.length.toString() + " local files were updated.",
+        );
       }
       for (final file in updatedFiles) {
         await _db.updateUploadedFile(

+ 10 - 4
lib/services/memories_service.dart

@@ -30,7 +30,8 @@ class MemoriesService extends ChangeNotifier {
     // Intention of delay is to give more CPU cycles to other tasks
     Future.delayed(const Duration(seconds: 5), () {
       _memoriesDB.clearMemoriesSeenBeforeTime(
-          DateTime.now().microsecondsSinceEpoch - (7 * kMicroSecondsInDay),);
+        DateTime.now().microsecondsSinceEpoch - (7 * kMicroSecondsInDay),
+      );
     });
   }
 
@@ -53,10 +54,13 @@ class MemoriesService extends ChangeNotifier {
   Future<List<Memory>> _fetchMemories() async {
     _logger.info("Fetching memories");
     final presentTime = DateTime.now();
-    final present = presentTime.subtract(Duration(
+    final present = presentTime.subtract(
+      Duration(
         hours: presentTime.hour,
         minutes: presentTime.minute,
-        seconds: presentTime.second,),);
+        seconds: presentTime.second,
+      ),
+    );
     final List<List<int>> durations = [];
     for (var yearAgo = 1; yearAgo <= yearsBefore; yearAgo++) {
       final date = _getDate(present, yearAgo);
@@ -94,7 +98,9 @@ class MemoriesService extends ChangeNotifier {
   Future markMemoryAsSeen(Memory memory) async {
     memory.markSeen();
     await _memoriesDB.markMemoryAsSeen(
-        memory, DateTime.now().microsecondsSinceEpoch,);
+      memory,
+      DateTime.now().microsecondsSinceEpoch,
+    );
     notifyListeners();
   }
 }

+ 9 - 3
lib/services/notification_service.dart

@@ -20,8 +20,10 @@ class NotificationService {
         InitializationSettings(
       android: initializationSettingsAndroid,
     );
-    await _flutterLocalNotificationsPlugin.initialize(initializationSettings,
-        onSelectNotification: selectNotification,);
+    await _flutterLocalNotificationsPlugin.initialize(
+      initializationSettings,
+      onSelectNotification: selectNotification,
+    );
   }
 
   Future selectNotification(String payload) async {}
@@ -42,6 +44,10 @@ class NotificationService {
     const NotificationDetails platformChannelSpecifics =
         NotificationDetails(android: androidPlatformChannelSpecifics);
     await _flutterLocalNotificationsPlugin.show(
-        0, title, message, platformChannelSpecifics,);
+      0,
+      title,
+      message,
+      platformChannelSpecifics,
+    );
   }
 }

+ 5 - 2
lib/services/push_service.dart

@@ -61,7 +61,9 @@ class PushService {
         await _setPushTokenOnServer(fcmToken, apnsToken);
         await _prefs.setString(kFCMPushToken, fcmToken);
         await _prefs.setInt(
-            kLastFCMTokenUpdationTime, DateTime.now().microsecondsSinceEpoch,);
+          kLastFCMTokenUpdationTime,
+          DateTime.now().microsecondsSinceEpoch,
+        );
         _logger.info("Push token updated on server");
       } catch (e) {
         _logger.severe("Could not set push token", e, StackTrace.current);
@@ -88,7 +90,8 @@ class PushService {
     _logger.info("Message data: ${message.data}");
     if (message.notification != null) {
       _logger.info(
-          "Message also contained a notification: ${message.notification}",);
+        "Message also contained a notification: ${message.notification}",
+      );
     }
     if (shouldSync(message)) {
       SyncService.instance.sync();

+ 71 - 33
lib/services/remote_sync_service.dart

@@ -147,7 +147,9 @@ class RemoteSyncService {
     }
     for (final c in updatedCollections) {
       await _syncCollectionDiff(
-          c.id, _collectionsService.getCollectionSyncTime(c.id),);
+        c.id,
+        _collectionsService.getCollectionSyncTime(c.id),
+      );
       await _collectionsService.setCollectionSyncTime(c.id, c.updationTime);
     }
   }
@@ -156,8 +158,10 @@ class RemoteSyncService {
     _logger.info('re-sync collections sinceTime: $sinceTime');
     final collections = _collectionsService.getActiveCollections();
     for (final c in collections) {
-      await _syncCollectionDiff(c.id,
-          min(_collectionsService.getCollectionSyncTime(c.id), sinceTime),);
+      await _syncCollectionDiff(
+        c.id,
+        min(_collectionsService.getCollectionSyncTime(c.id), sinceTime),
+      );
       await _collectionsService.setCollectionSyncTime(c.id, c.updationTime);
     }
   }
@@ -170,17 +174,28 @@ class RemoteSyncService {
       final deletedFiles =
           (await FilesDB.instance.getFilesFromIDs(fileIDs)).values.toList();
       await FilesDB.instance.deleteFilesFromCollection(collectionID, fileIDs);
-      Bus.instance.fire(CollectionUpdatedEvent(collectionID, deletedFiles,
-          type: EventType.deletedFromRemote,),);
-      Bus.instance.fire(LocalPhotosUpdatedEvent(deletedFiles,
-          type: EventType.deletedFromRemote,),);
+      Bus.instance.fire(
+        CollectionUpdatedEvent(
+          collectionID,
+          deletedFiles,
+          type: EventType.deletedFromRemote,
+        ),
+      );
+      Bus.instance.fire(
+        LocalPhotosUpdatedEvent(
+          deletedFiles,
+          type: EventType.deletedFromRemote,
+        ),
+      );
     }
     if (diff.updatedFiles.isNotEmpty) {
       await _storeDiff(diff.updatedFiles, collectionID);
-      _logger.info("Updated " +
-          diff.updatedFiles.length.toString() +
-          " files in collection " +
-          collectionID.toString(),);
+      _logger.info(
+        "Updated " +
+            diff.updatedFiles.length.toString() +
+            " files in collection " +
+            collectionID.toString(),
+      );
       Bus.instance.fire(LocalPhotosUpdatedEvent(diff.updatedFiles));
       Bus.instance
           .fire(CollectionUpdatedEvent(collectionID, diff.updatedFiles));
@@ -188,11 +203,15 @@ class RemoteSyncService {
 
     if (diff.latestUpdatedAtTime > 0) {
       await _collectionsService.setCollectionSyncTime(
-          collectionID, diff.latestUpdatedAtTime,);
+        collectionID,
+        diff.latestUpdatedAtTime,
+      );
     }
     if (diff.hasMore) {
-      return await _syncCollectionDiff(collectionID,
-          _collectionsService.getCollectionSyncTime(collectionID),);
+      return await _syncCollectionDiff(
+        collectionID,
+        _collectionsService.getCollectionSyncTime(collectionID),
+      );
     }
   }
 
@@ -213,11 +232,15 @@ class RemoteSyncService {
     if (filesToBeUploaded.isNotEmpty) {
       final int prevCount = filesToBeUploaded.length;
       final ignoredIDs = await IgnoredFilesService.instance.ignoredIDs;
-      filesToBeUploaded.removeWhere((file) =>
-          IgnoredFilesService.instance.shouldSkipUpload(ignoredIDs, file),);
+      filesToBeUploaded.removeWhere(
+        (file) =>
+            IgnoredFilesService.instance.shouldSkipUpload(ignoredIDs, file),
+      );
       if (prevCount != filesToBeUploaded.length) {
-        _logger.info((prevCount - filesToBeUploaded.length).toString() +
-            " files were ignored for upload",);
+        _logger.info(
+          (prevCount - filesToBeUploaded.length).toString() +
+              " files were ignored for upload",
+        );
       }
     }
     if (filesToBeUploaded.isEmpty) {
@@ -227,7 +250,8 @@ class RemoteSyncService {
     }
     _sortByTimeAndType(filesToBeUploaded);
     _logger.info(
-        filesToBeUploaded.length.toString() + " new files to be uploaded.",);
+      filesToBeUploaded.length.toString() + " new files to be uploaded.",
+    );
     return filesToBeUploaded;
   }
 
@@ -320,13 +344,21 @@ class RemoteSyncService {
         _completedUploads < 0 ||
         toBeUploadedInThisSession < 0) {
       _logger.info(
-          "Incorrect sync status",
-          InvalidSyncStatusError("Tried to report $_completedUploads as "
-              "uploaded out of $toBeUploadedInThisSession",),);
+        "Incorrect sync status",
+        InvalidSyncStatusError(
+          "Tried to report $_completedUploads as "
+          "uploaded out of $toBeUploadedInThisSession",
+        ),
+      );
       return;
     }
-    Bus.instance.fire(SyncStatusUpdate(SyncStatus.in_progress,
-        completed: _completedUploads, total: toBeUploadedInThisSession,),);
+    Bus.instance.fire(
+      SyncStatusUpdate(
+        SyncStatus.in_progress,
+        completed: _completedUploads,
+        total: toBeUploadedInThisSession,
+      ),
+    );
   }
 
   Future _storeDiff(List<File> diff, int collectionID) async {
@@ -362,17 +394,21 @@ class RemoteSyncService {
         // case when localID for a file changes and the file is uploaded again in
         // the same collection
         final fileWithLocalID = existingFiles.firstWhere(
-            (e) =>
-                file.localID != null &&
-                e.localID != null &&
-                e.localID == file.localID,
-            orElse: () => existingFiles.firstWhere((e) => e.localID != null,
-                orElse: () => null,),);
+          (e) =>
+              file.localID != null &&
+              e.localID != null &&
+              e.localID == file.localID,
+          orElse: () => existingFiles.firstWhere(
+            (e) => e.localID != null,
+            orElse: () => null,
+          ),
+        );
         if (fileWithLocalID != null) {
           // File should ideally have the same localID
           if (file.localID != null && file.localID != fileWithLocalID.localID) {
             _logger.severe(
-                "unexpected mismatch in localIDs remote: ${file.toString()} and existing: ${fileWithLocalID.toString()}",);
+              "unexpected mismatch in localIDs remote: ${file.toString()} and existing: ${fileWithLocalID.toString()}",
+            );
           }
           file.localID = fileWithLocalID.localID;
         } else {
@@ -384,8 +420,10 @@ class RemoteSyncService {
           file.generatedID = existingFiles[0].generatedID;
           if (file.modificationTime != existingFiles[0].modificationTime) {
             // File was updated since the app was uninstalled
-            _logger.info("Updated since last installation: " +
-                file.uploadedFileID.toString(),);
+            _logger.info(
+              "Updated since last installation: " +
+                  file.uploadedFileID.toString(),
+            );
             file.modificationTime = existingFiles[0].modificationTime;
             file.updationTime = null;
             updated++;

+ 37 - 15
lib/services/sync_service.dart

@@ -91,18 +91,28 @@ class SyncService {
     } on WiFiUnavailableError {
       _logger.warning("Not uploading over mobile data");
       Bus.instance.fire(
-          SyncStatusUpdate(SyncStatus.paused, reason: "waiting for WiFi..."),);
+        SyncStatusUpdate(SyncStatus.paused, reason: "waiting for WiFi..."),
+      );
     } on SyncStopRequestedError {
       _syncStopRequested = false;
       Bus.instance.fire(
-          SyncStatusUpdate(SyncStatus.completed_backup, wasStopped: true),);
+        SyncStatusUpdate(SyncStatus.completed_backup, wasStopped: true),
+      );
     } on NoActiveSubscriptionError {
-      Bus.instance.fire(SyncStatusUpdate(SyncStatus.error,
-          error: NoActiveSubscriptionError(),),);
+      Bus.instance.fire(
+        SyncStatusUpdate(
+          SyncStatus.error,
+          error: NoActiveSubscriptionError(),
+        ),
+      );
     } on StorageLimitExceededError {
       _showStorageLimitExceededNotification();
-      Bus.instance.fire(SyncStatusUpdate(SyncStatus.error,
-          error: StorageLimitExceededError(),),);
+      Bus.instance.fire(
+        SyncStatusUpdate(
+          SyncStatus.error,
+          error: StorageLimitExceededError(),
+        ),
+      );
     } on UnauthorizedError {
       _logger.info("Logging user out");
       Bus.instance.fire(TriggerLogoutEvent());
@@ -112,8 +122,12 @@ class SyncService {
             e.type == DioErrorType.sendTimeout ||
             e.type == DioErrorType.receiveTimeout ||
             e.type == DioErrorType.other) {
-          Bus.instance.fire(SyncStatusUpdate(SyncStatus.paused,
-              reason: "waiting for network...",),);
+          Bus.instance.fire(
+            SyncStatusUpdate(
+              SyncStatus.paused,
+              reason: "waiting for network...",
+            ),
+          );
           _logger.severe("unable to connect", e, StackTrace.current);
           return false;
         }
@@ -155,15 +169,21 @@ class SyncService {
   }
 
   void onFoldersSet(Set<String> paths) {
-    _uploader.removeFromQueueWhere((file) {
-      return !paths.contains(file.deviceFolder);
-    }, UserCancelledUploadError(),);
+    _uploader.removeFromQueueWhere(
+      (file) {
+        return !paths.contains(file.deviceFolder);
+      },
+      UserCancelledUploadError(),
+    );
   }
 
   void onVideoBackupPaused() {
-    _uploader.removeFromQueueWhere((file) {
-      return file.fileType == FileType.video;
-    }, UserCancelledUploadError(),);
+    _uploader.removeFromQueueWhere(
+      (file) {
+        return file.fileType == FileType.video;
+      },
+      UserCancelledUploadError(),
+    );
   }
 
   Future<void> deleteFilesOnServer(List<int> fileIDs) async {
@@ -224,7 +244,9 @@ class SyncService {
     if ((now - lastNotificationShownTime) > kMicroSecondsInDay) {
       await _prefs.setInt(kLastStorageLimitExceededNotificationPushTime, now);
       NotificationService.instance.showNotification(
-          "storage limit exceeded", "sorry, we had to pause your backups",);
+        "storage limit exceeded",
+        "sorry, we had to pause your backups",
+      );
     }
   }
 }

+ 2 - 1
lib/services/trash_sync_service.dart

@@ -113,7 +113,8 @@ class TrashSyncService {
   }
 
   Future<Response<dynamic>> _trashFiles(
-      Map<String, dynamic> requestData,) async {
+    Map<String, dynamic> requestData,
+  ) async {
     return _dio.post(
       Configuration.instance.getHttpEndpoint() + "/files/trash",
       options: Options(

+ 3 - 1
lib/services/update_service.dart

@@ -69,7 +69,9 @@ class UpdateService {
         hasBeen3DaysSinceLastNotification &&
         _latestVersion.shouldNotify) {
       NotificationService.instance.showNotification(
-          "update available", "click to install our best version yet",);
+        "update available",
+        "click to install our best version yet",
+      );
       await _prefs.setInt(kUpdateAvailableShownTimeKey, now);
     } else {
       _logger.info("Debouncing notification");

+ 116 - 56
lib/services/user_service.dart

@@ -59,9 +59,11 @@ class UserService {
         Navigator.of(context).push(
           MaterialPageRoute(
             builder: (BuildContext context) {
-              return OTTVerificationPage(email,
-                  isChangeEmail: isChangeEmail,
-                  isCreateAccountScreen: isCreateAccountScreen,);
+              return OTTVerificationPage(
+                email,
+                isChangeEmail: isChangeEmail,
+                isCreateAccountScreen: isCreateAccountScreen,
+              );
             },
           ),
         );
@@ -143,15 +145,17 @@ class UserService {
 
   Future<void> terminateSession(String token) async {
     try {
-      await _dio.delete(_config.getHttpEndpoint() + "/users/session",
-          options: Options(
-            headers: {
-              "X-Auth-Token": _config.getToken(),
-            },
-          ),
-          queryParameters: {
-            "token": token,
-          },);
+      await _dio.delete(
+        _config.getHttpEndpoint() + "/users/session",
+        options: Options(
+          headers: {
+            "X-Auth-Token": _config.getToken(),
+          },
+        ),
+        queryParameters: {
+          "token": token,
+        },
+      );
     } on DioError catch (e) {
       _logger.info(e);
       rethrow;
@@ -160,12 +164,14 @@ class UserService {
 
   Future<void> leaveFamilyPlan() async {
     try {
-      await _dio.delete(_config.getHttpEndpoint() + "/family/leave",
-          options: Options(
-            headers: {
-              "X-Auth-Token": _config.getToken(),
-            },
-          ),);
+      await _dio.delete(
+        _config.getHttpEndpoint() + "/family/leave",
+        options: Options(
+          headers: {
+            "X-Auth-Token": _config.getToken(),
+          },
+        ),
+      );
     } on DioError catch (e) {
       _logger.warning('failed to leave family plan', e);
       rethrow;
@@ -176,13 +182,14 @@ class UserService {
     final dialog = createProgressDialog(context, "Logging out...");
     await dialog.show();
     try {
-      final response =
-          await _dio.post(_config.getHttpEndpoint() + "/users/logout",
-              options: Options(
-                headers: {
-                  "X-Auth-Token": _config.getToken(),
-                },
-              ),);
+      final response = await _dio.post(
+        _config.getHttpEndpoint() + "/users/logout",
+        options: Options(
+          headers: {
+            "X-Auth-Token": _config.getToken(),
+          },
+        ),
+      );
       if (response != null && response.statusCode == 200) {
         await Configuration.instance.logout();
         await dialog.hide();
@@ -240,11 +247,17 @@ class UserService {
       await dialog.hide();
       if (e.response != null && e.response.statusCode == 410) {
         await showErrorDialog(
-            context, "Oops", "Your verification code has expired",);
+          context,
+          "Oops",
+          "Your verification code has expired",
+        );
         Navigator.of(context).pop();
       } else {
-        showErrorDialog(context, "Incorrect code",
-            "Sorry, the code you've entered is incorrect",);
+        showErrorDialog(
+          context,
+          "Incorrect code",
+          "Sorry, the code you've entered is incorrect",
+        );
       }
     } catch (e) {
       await dialog.hide();
@@ -287,8 +300,11 @@ class UserService {
       if (e.response != null && e.response.statusCode == 403) {
         showErrorDialog(context, "Oops", "This email is already in use");
       } else {
-        showErrorDialog(context, "Incorrect code",
-            "Authentication failed, please try again",);
+        showErrorDialog(
+          context,
+          "Incorrect code",
+          "Authentication failed, please try again",
+        );
       }
     } catch (e) {
       await dialog.hide();
@@ -371,7 +387,10 @@ class UserService {
   }
 
   Future<void> verifyTwoFactor(
-      BuildContext context, String sessionID, String code,) async {
+    BuildContext context,
+    String sessionID,
+    String code,
+  ) async {
     final dialog = createProgressDialog(context, "Authenticating...");
     await dialog.show();
     try {
@@ -409,14 +428,20 @@ class UserService {
           (route) => route.isFirst,
         );
       } else {
-        showErrorDialog(context, "Incorrect code",
-            "Authentication failed, please try again",);
+        showErrorDialog(
+          context,
+          "Incorrect code",
+          "Authentication failed, please try again",
+        );
       }
     } catch (e) {
       await dialog.hide();
       _logger.severe(e);
       showErrorDialog(
-          context, "Oops", "Authentication failed, please try again",);
+        context,
+        "Oops",
+        "Authentication failed, please try again",
+      );
     }
   }
 
@@ -435,9 +460,10 @@ class UserService {
           MaterialPageRoute(
             builder: (BuildContext context) {
               return TwoFactorRecoveryPage(
-                  sessionID,
-                  response.data["encryptedSecret"],
-                  response.data["secretDecryptionNonce"],);
+                sessionID,
+                response.data["encryptedSecret"],
+                response.data["secretDecryptionNonce"],
+              );
             },
           ),
           (route) => route.isFirst,
@@ -457,12 +483,18 @@ class UserService {
         );
       } else {
         showErrorDialog(
-            context, "Oops", "Something went wrong, please try again",);
+          context,
+          "Oops",
+          "Something went wrong, please try again",
+        );
       }
     } catch (e) {
       _logger.severe(e);
       showErrorDialog(
-          context, "Oops", "Something went wrong, please try again",);
+        context,
+        "Oops",
+        "Something went wrong, please try again",
+      );
     } finally {
       await dialog.hide();
     }
@@ -479,14 +511,20 @@ class UserService {
     await dialog.show();
     String secret;
     try {
-      secret = Sodium.bin2base64(await CryptoUtil.decrypt(
+      secret = Sodium.bin2base64(
+        await CryptoUtil.decrypt(
           Sodium.base642bin(encryptedSecret),
           Sodium.hex2bin(recoveryKey.trim()),
-          Sodium.base642bin(secretDecryptionNonce),),);
+          Sodium.base642bin(secretDecryptionNonce),
+        ),
+      );
     } catch (e) {
       await dialog.hide();
-      showErrorDialog(context, "Incorrect recovery key",
-          "The recovery key you entered is incorrect",);
+      showErrorDialog(
+        context,
+        "Incorrect recovery key",
+        "The recovery key you entered is incorrect",
+      );
       return;
     }
     try {
@@ -523,12 +561,18 @@ class UserService {
         );
       } else {
         showErrorDialog(
-            context, "Oops", "Something went wrong, please try again",);
+          context,
+          "Oops",
+          "Something went wrong, please try again",
+        );
       }
     } catch (e) {
       _logger.severe(e);
       showErrorDialog(
-          context, "Oops", "Something went wrong, please try again",);
+        context,
+        "Oops",
+        "Something went wrong, please try again",
+      );
     } finally {
       await dialog.hide();
     }
@@ -548,9 +592,12 @@ class UserService {
       );
       await dialog.hide();
       routeToPage(
-          context,
-          TwoFactorSetupPage(
-              response.data["secretCode"], response.data["qrCode"],),);
+        context,
+        TwoFactorSetupPage(
+          response.data["secretCode"],
+          response.data["qrCode"],
+        ),
+      );
     } catch (e, s) {
       await dialog.hide();
       _logger.severe(e, s);
@@ -559,7 +606,10 @@ class UserService {
   }
 
   Future<bool> enableTwoFactor(
-      BuildContext context, String secret, String code,) async {
+    BuildContext context,
+    String secret,
+    String code,
+  ) async {
     Uint8List recoveryKey;
     try {
       recoveryKey = await getOrCreateRecoveryKey(context);
@@ -596,13 +646,19 @@ class UserService {
       _logger.severe(e, s);
       if (e is DioError) {
         if (e.response != null && e.response.statusCode == 401) {
-          showErrorDialog(context, "Incorrect code",
-              "Please verify the code you have entered",);
+          showErrorDialog(
+            context,
+            "Incorrect code",
+            "Please verify the code you have entered",
+          );
           return false;
         }
       }
-      showErrorDialog(context, "Something went wrong",
-          "Please contact support if the problem persists",);
+      showErrorDialog(
+        context,
+        "Something went wrong",
+        "Please contact support if the problem persists",
+      );
     }
     return false;
   }
@@ -626,8 +682,11 @@ class UserService {
     } catch (e, s) {
       await dialog.hide();
       _logger.severe(e, s);
-      showErrorDialog(context, "Something went wrong",
-          "Please contact support if the problem persists",);
+      showErrorDialog(
+        context,
+        "Something went wrong",
+        "Please contact support if the problem persists",
+      );
     }
   }
 
@@ -716,7 +775,8 @@ class UserService {
       await Configuration.instance
           .setEncryptedToken(response.data["encryptedToken"]);
       await Configuration.instance.setKeyAttributes(
-          KeyAttributes.fromMap(response.data["keyAttributes"]),);
+        KeyAttributes.fromMap(response.data["keyAttributes"]),
+      );
     } else {
       await Configuration.instance.setToken(response.data["token"]);
     }

+ 5 - 3
lib/ui/app_lock.dart

@@ -106,11 +106,13 @@ class _AppLockState extends State<AppLock> with WidgetsBindingObserver {
         switch (settings.name) {
           case '/lock-screen':
             return PageRouteBuilder(
-                pageBuilder: (_, __, ___) => this._lockScreen,);
+              pageBuilder: (_, __, ___) => this._lockScreen,
+            );
           case '/unlocked':
             return PageRouteBuilder(
-                pageBuilder: (_, __, ___) =>
-                    this.widget.builder(settings.arguments),);
+              pageBuilder: (_, __, ___) =>
+                  this.widget.builder(settings.arguments),
+            );
         }
         return PageRouteBuilder(pageBuilder: (_, __, ___) => this._lockScreen);
       },

+ 24 - 17
lib/ui/app_update_dialog.dart

@@ -19,10 +19,12 @@ class _AppUpdateDialogState extends State<AppUpdateDialog> {
   Widget build(BuildContext context) {
     final List<Widget> changelog = [];
     for (final log in widget.latestVersionInfo.changelog) {
-      changelog.add(Padding(
-        padding: const EdgeInsets.fromLTRB(8, 4, 0, 4),
-        child: Text("- " + log, style: Theme.of(context).textTheme.caption),
-      ),);
+      changelog.add(
+        Padding(
+          padding: const EdgeInsets.fromLTRB(8, 4, 0, 4),
+          child: Text("- " + log, style: Theme.of(context).textTheme.caption),
+        ),
+      );
     }
     final content = Column(
       crossAxisAlignment: CrossAxisAlignment.start,
@@ -36,10 +38,12 @@ class _AppUpdateDialogState extends State<AppUpdateDialog> {
           ),
         ),
         Padding(padding: EdgeInsets.all(8)),
-        Text("Changelog",
-            style: TextStyle(
-              fontSize: 18,
-            ),),
+        Text(
+          "Changelog",
+          style: TextStyle(
+            fontSize: 18,
+          ),
+        ),
         Padding(padding: EdgeInsets.all(4)),
         Column(
           crossAxisAlignment: CrossAxisAlignment.start,
@@ -79,9 +83,9 @@ class _AppUpdateDialogState extends State<AppUpdateDialog> {
     return WillPopScope(
       onWillPop: () async => !shouldForceUpdate,
       child: AlertDialog(
-        title: Text(shouldForceUpdate
-            ? "Critical update available"
-            : "Update available",),
+        title: Text(
+          shouldForceUpdate ? "Critical update available" : "Update available",
+        ),
         content: content,
       ),
     );
@@ -134,12 +138,15 @@ class _ApkDownloaderDialogState extends State<ApkDownloaderDialog> {
 
   Future<void> _downloadApk() async {
     try {
-      await Network.instance.getDio().download(widget.versionInfo.url, _saveUrl,
-          onReceiveProgress: (count, _) {
-        setState(() {
-          _downloadProgress = count / widget.versionInfo.size;
-        });
-      },);
+      await Network.instance.getDio().download(
+        widget.versionInfo.url,
+        _saveUrl,
+        onReceiveProgress: (count, _) {
+          setState(() {
+            _downloadProgress = count / widget.versionInfo.size;
+          });
+        },
+      );
       Navigator.of(context, rootNavigator: true).pop('dialog');
       OpenFile.open(_saveUrl);
     } catch (e) {

+ 20 - 13
lib/ui/archive_page.dart

@@ -16,26 +16,32 @@ class ArchivePage extends StatelessWidget {
   final GalleryType overlayType;
   final _selectedFiles = SelectedFiles();
 
-  ArchivePage(
-      {this.tagPrefix = "archived_page",
-      this.appBarType = GalleryType.archive,
-      this.overlayType = GalleryType.archive,
-      Key key,})
-      : super(key: key);
+  ArchivePage({
+    this.tagPrefix = "archived_page",
+    this.appBarType = GalleryType.archive,
+    this.overlayType = GalleryType.archive,
+    Key key,
+  }) : super(key: key);
 
   @override
   Widget build(Object context) {
     final gallery = Gallery(
       asyncLoader: (creationStartTime, creationEndTime, {limit, asc}) {
-        return FilesDB.instance.getAllUploadedFiles(creationStartTime,
-            creationEndTime, Configuration.instance.getUserID(),
-            visibility: kVisibilityArchive, limit: limit, asc: asc,);
+        return FilesDB.instance.getAllUploadedFiles(
+          creationStartTime,
+          creationEndTime,
+          Configuration.instance.getUserID(),
+          visibility: kVisibilityArchive,
+          limit: limit,
+          asc: asc,
+        );
       },
       reloadEvent: Bus.instance.on<FilesUpdatedEvent>().where(
             (event) =>
                 event.updatedFiles.firstWhere(
-                    (element) => element.uploadedFileID != null,
-                    orElse: () => null,) !=
+                  (element) => element.uploadedFileID != null,
+                  orElse: () => null,
+                ) !=
                 null,
           ),
       removalEventTypes: const {EventType.unarchived},
@@ -43,8 +49,9 @@ class ArchivePage extends StatelessWidget {
         Bus.instance.on<FilesUpdatedEvent>().where(
               (event) =>
                   event.updatedFiles.firstWhere(
-                      (element) => element.uploadedFileID != null,
-                      orElse: () => null,) !=
+                    (element) => element.uploadedFileID != null,
+                    orElse: () => null,
+                  ) !=
                   null,
             ),
       ],

+ 44 - 31
lib/ui/backup_folder_selection_page.dart

@@ -133,21 +133,28 @@ class _BackupFolderSelectionPageState extends State<BackupFolderSelectionPage> {
                           .compareTo(second.deviceFolder.toLowerCase());
                     });
                     setState(() {});
-                  },),
+                  },
+                ),
           Expanded(child: _getFolders()),
           Hero(
             tag: "select_folders",
             child: Container(
               width: double.infinity,
-              decoration: BoxDecoration(boxShadow: [
-                BoxShadow(
+              decoration: BoxDecoration(
+                boxShadow: [
+                  BoxShadow(
                     color: Theme.of(context).backgroundColor,
                     blurRadius: 24,
                     offset: Offset(0, -8),
-                    spreadRadius: 4,)
-              ],),
+                    spreadRadius: 4,
+                  )
+                ],
+              ),
               padding: EdgeInsets.only(
-                  left: 20, right: 20, bottom: Platform.isIOS ? 60 : 32,),
+                left: 20,
+                right: 20,
+                bottom: Platform.isIOS ? 60 : 32,
+              ),
               child: OutlinedButton(
                 child: Text(widget.buttonText),
                 onPressed: _selectedFolders.isEmpty
@@ -226,24 +233,26 @@ class _BackupFolderSelectionPageState extends State<BackupFolderSelectionPage> {
       padding: const EdgeInsets.only(bottom: 1, right: 1),
       child: Container(
         decoration: BoxDecoration(
-            border: Border.all(
-              color: Theme.of(context).colorScheme.boxUnSelectColor,
-            ),
-            borderRadius: BorderRadius.all(
-              Radius.circular(12),
-            ),
-            // color: isSelected
-            //     ? Theme.of(context).colorScheme.boxSelectColor
-            //     : Theme.of(context).colorScheme.boxUnSelectColor,
-            gradient: isSelected
-                ? LinearGradient(colors: const [
-                    Color(0xFF00DD4D),
-                    Color(0xFF43BA6C)
-                  ],) //same for both themes
-                : LinearGradient(colors: [
+          border: Border.all(
+            color: Theme.of(context).colorScheme.boxUnSelectColor,
+          ),
+          borderRadius: BorderRadius.all(
+            Radius.circular(12),
+          ),
+          // color: isSelected
+          //     ? Theme.of(context).colorScheme.boxSelectColor
+          //     : Theme.of(context).colorScheme.boxUnSelectColor,
+          gradient: isSelected
+              ? LinearGradient(
+                  colors: const [Color(0xFF00DD4D), Color(0xFF43BA6C)],
+                ) //same for both themes
+              : LinearGradient(
+                  colors: [
                     Theme.of(context).colorScheme.boxUnSelectColor,
                     Theme.of(context).colorScheme.boxUnSelectColor
-                  ],),),
+                  ],
+                ),
+        ),
         padding: EdgeInsets.fromLTRB(8, 4, 4, 4),
         child: InkWell(
           child: Row(
@@ -343,21 +352,25 @@ class _BackupFolderSelectionPageState extends State<BackupFolderSelectionPage> {
     return ClipRRect(
       borderRadius: BorderRadius.circular(8),
       child: SizedBox(
-        child: Stack(alignment: AlignmentDirectional.bottomEnd, children: [
-          ThumbnailWidget(
-            file,
-            shouldShowSyncStatus: false,
-            key: Key("backup_selection_widget" + file.tag()),
-          ),
-          Padding(
+        child: Stack(
+          alignment: AlignmentDirectional.bottomEnd,
+          children: [
+            ThumbnailWidget(
+              file,
+              shouldShowSyncStatus: false,
+              key: Key("backup_selection_widget" + file.tag()),
+            ),
+            Padding(
               padding: const EdgeInsets.all(9),
               child: isSelected
                   ? Icon(
                       Icons.local_police,
                       color: Colors.white,
                     )
-                  : null,),
-        ],),
+                  : null,
+            ),
+          ],
+        ),
         height: 88,
         width: 88,
       ),

+ 15 - 11
lib/ui/billing_questions_widget.dart

@@ -26,22 +26,26 @@ class BillingQuestionsWidget extends StatelessWidget {
       builder: (BuildContext context, AsyncSnapshot snapshot) {
         if (snapshot.hasData) {
           final faqs = <Widget>[];
-          faqs.add(Padding(
-            padding: const EdgeInsets.all(24),
-            child: Text(
-              "FAQs",
-              style: TextStyle(
-                fontSize: 18,
-                fontWeight: FontWeight.bold,
+          faqs.add(
+            Padding(
+              padding: const EdgeInsets.all(24),
+              child: Text(
+                "FAQs",
+                style: TextStyle(
+                  fontSize: 18,
+                  fontWeight: FontWeight.bold,
+                ),
               ),
             ),
-          ),);
+          );
           for (final faq in snapshot.data) {
             faqs.add(FaqWidget(faq: faq));
           }
-          faqs.add(Padding(
-            padding: EdgeInsets.all(16),
-          ),);
+          faqs.add(
+            Padding(
+              padding: EdgeInsets.all(16),
+            ),
+          );
           return SingleChildScrollView(
             child: Column(
               children: faqs,

+ 5 - 2
lib/ui/change_email_dialog.dart

@@ -64,8 +64,11 @@ class _ChangeEmailDialogState extends State<ChangeEmailDialog> {
           ),
           onPressed: () {
             if (!isValidEmail(_email)) {
-              showErrorDialog(context, "Invalid email address",
-                  "Please enter a valid email address.",);
+              showErrorDialog(
+                context,
+                "Invalid email address",
+                "Please enter a valid email address.",
+              );
               return;
             }
             UserService.instance.getOtt(context, _email, isChangeEmail: true);

+ 13 - 8
lib/ui/collection_page.dart

@@ -17,12 +17,13 @@ class CollectionPage extends StatelessWidget {
   final GalleryType overlayType;
   final _selectedFiles = SelectedFiles();
 
-  CollectionPage(this.c,
-      {this.tagPrefix = "collection",
-      this.appBarType = GalleryType.owned_collection,
-      this.overlayType = GalleryType.owned_collection,
-      Key key,})
-      : super(key: key);
+  CollectionPage(
+    this.c, {
+    this.tagPrefix = "collection",
+    this.appBarType = GalleryType.owned_collection,
+    this.overlayType = GalleryType.owned_collection,
+    Key key,
+  }) : super(key: key);
 
   @override
   Widget build(Object context) {
@@ -30,8 +31,12 @@ class CollectionPage extends StatelessWidget {
     final gallery = Gallery(
       asyncLoader: (creationStartTime, creationEndTime, {limit, asc}) {
         return FilesDB.instance.getFilesInCollection(
-            c.collection.id, creationStartTime, creationEndTime,
-            limit: limit, asc: asc,);
+          c.collection.id,
+          creationStartTime,
+          creationEndTime,
+          limit: limit,
+          asc: asc,
+        );
       },
       reloadEvent: Bus.instance
           .on<CollectionUpdatedEvent>()

+ 122 - 85
lib/ui/collections_gallery_widget.dart

@@ -100,8 +100,10 @@ class _CollectionsGalleryWidgetState extends State<CollectionsGalleryWidget>
     for (final file in latestLocalFiles) {
       folders.add(DeviceFolder(file.deviceFolder, file.deviceFolder, file));
     }
-    folders.sort((first, second) =>
-        second.thumbnail.creationTime.compareTo(first.thumbnail.creationTime),);
+    folders.sort(
+      (first, second) =>
+          second.thumbnail.creationTime.compareTo(first.thumbnail.creationTime),
+    );
 
     final List<CollectionWithThumbnail> collectionsWithThumbnail = [];
     final latestCollectionFiles =
@@ -136,8 +138,8 @@ class _CollectionsGalleryWidgetState extends State<CollectionsGalleryWidget>
         .textTheme
         .subtitle1
         .copyWith(
-            color:
-                Theme.of(context).textTheme.subtitle1.color.withOpacity(0.5),);
+          color: Theme.of(context).textTheme.subtitle1.color.withOpacity(0.5),
+        );
     Size size = MediaQuery.of(context).size;
     int albumsCountInOneRow = max(size.width ~/ 220.0, 2);
     final double sideOfThumbnail = (size.width / 2) -
@@ -155,8 +157,8 @@ class _CollectionsGalleryWidgetState extends State<CollectionsGalleryWidget>
                 ? Padding(
                     padding: const EdgeInsets.all(22),
                     child: nothingToSeeHere(
-                        textColor:
-                            Theme.of(context).colorScheme.defaultTextColor,),
+                      textColor: Theme.of(context).colorScheme.defaultTextColor,
+                    ),
                   )
                 : Padding(
                     padding: const EdgeInsets.symmetric(horizontal: 8),
@@ -168,7 +170,8 @@ class _CollectionsGalleryWidgetState extends State<CollectionsGalleryWidget>
                             ? nothingToSeeHere(
                                 textColor: Theme.of(context)
                                     .colorScheme
-                                    .defaultTextColor,)
+                                    .defaultTextColor,
+                              )
                             : ListView.builder(
                                 shrinkWrap: true,
                                 scrollDirection: Axis.horizontal,
@@ -203,21 +206,25 @@ class _CollectionsGalleryWidgetState extends State<CollectionsGalleryWidget>
                       // to disable GridView's scrolling
                       itemBuilder: (context, index) {
                         return _buildCollection(
-                            context, items.collections, index,);
+                          context,
+                          items.collections,
+                          index,
+                        );
                       },
                       itemCount: items.collections.length + 1,
                       // To include the + button
                       gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
-                          crossAxisCount: albumsCountInOneRow,
-                          mainAxisSpacing: 12,
-                          crossAxisSpacing: crossAxisSpacingOfGrid,
-                          childAspectRatio: sideOfThumbnail /
-                              (sideOfThumbnail +
-                                  24),), //24 is height of album title
+                        crossAxisCount: albumsCountInOneRow,
+                        mainAxisSpacing: 12,
+                        crossAxisSpacing: crossAxisSpacingOfGrid,
+                        childAspectRatio:
+                            sideOfThumbnail / (sideOfThumbnail + 24),
+                      ), //24 is height of album title
                     ),
                   )
                 : nothingToSeeHere(
-                    textColor: Theme.of(context).colorScheme.defaultTextColor,),
+                    textColor: Theme.of(context).colorScheme.defaultTextColor,
+                  ),
             const SizedBox(height: 10),
             const Divider(),
             const Padding(padding: EdgeInsets.all(8)),
@@ -258,31 +265,38 @@ class _CollectionsGalleryWidgetState extends State<CollectionsGalleryWidget>
                                   builder: (context, snapshot) {
                                     if (snapshot.hasData && snapshot.data > 0) {
                                       return RichText(
-                                          text: TextSpan(
-                                              style: trashAndHiddenTextStyle,
-                                              children: [
+                                        text: TextSpan(
+                                          style: trashAndHiddenTextStyle,
+                                          children: [
                                             TextSpan(
-                                                text: "Trash",
-                                                style: Theme.of(context)
-                                                    .textTheme
-                                                    .subtitle1,),
+                                              text: "Trash",
+                                              style: Theme.of(context)
+                                                  .textTheme
+                                                  .subtitle1,
+                                            ),
                                             TextSpan(text: "  \u2022  "),
                                             TextSpan(
-                                                text: snapshot.data.toString(),),
+                                              text: snapshot.data.toString(),
+                                            ),
                                             //need to query in db and bring this value
-                                          ],),);
+                                          ],
+                                        ),
+                                      );
                                     } else {
                                       return RichText(
-                                          text: TextSpan(
-                                              style: trashAndHiddenTextStyle,
-                                              children: [
+                                        text: TextSpan(
+                                          style: trashAndHiddenTextStyle,
+                                          children: [
                                             TextSpan(
-                                                text: "Trash",
-                                                style: Theme.of(context)
-                                                    .textTheme
-                                                    .subtitle1,),
+                                              text: "Trash",
+                                              style: Theme.of(context)
+                                                  .textTheme
+                                                  .subtitle1,
+                                            ),
                                             //need to query in db and bring this value
-                                          ],),);
+                                          ],
+                                        ),
+                                      );
                                     }
                                   },
                                 ),
@@ -333,38 +347,46 @@ class _CollectionsGalleryWidgetState extends State<CollectionsGalleryWidget>
                                 ),
                                 Padding(padding: EdgeInsets.all(6)),
                                 FutureBuilder<int>(
-                                  future: FilesDB.instance
-                                      .fileCountWithVisibility(
-                                          kVisibilityArchive,
-                                          Configuration.instance.getUserID(),),
+                                  future:
+                                      FilesDB.instance.fileCountWithVisibility(
+                                    kVisibilityArchive,
+                                    Configuration.instance.getUserID(),
+                                  ),
                                   builder: (context, snapshot) {
                                     if (snapshot.hasData && snapshot.data > 0) {
                                       return RichText(
-                                          text: TextSpan(
-                                              style: trashAndHiddenTextStyle,
-                                              children: [
+                                        text: TextSpan(
+                                          style: trashAndHiddenTextStyle,
+                                          children: [
                                             TextSpan(
-                                                text: "Hidden",
-                                                style: Theme.of(context)
-                                                    .textTheme
-                                                    .subtitle1,),
+                                              text: "Hidden",
+                                              style: Theme.of(context)
+                                                  .textTheme
+                                                  .subtitle1,
+                                            ),
                                             TextSpan(text: "  \u2022  "),
                                             TextSpan(
-                                                text: snapshot.data.toString(),),
+                                              text: snapshot.data.toString(),
+                                            ),
                                             //need to query in db and bring this value
-                                          ],),);
+                                          ],
+                                        ),
+                                      );
                                     } else {
                                       return RichText(
-                                          text: TextSpan(
-                                              style: trashAndHiddenTextStyle,
-                                              children: [
+                                        text: TextSpan(
+                                          style: trashAndHiddenTextStyle,
+                                          children: [
                                             TextSpan(
-                                                text: "Hidden",
-                                                style: Theme.of(context)
-                                                    .textTheme
-                                                    .subtitle1,),
+                                              text: "Hidden",
+                                              style: Theme.of(context)
+                                                  .textTheme
+                                                  .subtitle1,
+                                            ),
                                             //need to query in db and bring this value
-                                          ],),);
+                                          ],
+                                        ),
+                                      );
                                     }
                                   },
                                 ),
@@ -408,10 +430,13 @@ class _CollectionsGalleryWidgetState extends State<CollectionsGalleryWidget>
         case AlbumSortKey.lastUpdated:
           text = "Last updated";
       }
-      return Text(text,
-          style: Theme.of(context).textTheme.subtitle1.copyWith(
+      return Text(
+        text,
+        style: Theme.of(context).textTheme.subtitle1.copyWith(
               fontSize: 14,
-              color: Theme.of(context).iconTheme.color.withOpacity(0.7),),);
+              color: Theme.of(context).iconTheme.color.withOpacity(0.7),
+            ),
+      );
     }
 
     return Padding(
@@ -460,8 +485,11 @@ class _CollectionsGalleryWidgetState extends State<CollectionsGalleryWidget>
     );
   }
 
-  Widget _buildCollection(BuildContext context,
-      List<CollectionWithThumbnail> collections, int index,) {
+  Widget _buildCollection(
+    BuildContext context,
+    List<CollectionWithThumbnail> collections,
+    int index,
+  ) {
     if (index < collections.length) {
       final c = collections[index];
       return CollectionItem(c);
@@ -473,10 +501,11 @@ class _CollectionsGalleryWidgetState extends State<CollectionsGalleryWidget>
             color: Theme.of(context).backgroundColor,
             boxShadow: [
               BoxShadow(
-                  blurRadius: 2,
-                  spreadRadius: 0,
-                  offset: Offset(0, 0),
-                  color: Theme.of(context).iconTheme.color.withOpacity(0.3),)
+                blurRadius: 2,
+                spreadRadius: 0,
+                offset: Offset(0, 0),
+                color: Theme.of(context).iconTheme.color.withOpacity(0.3),
+              )
             ],
             borderRadius: BorderRadius.circular(4),
           ),
@@ -486,9 +515,11 @@ class _CollectionsGalleryWidgetState extends State<CollectionsGalleryWidget>
           ),
         ),
         onTap: () async {
-          await showToast(context,
-              "long press to select photos and click + to create an album",
-              toastLength: Toast.LENGTH_LONG,);
+          await showToast(
+            context,
+            "long press to select photos and click + to create an album",
+            toastLength: Toast.LENGTH_LONG,
+          );
           Bus.instance
               .fire(TabChangedEvent(0, TabChangedEventSource.collections_page));
         },
@@ -566,9 +597,11 @@ class DeviceFolderIcon extends StatelessWidget {
                         ThumbnailWidget(
                           folder.thumbnail,
                           shouldShowSyncStatus: false,
-                          key: Key("device_folder:" +
-                              folder.path +
-                              folder.thumbnail.tag(),),
+                          key: Key(
+                            "device_folder:" +
+                                folder.path +
+                                folder.thumbnail.tag(),
+                          ),
                         ),
                         isBackedUp ? Container() : kUnsyncedIconOverlay,
                       ],
@@ -623,17 +656,19 @@ class CollectionItem extends StatelessWidget {
           ClipRRect(
             borderRadius: BorderRadius.circular(4),
             child: SizedBox(
-                child: Hero(
-                    tag: "collection" + c.thumbnail.tag(),
-                    child: ThumbnailWidget(
-                      c.thumbnail,
-                      shouldShowArchiveStatus: c.collection.isArchived(),
-                      key: Key(
-                        "collection" + c.thumbnail.tag(),
-                      ),
-                    ),),
-                height: sideOfThumbnail,
-                width: sideOfThumbnail,),
+              child: Hero(
+                tag: "collection" + c.thumbnail.tag(),
+                child: ThumbnailWidget(
+                  c.thumbnail,
+                  shouldShowArchiveStatus: c.collection.isArchived(),
+                  key: Key(
+                    "collection" + c.thumbnail.tag(),
+                  ),
+                ),
+              ),
+              height: sideOfThumbnail,
+              width: sideOfThumbnail,
+            ),
           ),
           SizedBox(height: 4),
           Row(
@@ -651,15 +686,17 @@ class CollectionItem extends StatelessWidget {
                 builder: (context, snapshot) {
                   if (snapshot.hasData && snapshot.data > 0) {
                     return RichText(
-                        text: TextSpan(
-                            style: albumTitleTextStyle.copyWith(
-                                color:
-                                    albumTitleTextStyle.color.withOpacity(0.5),),
-                            children: [
+                      text: TextSpan(
+                        style: albumTitleTextStyle.copyWith(
+                          color: albumTitleTextStyle.color.withOpacity(0.5),
+                        ),
+                        children: [
                           TextSpan(text: "  \u2022  "),
                           TextSpan(text: snapshot.data.toString()),
                           //need to query in db and bring this value
-                        ],),);
+                        ],
+                      ),
+                    );
                   } else {
                     return Container();
                   }

+ 7 - 7
lib/ui/common/bottomShadow.dart

@@ -14,13 +14,13 @@ class BottomShadowWidget extends StatelessWidget {
         color: Colors.transparent,
         boxShadow: [
           BoxShadow(
-              color: shadowColor == null
-                  ? Theme.of(context).backgroundColor
-                  : shadowColor,
-              spreadRadius: 42,
-              blurRadius: 42,
-              offset: Offset(0, offsetDy), // changes position of shadow
-              ),
+            color: shadowColor == null
+                ? Theme.of(context).backgroundColor
+                : shadowColor,
+            spreadRadius: 42,
+            blurRadius: 42,
+            offset: Offset(0, offsetDy), // changes position of shadow
+          ),
         ],
       ),
     );

+ 24 - 24
lib/ui/common/dynamicFAB.dart

@@ -9,13 +9,13 @@ class DynamicFAB extends StatelessWidget {
   final String buttonText;
   final Function onPressedFunction;
 
-  DynamicFAB(
-      {Key key,
-      this.isKeypadOpen,
-      this.buttonText,
-      this.isFormValid,
-      this.onPressedFunction,})
-      : super(key: key);
+  DynamicFAB({
+    Key key,
+    this.isKeypadOpen,
+    this.buttonText,
+    this.isFormValid,
+    this.onPressedFunction,
+  }) : super(key: key);
 
   @override
   Widget build(BuildContext context) {
@@ -36,24 +36,24 @@ class DynamicFAB extends StatelessWidget {
           mainAxisAlignment: MainAxisAlignment.end,
           children: [
             FloatingActionButton(
-                heroTag: 'FAB',
-                backgroundColor:
-                    Theme.of(context).colorScheme.dynamicFABBackgroundColor,
-                foregroundColor:
-                    Theme.of(context).colorScheme.dynamicFABTextColor,
-                child: Transform.rotate(
-                  angle: isFormValid ? 0 : math.pi / 2,
-                  child: Icon(
-                    Icons.chevron_right,
-                    size: 36,
-                  ),
-                ),
-                onPressed: isFormValid
-                    ? onPressedFunction
-                    : () {
-                        FocusScope.of(context).unfocus();
-                      }, //keypad down here
+              heroTag: 'FAB',
+              backgroundColor:
+                  Theme.of(context).colorScheme.dynamicFABBackgroundColor,
+              foregroundColor:
+                  Theme.of(context).colorScheme.dynamicFABTextColor,
+              child: Transform.rotate(
+                angle: isFormValid ? 0 : math.pi / 2,
+                child: Icon(
+                  Icons.chevron_right,
+                  size: 36,
                 ),
+              ),
+              onPressed: isFormValid
+                  ? onPressedFunction
+                  : () {
+                      FocusScope.of(context).unfocus();
+                    }, //keypad down here
+            ),
           ],
         ),
       );

+ 11 - 8
lib/ui/common/onlyOuterShadow.dart

@@ -10,20 +10,23 @@ class onlyOuterShadow extends BoxShadow {
     double spreadRadius = 0.0,
     this.blurStyle = BlurStyle.normal,
   }) : super(
-            color: color,
-            offset: offset,
-            blurRadius: blurRadius,
-            spreadRadius: spreadRadius,);
+          color: color,
+          offset: offset,
+          blurRadius: blurRadius,
+          spreadRadius: spreadRadius,
+        );
 
   @override
   Paint toPaint() {
     final Paint result = Paint()
       ..color = color
       ..maskFilter = MaskFilter.blur(this.blurStyle, blurSigma);
-    assert(() {
-      if (debugDisableShadows) result.maskFilter = null;
-      return true;
-    }(),);
+    assert(
+      () {
+        if (debugDisableShadows) result.maskFilter = null;
+        return true;
+      }(),
+    );
     return result;
   }
 }

+ 6 - 2
lib/ui/common/report_bug_popup.dart

@@ -19,8 +19,12 @@ PopupMenuButton<dynamic> reportBugPopupMenu(BuildContext context) {
     },
     onSelected: (value) async {
       if (value == 1) {
-        await sendLogs(context, "Contact support", "support@ente.io",
-            postShare: () {},);
+        await sendLogs(
+          context,
+          "Contact support",
+          "support@ente.io",
+          postShare: () {},
+        );
       }
     },
   );

+ 41 - 20
lib/ui/create_collection_page.dart

@@ -43,9 +43,12 @@ class CreateCollectionPage extends StatefulWidget {
   final List<SharedMediaFile> sharedFiles;
   final CollectionActionType actionType;
 
-  const CreateCollectionPage(this.selectedFiles, this.sharedFiles,
-      {Key key, this.actionType = CollectionActionType.addFiles,})
-      : super(key: key);
+  const CreateCollectionPage(
+    this.selectedFiles,
+    this.sharedFiles, {
+    Key key,
+    this.actionType = CollectionActionType.addFiles,
+  }) : super(key: key);
 
   @override
   _CreateCollectionPageState createState() => _CreateCollectionPageState();
@@ -78,7 +81,11 @@ class _CreateCollectionPageState extends State<CreateCollectionPage> {
               Expanded(
                 child: Padding(
                   padding: const EdgeInsets.only(
-                      top: 30, bottom: 12, left: 40, right: 40,),
+                    top: 30,
+                    bottom: 12,
+                    left: 40,
+                    right: 40,
+                  ),
                   child: GradientButton(
                     child: Row(
                       mainAxisAlignment: MainAxisAlignment.center,
@@ -182,10 +189,11 @@ class _CreateCollectionPageState extends State<CreateCollectionPage> {
         onTap: () async {
           if (await _runCollectionAction(item.collection.id)) {
             showShortToast(
-                context,
-                widget.actionType == CollectionActionType.addFiles
-                    ? "Added successfully to " + item.collection.name
-                    : "Moved successfully to " + item.collection.name,);
+              context,
+              widget.actionType == CollectionActionType.addFiles
+                  ? "Added successfully to " + item.collection.name
+                  : "Moved successfully to " + item.collection.name,
+            );
             _navigateToCollection(item.collection);
           }
         },
@@ -243,10 +251,14 @@ class _CreateCollectionPageState extends State<CreateCollectionPage> {
               if (await _runCollectionAction(collection.id)) {
                 if (widget.actionType == CollectionActionType.restoreFiles) {
                   showShortToast(
-                      context, 'Restored files to album ' + _albumName,);
+                    context,
+                    'Restored files to album ' + _albumName,
+                  );
                 } else {
                   showShortToast(
-                      context, "Album '" + _albumName + "' created.",);
+                    context,
+                    "Album '" + _albumName + "' created.",
+                  );
                 }
                 _navigateToCollection(collection);
               }
@@ -267,12 +279,14 @@ class _CreateCollectionPageState extends State<CreateCollectionPage> {
   void _navigateToCollection(Collection collection) {
     Navigator.pop(context);
     Navigator.push(
-        context,
-        PageTransition(
-            type: PageTransitionType.bottomToTop,
-            child: CollectionPage(
-              CollectionWithThumbnail(collection, null),
-            ),),);
+      context,
+      PageTransition(
+        type: PageTransitionType.bottomToTop,
+        child: CollectionPage(
+          CollectionWithThumbnail(collection, null),
+        ),
+      ),
+    );
   }
 
   Future<bool> _runCollectionAction(int collectionID) async {
@@ -292,8 +306,11 @@ class _CreateCollectionPageState extends State<CreateCollectionPage> {
     await dialog.show();
     try {
       int fromCollectionID = widget.selectedFiles.files?.first?.collectionID;
-      await CollectionsService.instance.move(toCollectionID, fromCollectionID,
-          widget.selectedFiles.files?.toList(),);
+      await CollectionsService.instance.move(
+        toCollectionID,
+        fromCollectionID,
+        widget.selectedFiles.files?.toList(),
+      );
       RemoteSyncService.instance.sync(silently: true);
       widget.selectedFiles?.clearAll();
       await dialog.hide();
@@ -339,8 +356,12 @@ class _CreateCollectionPageState extends State<CreateCollectionPage> {
       final List<File> files = [];
       final List<File> filesPendingUpload = [];
       if (widget.sharedFiles != null) {
-        filesPendingUpload.addAll(await convertIncomingSharedMediaToFile(
-            widget.sharedFiles, collectionID,),);
+        filesPendingUpload.addAll(
+          await convertIncomingSharedMediaToFile(
+            widget.sharedFiles,
+            collectionID,
+          ),
+        );
       } else {
         final List<File> filesPendingUpload = [];
         for (final file in widget.selectedFiles.files) {

+ 28 - 22
lib/ui/deduplicate_page.dart

@@ -126,15 +126,17 @@ class _DeduplicatePageState extends State<DeduplicatePage> {
                   return Padding(
                     padding: EdgeInsets.only(top: 32),
                     child: nothingToSeeHere(
-                        textColor:
-                            Theme.of(context).colorScheme.defaultTextColor,),
+                      textColor: Theme.of(context).colorScheme.defaultTextColor,
+                    ),
                   );
                 }
               }
               return Padding(
                 padding: const EdgeInsets.only(top: 10, bottom: 10),
-                child: _getGridView(_duplicates[index - kHeaderRowCount],
-                    index - kHeaderRowCount,),
+                child: _getGridView(
+                  _duplicates[index - kHeaderRowCount],
+                  index - kHeaderRowCount,
+                ),
               );
             },
             itemCount: _duplicates.length + kHeaderRowCount,
@@ -153,10 +155,11 @@ class _DeduplicatePageState extends State<DeduplicatePage> {
         crossAxisAlignment: CrossAxisAlignment.center,
         children: [
           Text(
-              "Following files were clubbed based on their sizes" +
-                  ((_shouldClubByCaptureTime ? " and capture times." : ".") +
-                      ", please review and delete the items you believe are duplicates."),
-              style: Theme.of(context).textTheme.subtitle2,),
+            "Following files were clubbed based on their sizes" +
+                ((_shouldClubByCaptureTime ? " and capture times." : ".") +
+                    ", please review and delete the items you believe are duplicates."),
+            style: Theme.of(context).textTheme.subtitle2,
+          ),
           Padding(
             padding: EdgeInsets.all(12),
           ),
@@ -210,8 +213,9 @@ class _DeduplicatePageState extends State<DeduplicatePage> {
       return Text(
         text,
         style: Theme.of(context).textTheme.subtitle1.copyWith(
-            fontSize: 14,
-            color: Theme.of(context).iconTheme.color.withOpacity(0.7),),
+              fontSize: 14,
+              color: Theme.of(context).iconTheme.color.withOpacity(0.7),
+            ),
       );
     }
 
@@ -377,19 +381,21 @@ class _DeduplicatePageState extends State<DeduplicatePage> {
                 )
               : null,
         ),
-        child: Stack(children: [
-          Hero(
-            tag: "deduplicate_" + file.tag(),
-            child: ThumbnailWidget(
-              file,
-              diskLoadDeferDuration: kThumbnailDiskLoadDeferDuration,
-              serverLoadDeferDuration: kThumbnailServerLoadDeferDuration,
-              shouldShowLivePhotoOverlay: true,
-              key: Key("deduplicate_" + file.tag()),
+        child: Stack(
+          children: [
+            Hero(
+              tag: "deduplicate_" + file.tag(),
+              child: ThumbnailWidget(
+                file,
+                diskLoadDeferDuration: kThumbnailDiskLoadDeferDuration,
+                serverLoadDeferDuration: kThumbnailServerLoadDeferDuration,
+                shouldShowLivePhotoOverlay: true,
+                key: Key("deduplicate_" + file.tag()),
+              ),
             ),
-          ),
-          _selectedFiles.contains(file) ? kDeleteIconOverlay : Container(),
-        ],),
+            _selectedFiles.contains(file) ? kDeleteIconOverlay : Container(),
+          ],
+        ),
       ),
     );
   }

+ 34 - 19
lib/ui/detail_page.dart

@@ -91,13 +91,15 @@ class _DetailPageState extends State<DetailPage> {
 
   @override
   Widget build(BuildContext context) {
-    _logger.info("Opening " +
-        _files[_selectedIndex].toString() +
-        ". " +
-        (_selectedIndex + 1).toString() +
-        " / " +
-        _files.length.toString() +
-        " files .",);
+    _logger.info(
+      "Opening " +
+          _files[_selectedIndex].toString() +
+          ". " +
+          (_selectedIndex + 1).toString() +
+          " / " +
+          _files.length.toString() +
+          " files .",
+    );
     _appBarKey = GlobalKey<FadingAppBarState>();
     _bottomBarKey = GlobalKey<FadingBottomBarState>();
     return Scaffold(
@@ -198,10 +200,11 @@ class _DetailPageState extends State<DetailPage> {
     }
     if (_selectedIndex == 0 && !_hasLoadedTillStart) {
       final result = await widget.config.asyncLoader(
-          _files[_selectedIndex].creationTime + 1,
-          DateTime.now().microsecondsSinceEpoch,
-          limit: kLoadLimit,
-          asc: true,);
+        _files[_selectedIndex].creationTime + 1,
+        DateTime.now().microsecondsSinceEpoch,
+        limit: kLoadLimit,
+        asc: true,
+      );
       setState(() {
         // Returned result could be a subtype of File
         // ignore: unnecessary_cast
@@ -218,8 +221,10 @@ class _DetailPageState extends State<DetailPage> {
     }
     if (_selectedIndex == _files.length - 1 && !_hasLoadedTillEnd) {
       final result = await widget.config.asyncLoader(
-          kGalleryLoadStartTime, _files[_selectedIndex].creationTime - 1,
-          limit: kLoadLimit,);
+        kGalleryLoadStartTime,
+        _files[_selectedIndex].creationTime - 1,
+        limit: kLoadLimit,
+      );
       setState(() {
         if (!result.hasMore) {
           _hasLoadedTillEnd = true;
@@ -248,13 +253,17 @@ class _DetailPageState extends State<DetailPage> {
     if (_selectedIndex == totalFiles - 1) {
       // Deleted the last file
       await _pageController.previousPage(
-          duration: Duration(milliseconds: 200), curve: Curves.easeInOut,);
+        duration: Duration(milliseconds: 200),
+        curve: Curves.easeInOut,
+      );
       setState(() {
         _files.remove(file);
       });
     } else {
       await _pageController.nextPage(
-          duration: Duration(milliseconds: 200), curve: Curves.easeInOut,);
+        duration: Duration(milliseconds: 200),
+        curve: Curves.easeInOut,
+      );
       setState(() {
         _selectedIndex--;
         _files.remove(file);
@@ -265,10 +274,16 @@ class _DetailPageState extends State<DetailPage> {
   Future<void> _onEditFileRequested(File file) async {
     if (file.uploadedFileID != null &&
         file.ownerID != Configuration.instance.getUserID()) {
-      _logger.severe("Attempt to edit unowned file", UnauthorizedEditError(),
-          StackTrace.current,);
-      showErrorDialog(context, "Sorry",
-          "We don't support editing photos and albums that you don't own yet",);
+      _logger.severe(
+        "Attempt to edit unowned file",
+        UnauthorizedEditError(),
+        StackTrace.current,
+      );
+      showErrorDialog(
+        context,
+        "Sorry",
+        "We don't support editing photos and albums that you don't own yet",
+      );
       return;
     }
     final dialog = createProgressDialog(context, "Please wait...");

+ 11 - 6
lib/ui/device_folder_page.dart

@@ -24,8 +24,12 @@ class DeviceFolderPage extends StatelessWidget {
     final gallery = Gallery(
       asyncLoader: (creationStartTime, creationEndTime, {limit, asc}) {
         return FilesDB.instance.getFilesInPath(
-            folder.path, creationStartTime, creationEndTime,
-            limit: limit, asc: asc,);
+          folder.path,
+          creationStartTime,
+          creationEndTime,
+          limit: limit,
+          asc: asc,
+        );
       },
       reloadEvent: Bus.instance.on<LocalPhotosUpdatedEvent>(),
       removalEventTypes: const {
@@ -96,10 +100,11 @@ class _BackupConfigurationHeaderWidgetState
               : Text(
                   "Backup disabled",
                   style: TextStyle(
-                      color: Theme.of(context)
-                          .colorScheme
-                          .defaultTextColor
-                          .withOpacity(0.7),),
+                    color: Theme.of(context)
+                        .colorScheme
+                        .defaultTextColor
+                        .withOpacity(0.7),
+                  ),
                 ),
           Switch(
             value: isBackedUp,

+ 15 - 11
lib/ui/editor/filtered_image.dart

@@ -18,19 +18,23 @@ class FilteredImage extends StatelessWidget {
   @override
   Widget build(BuildContext context) {
     return ColorFiltered(
-      colorFilter:
-          ColorFilter.matrix(ColorFilterGenerator.brightnessAdjustMatrix(
-        value: brightness ?? 1,
-      ),),
+      colorFilter: ColorFilter.matrix(
+        ColorFilterGenerator.brightnessAdjustMatrix(
+          value: brightness ?? 1,
+        ),
+      ),
       child: ColorFiltered(
-        colorFilter:
-            ColorFilter.matrix(ColorFilterGenerator.saturationAdjustMatrix(
-          value: saturation ?? 1,
-        ),),
+        colorFilter: ColorFilter.matrix(
+          ColorFilterGenerator.saturationAdjustMatrix(
+            value: saturation ?? 1,
+          ),
+        ),
         child: ColorFiltered(
-          colorFilter: ColorFilter.matrix(ColorFilterGenerator.hueAdjustMatrix(
-            value: hue ?? 0,
-          ),),
+          colorFilter: ColorFilter.matrix(
+            ColorFilterGenerator.hueAdjustMatrix(
+              value: hue ?? 0,
+            ),
+          ),
           child: child,
         ),
       ),

+ 45 - 32
lib/ui/email_entry_page.dart

@@ -88,15 +88,16 @@ class _EmailEntryPageState extends State<EmailEntryPage> {
         },
       ),
       title: Material(
-          type: MaterialType.transparency,
-          child: StepProgressIndicator(
-            totalSteps: 4,
-            currentStep: 1,
-            selectedColor: Theme.of(context).buttonColor,
-            roundedEdges: Radius.circular(10),
-            unselectedColor:
-                Theme.of(context).colorScheme.stepProgressUnselectedColor,
-          ),),
+        type: MaterialType.transparency,
+        child: StepProgressIndicator(
+          totalSteps: 4,
+          currentStep: 1,
+          selectedColor: Theme.of(context).buttonColor,
+          roundedEdges: Radius.circular(10),
+          unselectedColor:
+              Theme.of(context).colorScheme.stepProgressUnselectedColor,
+        ),
+      ),
     );
     return Scaffold(
       appBar: appBar,
@@ -136,8 +137,10 @@ class _EmailEntryPageState extends State<EmailEntryPage> {
                 Padding(
                   padding:
                       const EdgeInsets.symmetric(vertical: 30, horizontal: 20),
-                  child: Text('Create new account',
-                      style: Theme.of(context).textTheme.headline4,),
+                  child: Text(
+                    'Create new account',
+                    style: Theme.of(context).textTheme.headline4,
+                  ),
                 ),
                 Padding(
                   padding: const EdgeInsets.fromLTRB(20, 0, 20, 0),
@@ -151,8 +154,9 @@ class _EmailEntryPageState extends State<EmailEntryPage> {
                       contentPadding:
                           EdgeInsets.symmetric(horizontal: 16, vertical: 14),
                       border: UnderlineInputBorder(
-                          borderSide: BorderSide.none,
-                          borderRadius: BorderRadius.circular(6),),
+                        borderSide: BorderSide.none,
+                        borderRadius: BorderRadius.circular(6),
+                      ),
                       suffixIcon: _emailIsValid
                           ? Icon(
                               Icons.check,
@@ -221,8 +225,9 @@ class _EmailEntryPageState extends State<EmailEntryPage> {
                                 )
                               : null,
                       border: UnderlineInputBorder(
-                          borderSide: BorderSide.none,
-                          borderRadius: BorderRadius.circular(6),),
+                        borderSide: BorderSide.none,
+                        borderRadius: BorderRadius.circular(6),
+                      ),
                     ),
                     focusNode: _password1FocusNode,
                     onChanged: (password) {
@@ -284,8 +289,9 @@ class _EmailEntryPageState extends State<EmailEntryPage> {
                                 )
                               : null,
                       border: UnderlineInputBorder(
-                          borderSide: BorderSide.none,
-                          borderRadius: BorderRadius.circular(6),),
+                        borderSide: BorderSide.none,
+                        borderRadius: BorderRadius.circular(6),
+                      ),
                     ),
                     focusNode: _password2FocusNode,
                     onChanged: (cnfPassword) {
@@ -348,13 +354,14 @@ class _EmailEntryPageState extends State<EmailEntryPage> {
       child: Row(
         children: [
           Checkbox(
-              value: _hasAgreedToTOS,
-              side: CheckboxTheme.of(context).side,
-              onChanged: (value) {
-                setState(() {
-                  _hasAgreedToTOS = value;
-                });
-              },),
+            value: _hasAgreedToTOS,
+            side: CheckboxTheme.of(context).side,
+            onChanged: (value) {
+              setState(() {
+                _hasAgreedToTOS = value;
+              });
+            },
+          ),
           Expanded(
             child: RichText(
               text: TextSpan(
@@ -390,7 +397,9 @@ class _EmailEntryPageState extends State<EmailEntryPage> {
                           MaterialPageRoute(
                             builder: (BuildContext context) {
                               return WebPage(
-                                  "Privacy", "https://ente.io/privacy",);
+                                "Privacy",
+                                "https://ente.io/privacy",
+                              );
                             },
                           ),
                         );
@@ -448,7 +457,9 @@ class _EmailEntryPageState extends State<EmailEntryPage> {
                           MaterialPageRoute(
                             builder: (BuildContext context) {
                               return WebPage(
-                                  "encryption", "https://ente.io/architecture",);
+                                "encryption",
+                                "https://ente.io/architecture",
+                              );
                             },
                           ),
                         );
@@ -526,12 +537,14 @@ class PricingWidget extends StatelessWidget {
               children: planWidgets,
             ),
           ),
-          Text("We offer a free trial of " +
-              convertBytesToReadableFormat(freePlan.storage) +
-              " for " +
-              freePlan.duration.toString() +
-              " " +
-              freePlan.period,),
+          Text(
+            "We offer a free trial of " +
+                convertBytesToReadableFormat(freePlan.storage) +
+                " for " +
+                freePlan.duration.toString() +
+                " " +
+                freePlan.period,
+          ),
           GestureDetector(
             child: Row(
               mainAxisAlignment: MainAxisAlignment.center,

+ 16 - 15
lib/ui/expansion_card.dart

@@ -178,21 +178,22 @@ class _ExpansionTileState extends State<ExpansionCard>
             mainAxisSize: MainAxisSize.min,
             children: <Widget>[
               ListTileTheme.merge(
-                  iconColor: _iconColor.value,
-                  textColor: _headerColor.value,
-                  child: Container(
-                    margin: widget.margin,
-                    child: ListTile(
-                      onTap: _handleTap,
-                      leading: widget.leading,
-                      title: widget.title,
-                      trailing: widget.trailing ??
-                          RotationTransition(
-                            turns: _iconTurns,
-                            child: const Icon(Icons.expand_more),
-                          ),
-                    ),
-                  ),),
+                iconColor: _iconColor.value,
+                textColor: _headerColor.value,
+                child: Container(
+                  margin: widget.margin,
+                  child: ListTile(
+                    onTap: _handleTap,
+                    leading: widget.leading,
+                    title: widget.title,
+                    trailing: widget.trailing ??
+                        RotationTransition(
+                          turns: _iconTurns,
+                          child: const Icon(Icons.expand_more),
+                        ),
+                  ),
+                ),
+              ),
               ClipRect(
                 child: Align(
                   heightFactor: _heightFactor.value,

+ 23 - 9
lib/ui/extents_page_view.dart

@@ -368,14 +368,28 @@ class _PageViewState extends State<ExtentsPageView> {
     description
         .add(EnumProperty<Axis>('scrollDirection', widget.scrollDirection));
     description.add(
-        FlagProperty('reverse', value: widget.reverse, ifTrue: 'reversed'),);
-    description.add(DiagnosticsProperty<PageController>(
-        'controller', widget.controller,
-        showName: false,),);
-    description.add(DiagnosticsProperty<ScrollPhysics>(
-        'physics', widget.physics,
-        showName: false,),);
-    description.add(FlagProperty('pageSnapping',
-        value: widget.pageSnapping, ifFalse: 'snapping disabled',),);
+      FlagProperty('reverse', value: widget.reverse, ifTrue: 'reversed'),
+    );
+    description.add(
+      DiagnosticsProperty<PageController>(
+        'controller',
+        widget.controller,
+        showName: false,
+      ),
+    );
+    description.add(
+      DiagnosticsProperty<ScrollPhysics>(
+        'physics',
+        widget.physics,
+        showName: false,
+      ),
+    );
+    description.add(
+      FlagProperty(
+        'pageSnapping',
+        value: widget.pageSnapping,
+        ifFalse: 'snapping disabled',
+      ),
+    );
   }
 }

+ 116 - 103
lib/ui/fading_app_bar.dart

@@ -99,87 +99,89 @@ class FadingAppBarState extends State<FadingAppBar> {
     if (widget.file.ownerID == null || widget.file.ownerID == widget.userID) {
       actions.add(_getFavoriteButton());
     }
-    actions.add(PopupMenuButton(
-      itemBuilder: (context) {
-        final List<PopupMenuItem> items = [];
-        if (widget.file.isRemoteFile()) {
-          items.add(
-            PopupMenuItem(
-              value: 1,
-              child: Row(
-                children: [
-                  Icon(
-                    Platform.isAndroid
-                        ? Icons.download
-                        : CupertinoIcons.cloud_download,
-                    color: Theme.of(context).iconTheme.color,
-                  ),
-                  Padding(
-                    padding: EdgeInsets.all(8),
-                  ),
-                  Text("Download"),
-                ],
-              ),
-            ),
-          );
-        }
-        // options for files owned by the user
-        if (widget.file.ownerID == null ||
-            widget.file.ownerID == widget.userID) {
-          if (widget.file.uploadedFileID != null) {
+    actions.add(
+      PopupMenuButton(
+        itemBuilder: (context) {
+          final List<PopupMenuItem> items = [];
+          if (widget.file.isRemoteFile()) {
             items.add(
               PopupMenuItem(
-                value: 2,
+                value: 1,
                 child: Row(
                   children: [
                     Icon(
                       Platform.isAndroid
-                          ? Icons.access_time_rounded
-                          : CupertinoIcons.time,
+                          ? Icons.download
+                          : CupertinoIcons.cloud_download,
                       color: Theme.of(context).iconTheme.color,
                     ),
                     Padding(
                       padding: EdgeInsets.all(8),
                     ),
-                    Text("Edit time"),
+                    Text("Download"),
                   ],
                 ),
               ),
             );
           }
-
-          items.add(
-            PopupMenuItem(
-              value: 3,
-              child: Row(
-                children: [
-                  Icon(
-                    Platform.isAndroid
-                        ? Icons.delete_outline
-                        : CupertinoIcons.delete,
-                    color: Theme.of(context).iconTheme.color,
+          // options for files owned by the user
+          if (widget.file.ownerID == null ||
+              widget.file.ownerID == widget.userID) {
+            if (widget.file.uploadedFileID != null) {
+              items.add(
+                PopupMenuItem(
+                  value: 2,
+                  child: Row(
+                    children: [
+                      Icon(
+                        Platform.isAndroid
+                            ? Icons.access_time_rounded
+                            : CupertinoIcons.time,
+                        color: Theme.of(context).iconTheme.color,
+                      ),
+                      Padding(
+                        padding: EdgeInsets.all(8),
+                      ),
+                      Text("Edit time"),
+                    ],
                   ),
-                  Padding(
-                    padding: EdgeInsets.all(8),
-                  ),
-                  Text("Delete"),
-                ],
+                ),
+              );
+            }
+
+            items.add(
+              PopupMenuItem(
+                value: 3,
+                child: Row(
+                  children: [
+                    Icon(
+                      Platform.isAndroid
+                          ? Icons.delete_outline
+                          : CupertinoIcons.delete,
+                      color: Theme.of(context).iconTheme.color,
+                    ),
+                    Padding(
+                      padding: EdgeInsets.all(8),
+                    ),
+                    Text("Delete"),
+                  ],
+                ),
               ),
-            ),
-          );
-        }
-        return items;
-      },
-      onSelected: (value) {
-        if (value == 1) {
-          _download(widget.file);
-        } else if (value == 2) {
-          _showDateTimePicker(widget.file);
-        } else if (value == 3) {
-          _showDeleteSheet(widget.file);
-        }
-      },
-    ),);
+            );
+          }
+          return items;
+        },
+        onSelected: (value) {
+          if (value == 1) {
+            _download(widget.file);
+          } else if (value == 2) {
+            _showDateTimePicker(widget.file);
+          } else if (value == 3) {
+            _showDeleteSheet(widget.file);
+          }
+        },
+      ),
+    );
     return AppBar(
       iconTheme: IconThemeData(color: Colors.white), //same for both themes
       actions: shouldShowActions ? actions : [],
@@ -267,8 +269,11 @@ class FadingAppBarState extends State<FadingAppBar> {
       theme: Theme.of(context).colorScheme.dateTimePickertheme,
     );
     if (dateWithTimeResult != null) {
-      if (await editTime(context, List.of([widget.file]),
-          dateWithTimeResult.microsecondsSinceEpoch,)) {
+      if (await editTime(
+        context,
+        List.of([widget.file]),
+        dateWithTimeResult.microsecondsSinceEpoch,
+      )) {
         widget.file.creationTime = dateWithTimeResult.microsecondsSinceEpoch;
         setState(() {});
       }
@@ -278,48 +283,56 @@ class FadingAppBarState extends State<FadingAppBar> {
   void _showDeleteSheet(File file) {
     final List<Widget> actions = [];
     if (file.uploadedFileID == null || file.localID == null) {
-      actions.add(CupertinoActionSheetAction(
-        child: Text("Everywhere"),
-        isDestructiveAction: true,
-        onPressed: () async {
-          await deleteFilesFromEverywhere(context, [file]);
-          Navigator.of(context, rootNavigator: true).pop();
-          widget.onFileDeleted(file);
-        },
-      ),);
+      actions.add(
+        CupertinoActionSheetAction(
+          child: Text("Everywhere"),
+          isDestructiveAction: true,
+          onPressed: () async {
+            await deleteFilesFromEverywhere(context, [file]);
+            Navigator.of(context, rootNavigator: true).pop();
+            widget.onFileDeleted(file);
+          },
+        ),
+      );
     } else {
       // uploaded file which is present locally too
-      actions.add(CupertinoActionSheetAction(
-        child: Text("Device"),
-        isDestructiveAction: true,
-        onPressed: () async {
-          await deleteFilesOnDeviceOnly(context, [file]);
-          showToast(context, "File deleted from device");
-          Navigator.of(context, rootNavigator: true).pop();
-          // TODO: Fix behavior when inside a device folder
-        },
-      ),);
+      actions.add(
+        CupertinoActionSheetAction(
+          child: Text("Device"),
+          isDestructiveAction: true,
+          onPressed: () async {
+            await deleteFilesOnDeviceOnly(context, [file]);
+            showToast(context, "File deleted from device");
+            Navigator.of(context, rootNavigator: true).pop();
+            // TODO: Fix behavior when inside a device folder
+          },
+        ),
+      );
 
-      actions.add(CupertinoActionSheetAction(
-        child: Text("ente"),
-        isDestructiveAction: true,
-        onPressed: () async {
-          await deleteFilesFromRemoteOnly(context, [file]);
-          showShortToast(context, "Moved to trash");
-          Navigator.of(context, rootNavigator: true).pop();
-          // TODO: Fix behavior when inside a collection
-        },
-      ),);
+      actions.add(
+        CupertinoActionSheetAction(
+          child: Text("ente"),
+          isDestructiveAction: true,
+          onPressed: () async {
+            await deleteFilesFromRemoteOnly(context, [file]);
+            showShortToast(context, "Moved to trash");
+            Navigator.of(context, rootNavigator: true).pop();
+            // TODO: Fix behavior when inside a collection
+          },
+        ),
+      );
 
-      actions.add(CupertinoActionSheetAction(
-        child: Text("Everywhere"),
-        isDestructiveAction: true,
-        onPressed: () async {
-          await deleteFilesFromEverywhere(context, [file]);
-          Navigator.of(context, rootNavigator: true).pop();
-          widget.onFileDeleted(file);
-        },
-      ),);
+      actions.add(
+        CupertinoActionSheetAction(
+          child: Text("Everywhere"),
+          isDestructiveAction: true,
+          onPressed: () async {
+            await deleteFilesFromEverywhere(context, [file]);
+            Navigator.of(context, rootNavigator: true).pop();
+            widget.onFileDeleted(file);
+          },
+        ),
+      );
     }
     final action = CupertinoActionSheet(
       title: Text("Delete file?"),

+ 10 - 8
lib/ui/fading_bottom_bar.dart

@@ -192,14 +192,16 @@ class FadingBottomBarState extends State<FadingBottomBar> {
               final selectedFiles = SelectedFiles();
               selectedFiles.toggleSelection(widget.file);
               Navigator.push(
-                  context,
-                  PageTransition(
-                      type: PageTransitionType.bottomToTop,
-                      child: CreateCollectionPage(
-                        selectedFiles,
-                        null,
-                        actionType: CollectionActionType.restoreFiles,
-                      ),),);
+                context,
+                PageTransition(
+                  type: PageTransitionType.bottomToTop,
+                  child: CreateCollectionPage(
+                    selectedFiles,
+                    null,
+                    actionType: CollectionActionType.restoreFiles,
+                  ),
+                ),
+              );
             },
           ),
         ),

+ 6 - 3
lib/ui/file_info_dialog.dart

@@ -134,7 +134,8 @@ class _FileInfoWidgetState extends State<FileInfoWidget> {
               Padding(padding: EdgeInsets.all(4)),
               Text(
                 getFormattedTime(
-                    DateTime.fromMicrosecondsSinceEpoch(file.updationTime),),
+                  DateTime.fromMicrosecondsSinceEpoch(file.updationTime),
+                ),
                 style: TextStyle(color: infoColor),
               ),
             ],
@@ -385,8 +386,10 @@ class _FileInfoWidgetState extends State<FileInfoWidget> {
           children: [
             Icon(Icons.center_focus_strong_outlined, color: infoColor),
             Padding(padding: EdgeInsets.all(4)),
-            Text(focalLength.toString() + " mm",
-                style: TextStyle(color: infoColor),),
+            Text(
+              focalLength.toString() + " mm",
+              style: TextStyle(color: infoColor),
+            ),
           ],
         ),
         Padding(padding: EdgeInsets.all(6)),

+ 3 - 2
lib/ui/free_space_page.dart

@@ -30,8 +30,9 @@ class _FreeSpacePageState extends State<FreeSpacePage> {
   }
 
   Widget _getBody() {
-    Logger("FreeSpacePage").info("Number of uploaded files: " +
-        widget.status.localIDs.length.toString(),);
+    Logger("FreeSpacePage").info(
+      "Number of uploaded files: " + widget.status.localIDs.length.toString(),
+    );
     Logger("FreeSpacePage")
         .info("Space consumed: " + widget.status.size.toString());
     return _getWidget(widget.status);

+ 33 - 19
lib/ui/gallery.dart

@@ -79,11 +79,13 @@ class _GalleryState extends State<Gallery> {
     }
     if (widget.forceReloadEvents != null) {
       for (final event in widget.forceReloadEvents) {
-        _forceReloadEventSubscriptions.add(event.listen((event) async {
-          _logger.info("Force reload triggered");
-          final result = await _loadFiles();
-          _setFilesAndReload(result.files);
-        }),);
+        _forceReloadEventSubscriptions.add(
+          event.listen((event) async {
+            _logger.info("Force reload triggered");
+            final result = await _loadFiles();
+            _setFilesAndReload(result.files);
+          }),
+        );
       }
     }
     if (widget.initialFiles != null) {
@@ -111,15 +113,19 @@ class _GalleryState extends State<Gallery> {
     try {
       final startTime = DateTime.now().microsecondsSinceEpoch;
       final result = await widget.asyncLoader(
-          kGalleryLoadStartTime, DateTime.now().microsecondsSinceEpoch,
-          limit: limit,);
+        kGalleryLoadStartTime,
+        DateTime.now().microsecondsSinceEpoch,
+        limit: limit,
+      );
       final endTime = DateTime.now().microsecondsSinceEpoch;
       final duration = Duration(microseconds: endTime - startTime);
-      _logger.info("Time taken to load " +
-          result.files.length.toString() +
-          " files :" +
-          duration.inMilliseconds.toString() +
-          "ms",);
+      _logger.info(
+        "Time taken to load " +
+            result.files.length.toString() +
+            " files :" +
+            duration.inMilliseconds.toString() +
+            "ms",
+      );
       return result;
     } catch (e, s) {
       _logger.severe("failed to load files", e, s);
@@ -178,10 +184,13 @@ class _GalleryState extends State<Gallery> {
         if (widget.header != null) {
           children.add(widget.header);
         }
-        children.add(Expanded(
-          child: nothingToSeeHere(
-              textColor: Theme.of(context).colorScheme.defaultTextColor,),
-        ),);
+        children.add(
+          Expanded(
+            child: nothingToSeeHere(
+              textColor: Theme.of(context).colorScheme.defaultTextColor,
+            ),
+          ),
+        );
         if (widget.footer != null) {
           children.add(widget.footer);
         }
@@ -215,8 +224,11 @@ class _GalleryState extends State<Gallery> {
         return gallery;
       },
       labelTextBuilder: (int index) {
-        return getMonthAndYear(DateTime.fromMicrosecondsSinceEpoch(
-            _collatedFiles[index][0].creationTime,),);
+        return getMonthAndYear(
+          DateTime.fromMicrosecondsSinceEpoch(
+            _collatedFiles[index][0].creationTime,
+          ),
+        );
       },
       thumbBackgroundColor:
           Theme.of(context).colorScheme.galleryThumbBackgroundColor,
@@ -234,7 +246,9 @@ class _GalleryState extends State<Gallery> {
     for (int index = 0; index < files.length; index++) {
       if (index > 0 &&
           !_areFromSameDay(
-              files[index - 1].creationTime, files[index].creationTime,)) {
+            files[index - 1].creationTime,
+            files[index].creationTime,
+          )) {
         final List<File> collatedDailyFiles = [];
         collatedDailyFiles.addAll(dailyFiles);
         collatedFiles.add(collatedDailyFiles);

+ 41 - 37
lib/ui/gallery_app_bar_widget.dart

@@ -135,56 +135,59 @@ class _GalleryAppBarWidgetState extends State<GalleryAppBarWidget> {
       );
     }
     if (widget.type == GalleryType.owned_collection) {
-      actions.add(PopupMenuButton(
-        itemBuilder: (context) {
-          final List<PopupMenuItem> items = [];
-          if (widget.collection.type == CollectionType.album) {
+      actions.add(
+        PopupMenuButton(
+          itemBuilder: (context) {
+            final List<PopupMenuItem> items = [];
+            if (widget.collection.type == CollectionType.album) {
+              items.add(
+                PopupMenuItem(
+                  value: 1,
+                  child: Row(
+                    children: const [
+                      Icon(Icons.edit),
+                      Padding(
+                        padding: EdgeInsets.all(8),
+                      ),
+                      Text("Rename"),
+                    ],
+                  ),
+                ),
+              );
+            }
+            bool isArchived = widget.collection.isArchived();
             items.add(
               PopupMenuItem(
-                value: 1,
+                value: 2,
                 child: Row(
-                  children: const [
-                    Icon(Icons.edit),
+                  children: [
+                    Icon(isArchived ? Icons.visibility : Icons.visibility_off),
                     Padding(
                       padding: EdgeInsets.all(8),
                     ),
-                    Text("Rename"),
+                    Text(isArchived ? "Unhide" : "Hide"),
                   ],
                 ),
               ),
             );
-          }
-          bool isArchived = widget.collection.isArchived();
-          items.add(
-            PopupMenuItem(
-              value: 2,
-              child: Row(
-                children: [
-                  Icon(isArchived ? Icons.visibility : Icons.visibility_off),
-                  Padding(
-                    padding: EdgeInsets.all(8),
-                  ),
-                  Text(isArchived ? "Unhide" : "Hide"),
-                ],
-              ),
-            ),
-          );
-          return items;
-        },
-        onSelected: (value) async {
-          if (value == 1) {
-            await _renameAlbum(context);
-          }
-          if (value == 2) {
-            await changeCollectionVisibility(
+            return items;
+          },
+          onSelected: (value) async {
+            if (value == 1) {
+              await _renameAlbum(context);
+            }
+            if (value == 2) {
+              await changeCollectionVisibility(
                 context,
                 widget.collection,
                 widget.collection.isArchived()
                     ? kVisibilityVisible
-                    : kVisibilityArchive,);
-          }
-        },
-      ),);
+                    : kVisibilityArchive,
+              );
+            }
+          },
+        ),
+      );
     }
     return actions;
   }
@@ -200,7 +203,8 @@ class _GalleryAppBarWidgetState extends State<GalleryAppBarWidget> {
               await CollectionsService.instance.getOrCreateForPath(widget.path);
         } else {
           throw Exception(
-              "Cannot create a collection of type" + widget.type.toString(),);
+            "Cannot create a collection of type" + widget.type.toString(),
+          );
         }
       } else {
         final sharees =

+ 159 - 109
lib/ui/gallery_overlay_widget.dart

@@ -27,9 +27,13 @@ class GalleryOverlayWidget extends StatefulWidget {
   final SelectedFiles selectedFiles;
   final String path;
   final Collection collection;
-  const GalleryOverlayWidget(this.type, this.selectedFiles,
-      {this.path, this.collection, Key key,})
-      : super(key: key);
+  const GalleryOverlayWidget(
+    this.type,
+    this.selectedFiles, {
+    this.path,
+    this.collection,
+    Key key,
+  }) : super(key: key);
 
   @override
   State<GalleryOverlayWidget> createState() => _GalleryOverlayWidgetState();
@@ -216,25 +220,29 @@ class _OverlayWidgetState extends State<OverlayWidget> {
 
   Future<void> _createAlbum() async {
     Navigator.push(
-        context,
-        PageTransition(
-            type: PageTransitionType.bottomToTop,
-            child: CreateCollectionPage(
-              widget.selectedFiles,
-              null,
-            ),),);
+      context,
+      PageTransition(
+        type: PageTransitionType.bottomToTop,
+        child: CreateCollectionPage(
+          widget.selectedFiles,
+          null,
+        ),
+      ),
+    );
   }
 
   Future<void> _moveFiles() async {
     Navigator.push(
-        context,
-        PageTransition(
-            type: PageTransitionType.bottomToTop,
-            child: CreateCollectionPage(
-              widget.selectedFiles,
-              null,
-              actionType: CollectionActionType.moveFiles,
-            ),),);
+      context,
+      PageTransition(
+        type: PageTransitionType.bottomToTop,
+        child: CreateCollectionPage(
+          widget.selectedFiles,
+          null,
+          actionType: CollectionActionType.moveFiles,
+        ),
+      ),
+    );
   }
 
   List<Widget> _getActions(BuildContext context) {
@@ -276,9 +284,11 @@ class _OverlayWidgetState extends State<OverlayWidget> {
           message: "Move",
           child: IconButton(
             color: Theme.of(context).colorScheme.iconColor,
-            icon: Icon(Platform.isAndroid
-                ? Icons.arrow_forward
-                : CupertinoIcons.arrow_right,),
+            icon: Icon(
+              Platform.isAndroid
+                  ? Icons.arrow_forward
+                  : CupertinoIcons.arrow_right,
+            ),
             onPressed: () {
               _moveFiles();
             },
@@ -352,44 +362,52 @@ class _OverlayWidgetState extends State<OverlayWidget> {
     if (widget.type == GalleryType.homepage ||
         widget.type == GalleryType.archive) {
       bool showArchive = widget.type == GalleryType.homepage;
-      actions.add(Tooltip(
-        message: showArchive ? "Hide" : "Unhide",
-        child: IconButton(
-          color: Theme.of(context).colorScheme.iconColor,
-          icon: Icon(
-            showArchive ? Icons.visibility_off : Icons.visibility,
+      actions.add(
+        Tooltip(
+          message: showArchive ? "Hide" : "Unhide",
+          child: IconButton(
+            color: Theme.of(context).colorScheme.iconColor,
+            icon: Icon(
+              showArchive ? Icons.visibility_off : Icons.visibility,
+            ),
+            onPressed: () {
+              _handleVisibilityChangeRequest(
+                context,
+                showArchive ? kVisibilityArchive : kVisibilityVisible,
+              );
+            },
           ),
-          onPressed: () {
-            _handleVisibilityChangeRequest(
-                context, showArchive ? kVisibilityArchive : kVisibilityVisible,);
-          },
         ),
-      ),);
+      );
     }
     return actions;
   }
 
   void _addTrashAction(List<Widget> actions) {
-    actions.add(Tooltip(
-      message: "Restore",
-      child: IconButton(
-        color: Theme.of(context).colorScheme.iconColor,
-        icon: Icon(
-          Icons.restore,
-        ),
-        onPressed: () {
-          Navigator.push(
+    actions.add(
+      Tooltip(
+        message: "Restore",
+        child: IconButton(
+          color: Theme.of(context).colorScheme.iconColor,
+          icon: Icon(
+            Icons.restore,
+          ),
+          onPressed: () {
+            Navigator.push(
               context,
               PageTransition(
-                  type: PageTransitionType.bottomToTop,
-                  child: CreateCollectionPage(
-                    widget.selectedFiles,
-                    null,
-                    actionType: CollectionActionType.restoreFiles,
-                  ),),);
-        },
+                type: PageTransitionType.bottomToTop,
+                child: CreateCollectionPage(
+                  widget.selectedFiles,
+                  null,
+                  actionType: CollectionActionType.restoreFiles,
+                ),
+              ),
+            );
+          },
+        ),
       ),
-    ),);
+    );
     actions.add(
       Tooltip(
         message: "Delete permanently",
@@ -400,7 +418,9 @@ class _OverlayWidgetState extends State<OverlayWidget> {
           ),
           onPressed: () async {
             if (await deleteFromTrash(
-                context, widget.selectedFiles.files.toList(),)) {
+              context,
+              widget.selectedFiles.files.toList(),
+            )) {
               _clearSelectedFiles();
             }
           },
@@ -410,10 +430,15 @@ class _OverlayWidgetState extends State<OverlayWidget> {
   }
 
   Future<void> _handleVisibilityChangeRequest(
-      BuildContext context, int newVisibility,) async {
+    BuildContext context,
+    int newVisibility,
+  ) async {
     try {
       await changeVisibility(
-          context, widget.selectedFiles.files.toList(), newVisibility,);
+        context,
+        widget.selectedFiles.files.toList(),
+        newVisibility,
+      );
     } catch (e, s) {
       _logger.severe("failed to update file visibility", e, s);
       await showGenericErrorDialog(context);
@@ -423,8 +448,11 @@ class _OverlayWidgetState extends State<OverlayWidget> {
   }
 
   void _shareSelected(BuildContext context) {
-    share(context, widget.selectedFiles.files.toList(),
-        shareButtonKey: shareButtonKey,);
+    share(
+      context,
+      widget.selectedFiles.files.toList(),
+      shareButtonKey: shareButtonKey,
+    );
   }
 
   void _showDeleteSheet(BuildContext context) {
@@ -440,56 +468,74 @@ class _OverlayWidgetState extends State<OverlayWidget> {
     }
     final actions = <Widget>[];
     if (containsUploadedFile && containsLocalFile) {
-      actions.add(CupertinoActionSheetAction(
-        child: Text("Device"),
-        isDestructiveAction: true,
-        onPressed: () async {
-          Navigator.of(context, rootNavigator: true).pop();
-          await deleteFilesOnDeviceOnly(
-              context, widget.selectedFiles.files.toList(),);
-          _clearSelectedFiles();
-          showToast(context, "Files deleted from device");
-        },
-      ),);
-      actions.add(CupertinoActionSheetAction(
-        child: Text("ente"),
-        isDestructiveAction: true,
-        onPressed: () async {
-          Navigator.of(context, rootNavigator: true).pop();
-          await deleteFilesFromRemoteOnly(
-              context, widget.selectedFiles.files.toList(),);
-          _clearSelectedFiles();
-          showShortToast(context, "Moved to trash");
-        },
-      ),);
-      actions.add(CupertinoActionSheetAction(
-        child: Text("Everywhere"),
-        isDestructiveAction: true,
-        onPressed: () async {
-          Navigator.of(context, rootNavigator: true).pop();
-          await deleteFilesFromEverywhere(
-              context, widget.selectedFiles.files.toList(),);
-          _clearSelectedFiles();
-        },
-      ),);
+      actions.add(
+        CupertinoActionSheetAction(
+          child: Text("Device"),
+          isDestructiveAction: true,
+          onPressed: () async {
+            Navigator.of(context, rootNavigator: true).pop();
+            await deleteFilesOnDeviceOnly(
+              context,
+              widget.selectedFiles.files.toList(),
+            );
+            _clearSelectedFiles();
+            showToast(context, "Files deleted from device");
+          },
+        ),
+      );
+      actions.add(
+        CupertinoActionSheetAction(
+          child: Text("ente"),
+          isDestructiveAction: true,
+          onPressed: () async {
+            Navigator.of(context, rootNavigator: true).pop();
+            await deleteFilesFromRemoteOnly(
+              context,
+              widget.selectedFiles.files.toList(),
+            );
+            _clearSelectedFiles();
+            showShortToast(context, "Moved to trash");
+          },
+        ),
+      );
+      actions.add(
+        CupertinoActionSheetAction(
+          child: Text("Everywhere"),
+          isDestructiveAction: true,
+          onPressed: () async {
+            Navigator.of(context, rootNavigator: true).pop();
+            await deleteFilesFromEverywhere(
+              context,
+              widget.selectedFiles.files.toList(),
+            );
+            _clearSelectedFiles();
+          },
+        ),
+      );
     } else {
-      actions.add(CupertinoActionSheetAction(
-        child: Text("Delete"),
-        isDestructiveAction: true,
-        onPressed: () async {
-          Navigator.of(context, rootNavigator: true).pop();
-          await deleteFilesFromEverywhere(
-              context, widget.selectedFiles.files.toList(),);
-          _clearSelectedFiles();
-        },
-      ),);
+      actions.add(
+        CupertinoActionSheetAction(
+          child: Text("Delete"),
+          isDestructiveAction: true,
+          onPressed: () async {
+            Navigator.of(context, rootNavigator: true).pop();
+            await deleteFilesFromEverywhere(
+              context,
+              widget.selectedFiles.files.toList(),
+            );
+            _clearSelectedFiles();
+          },
+        ),
+      );
     }
     final action = CupertinoActionSheet(
-      title: Text("Delete " +
-          count.toString() +
-          " file" +
-          (count == 1 ? "" : "s") +
-          (containsUploadedFile && containsLocalFile ? " from" : "?"),),
+      title: Text(
+        "Delete " +
+            count.toString() +
+            " file" +
+            (count == 1 ? "" : "s") +
+            (containsUploadedFile && containsLocalFile ? " from" : "?"),
+      ),
       actions: actions,
       cancelButton: CupertinoActionSheetAction(
         child: Text("Cancel"),
@@ -508,13 +554,15 @@ class _OverlayWidgetState extends State<OverlayWidget> {
   void _showRemoveFromCollectionSheet(BuildContext context) {
     final count = widget.selectedFiles.files.length;
     final action = CupertinoActionSheet(
-      title: Text("Remove " +
-          count.toString() +
-          " file" +
-          (count == 1 ? "" : "s") +
-          " from " +
-          widget.collection.name +
-          "?",),
+      title: Text(
+        "Remove " +
+            count.toString() +
+            " file" +
+            (count == 1 ? "" : "s") +
+            " from " +
+            widget.collection.name +
+            "?",
+      ),
       actions: <Widget>[
         CupertinoActionSheetAction(
           child: Text("Remove"),
@@ -525,7 +573,9 @@ class _OverlayWidgetState extends State<OverlayWidget> {
             await dialog.show();
             try {
               await CollectionsService.instance.removeFromCollection(
-                  widget.collection.id, widget.selectedFiles.files.toList(),);
+                widget.collection.id,
+                widget.selectedFiles.files.toList(),
+              );
               await dialog.hide();
               widget.selectedFiles.clearAll();
             } catch (e, s) {

+ 23 - 15
lib/ui/grant_permissions_widget.dart

@@ -47,28 +47,34 @@ class GrantPermissionsWidget extends StatelessWidget {
                   Padding(
                     padding: const EdgeInsets.symmetric(horizontal: 40),
                     child: RichText(
-                        text: TextSpan(
+                      text: TextSpan(
+                        style: Theme.of(context)
+                            .textTheme
+                            .headline5
+                            .copyWith(fontWeight: FontWeight.w700),
+                        children: [
+                          TextSpan(text: 'ente '),
+                          TextSpan(
+                            text: "needs permission to ",
                             style: Theme.of(context)
                                 .textTheme
                                 .headline5
-                                .copyWith(fontWeight: FontWeight.w700),
-                            children: [
-                          TextSpan(text: 'ente '),
-                          TextSpan(
-                              text: "needs permission to ",
-                              style: Theme.of(context)
-                                  .textTheme
-                                  .headline5
-                                  .copyWith(fontWeight: FontWeight.w400),),
+                                .copyWith(fontWeight: FontWeight.w400),
+                          ),
                           TextSpan(text: 'preserve your photos')
-                        ],),),
+                        ],
+                      ),
+                    ),
                   ),
                 ],
               ),
               Container(
                 width: double.infinity,
                 padding: EdgeInsets.only(
-                    left: 20, right: 20, bottom: Platform.isIOS ? 84 : 60,),
+                  left: 20,
+                  right: 20,
+                  bottom: Platform.isIOS ? 84 : 60,
+                ),
                 child: OutlinedButton(
                   child: Text("Grant permission"),
                   onPressed: () async {
@@ -80,7 +86,8 @@ class GrantPermissionsWidget extends StatelessWidget {
                       AlertDialog alert = AlertDialog(
                         title: Text("Please grant permissions"),
                         content: Text(
-                            "ente can encrypt and preserve files only if you grant access to them",),
+                          "ente can encrypt and preserve files only if you grant access to them",
+                        ),
                         actions: [
                           TextButton(
                             child: Text(
@@ -89,8 +96,9 @@ class GrantPermissionsWidget extends StatelessWidget {
                                   .textTheme
                                   .subtitle1
                                   .copyWith(
-                                      fontSize: 14,
-                                      fontWeight: FontWeight.w700,),
+                                    fontSize: 14,
+                                    fontWeight: FontWeight.w700,
+                                  ),
                             ),
                             onPressed: () {
                               Navigator.of(context, rootNavigator: true)

+ 171 - 145
lib/ui/home_widget.dart

@@ -183,7 +183,8 @@ class _HomeWidgetState extends State<HomeWidget> {
             context: context,
             builder: (BuildContext context) {
               return AppUpdateDialog(
-                  UpdateService.instance.getLatestVersionInfo(),);
+                UpdateService.instance.getLatestVersionInfo(),
+              );
             },
             barrierColor: Colors.black.withOpacity(0.85),
           );
@@ -209,14 +210,17 @@ class _HomeWidgetState extends State<HomeWidget> {
   }
 
   void _initMediaShareSubscription() {
-    _intentDataStreamSubscription = ReceiveSharingIntent.getMediaStream()
-        .listen((List<SharedMediaFile> value) {
-      setState(() {
-        _sharedFiles = value;
-      });
-    }, onError: (err) {
-      _logger.severe("getIntentDataStream error: $err");
-    },);
+    _intentDataStreamSubscription =
+        ReceiveSharingIntent.getMediaStream().listen(
+      (List<SharedMediaFile> value) {
+        setState(() {
+          _sharedFiles = value;
+        });
+      },
+      onError: (err) {
+        _logger.severe("getIntentDataStream error: $err");
+      },
+    );
     // For sharing images coming from outside the app while the app is closed
     ReceiveSharingIntent.getInitialMedia().then((List<SharedMediaFile> value) {
       setState(() {
@@ -283,10 +287,12 @@ class _HomeWidgetState extends State<HomeWidget> {
             _settingsPage,
           ],
           onPageChanged: (page) {
-            Bus.instance.fire(TabChangedEvent(
-              page,
-              TabChangedEventSource.page_view,
-            ),);
+            Bus.instance.fire(
+              TabChangedEvent(
+                page,
+                TabChangedEventSource.page_view,
+              ),
+            );
           },
           physics: NeverScrollableScrollPhysics(),
           controller: _pageController,
@@ -330,12 +336,15 @@ class _HomeWidgetState extends State<HomeWidget> {
     }
 
     // Attach a listener to the stream
-    linkStream.listen((String link) {
-      _logger.info("Link received: " + link);
-      _getCredentials(context, link);
-    }, onError: (err) {
-      _logger.severe(err);
-    },);
+    linkStream.listen(
+      (String link) {
+        _logger.info("Link received: " + link);
+        _getCredentials(context, link);
+      },
+      onError: (err) {
+        _logger.severe(err);
+      },
+    );
     return false;
   }
 
@@ -362,31 +371,43 @@ class _HomeWidgetState extends State<HomeWidget> {
             CollectionsService.instance.getArchivedCollections();
         FileLoadResult result;
         if (importantPaths.isNotEmpty) {
-          result = await FilesDB.instance.getImportantFiles(creationStartTime,
-              creationEndTime, ownerID, importantPaths.toList(),
-              limit: limit,
-              asc: asc,
-              ignoredCollectionIDs: archivedCollectionIds,);
+          result = await FilesDB.instance.getImportantFiles(
+            creationStartTime,
+            creationEndTime,
+            ownerID,
+            importantPaths.toList(),
+            limit: limit,
+            asc: asc,
+            ignoredCollectionIDs: archivedCollectionIds,
+          );
         } else {
           if (LocalSyncService.instance.hasGrantedLimitedPermissions()) {
             result = await FilesDB.instance.getAllLocalAndUploadedFiles(
-                creationStartTime, creationEndTime, ownerID,
-                limit: limit,
-                asc: asc,
-                ignoredCollectionIDs: archivedCollectionIds,);
+              creationStartTime,
+              creationEndTime,
+              ownerID,
+              limit: limit,
+              asc: asc,
+              ignoredCollectionIDs: archivedCollectionIds,
+            );
           } else {
             result = await FilesDB.instance.getAllUploadedFiles(
-                creationStartTime, creationEndTime, ownerID,
-                limit: limit,
-                asc: asc,
-                ignoredCollectionIDs: archivedCollectionIds,);
+              creationStartTime,
+              creationEndTime,
+              ownerID,
+              limit: limit,
+              asc: asc,
+              ignoredCollectionIDs: archivedCollectionIds,
+            );
           }
         }
         // hide ignored files from home page UI
         final ignoredIDs = await IgnoredFilesService.instance.ignoredIDs;
-        result.files.removeWhere((f) =>
-            f.uploadedFileID == null &&
-            IgnoredFilesService.instance.shouldSkipUpload(ignoredIDs, f),);
+        result.files.removeWhere(
+          (f) =>
+              f.uploadedFileID == null &&
+              IgnoredFilesService.instance.shouldSkipUpload(ignoredIDs, f),
+        );
         return result;
       },
       reloadEvent: Bus.instance.on<LocalPhotosUpdatedEvent>(),
@@ -426,11 +447,13 @@ class _HomeWidgetState extends State<HomeWidget> {
             height: 206,
           ),
         ),
-        Text('No photos are being backed up right now',
-            style: Theme.of(context)
-                .textTheme
-                .caption
-                .copyWith(fontFamily: 'Inter-Medium', fontSize: 16),),
+        Text(
+          'No photos are being backed up right now',
+          style: Theme.of(context)
+              .textTheme
+              .caption
+              .copyWith(fontFamily: 'Inter-Medium', fontSize: 16),
+        ),
         Center(
           child: Hero(
             tag: "select_folders",
@@ -560,10 +583,12 @@ class _HomeBottomNavigationBarState extends State<HomeBottomNavigationBar> {
   }
 
   void _onTabChange(int index) {
-    Bus.instance.fire(TabChangedEvent(
-      index,
-      TabChangedEventSource.tab_bar,
-    ),);
+    Bus.instance.fire(
+      TabChangedEvent(
+        index,
+        TabChangedEventSource.tab_bar,
+      ),
+    );
   }
 
   @override
@@ -580,111 +605,112 @@ class _HomeBottomNavigationBarState extends State<HomeBottomNavigationBar> {
         child: IgnorePointer(
           ignoring: filesAreSelected,
           child: ListView(
-              physics: const NeverScrollableScrollPhysics(),
-              children: [
-                Row(
-                  mainAxisAlignment: MainAxisAlignment.center,
-                  children: [
-                    ClipRRect(
-                      borderRadius: BorderRadius.circular(36),
-                      child: Container(
-                        alignment: Alignment.bottomCenter,
-                        height: 52,
-                        width: 240,
-                        child: ClipRect(
-                          child: BackdropFilter(
-                            filter: ImageFilter.blur(sigmaX: 20, sigmaY: 20),
-                            child: GNav(
-                              curve: Curves.easeOutExpo,
-                              backgroundColor: Theme.of(context)
-                                  .colorScheme
-                                  .gNavBackgroundColor,
-                              mainAxisAlignment: MainAxisAlignment.center,
-                              rippleColor: Colors.white.withOpacity(0.1),
-                              activeColor: Theme.of(context)
-                                  .colorScheme
-                                  .gNavBarActiveColor,
-                              iconSize: 24,
-                              padding: EdgeInsets.fromLTRB(16, 8, 16, 8),
-                              duration: Duration(milliseconds: 200),
-                              gap: 0,
-                              tabBorderRadius: 24,
-                              tabBackgroundColor: Theme.of(context)
-                                  .colorScheme
-                                  .gNavBarActiveColor,
-                              haptic: false,
-                              tabs: [
-                                GButton(
-                                  margin: EdgeInsets.fromLTRB(6, 6, 0, 6),
-                                  icon: Icons.home,
-                                  iconColor: Theme.of(context)
-                                      .colorScheme
-                                      .gNavIconColor,
-                                  iconActiveColor: Theme.of(context)
-                                      .colorScheme
-                                      .gNavActiveIconColor,
-                                  text: '',
-                                  onPressed: () {
-                                    _onTabChange(
-                                        0,); // To take care of occasional missing events
-                                  },
-                                ),
-                                GButton(
-                                  margin: EdgeInsets.fromLTRB(0, 6, 0, 6),
-                                  icon: Icons.photo_library,
-                                  iconColor: Theme.of(context)
-                                      .colorScheme
-                                      .gNavIconColor,
-                                  iconActiveColor: Theme.of(context)
-                                      .colorScheme
-                                      .gNavActiveIconColor,
-                                  text: '',
-                                  onPressed: () {
-                                    _onTabChange(
-                                        1,); // To take care of occasional missing events
-                                  },
-                                ),
-                                GButton(
-                                  margin: EdgeInsets.fromLTRB(0, 6, 0, 6),
-                                  icon: Icons.folder_shared,
-                                  iconColor: Theme.of(context)
-                                      .colorScheme
-                                      .gNavIconColor,
-                                  iconActiveColor: Theme.of(context)
-                                      .colorScheme
-                                      .gNavActiveIconColor,
-                                  text: '',
-                                  onPressed: () {
-                                    _onTabChange(
-                                        2,); // To take care of occasional missing events
-                                  },
-                                ),
-                                GButton(
-                                  margin: EdgeInsets.fromLTRB(0, 6, 6, 6),
-                                  icon: Icons.person,
-                                  iconColor: Theme.of(context)
-                                      .colorScheme
-                                      .gNavIconColor,
-                                  iconActiveColor: Theme.of(context)
-                                      .colorScheme
-                                      .gNavActiveIconColor,
-                                  text: '',
-                                  onPressed: () {
-                                    _onTabChange(
-                                        3,); // To take care of occasional missing events
-                                  },
-                                )
-                              ],
-                              selectedIndex: currentTabIndex,
-                              onTabChange: _onTabChange,
-                            ),
+            physics: const NeverScrollableScrollPhysics(),
+            children: [
+              Row(
+                mainAxisAlignment: MainAxisAlignment.center,
+                children: [
+                  ClipRRect(
+                    borderRadius: BorderRadius.circular(36),
+                    child: Container(
+                      alignment: Alignment.bottomCenter,
+                      height: 52,
+                      width: 240,
+                      child: ClipRect(
+                        child: BackdropFilter(
+                          filter: ImageFilter.blur(sigmaX: 20, sigmaY: 20),
+                          child: GNav(
+                            curve: Curves.easeOutExpo,
+                            backgroundColor: Theme.of(context)
+                                .colorScheme
+                                .gNavBackgroundColor,
+                            mainAxisAlignment: MainAxisAlignment.center,
+                            rippleColor: Colors.white.withOpacity(0.1),
+                            activeColor: Theme.of(context)
+                                .colorScheme
+                                .gNavBarActiveColor,
+                            iconSize: 24,
+                            padding: EdgeInsets.fromLTRB(16, 8, 16, 8),
+                            duration: Duration(milliseconds: 200),
+                            gap: 0,
+                            tabBorderRadius: 24,
+                            tabBackgroundColor: Theme.of(context)
+                                .colorScheme
+                                .gNavBarActiveColor,
+                            haptic: false,
+                            tabs: [
+                              GButton(
+                                margin: EdgeInsets.fromLTRB(6, 6, 0, 6),
+                                icon: Icons.home,
+                                iconColor:
+                                    Theme.of(context).colorScheme.gNavIconColor,
+                                iconActiveColor: Theme.of(context)
+                                    .colorScheme
+                                    .gNavActiveIconColor,
+                                text: '',
+                                onPressed: () {
+                                  _onTabChange(
+                                    0,
+                                  ); // To take care of occasional missing events
+                                },
+                              ),
+                              GButton(
+                                margin: EdgeInsets.fromLTRB(0, 6, 0, 6),
+                                icon: Icons.photo_library,
+                                iconColor:
+                                    Theme.of(context).colorScheme.gNavIconColor,
+                                iconActiveColor: Theme.of(context)
+                                    .colorScheme
+                                    .gNavActiveIconColor,
+                                text: '',
+                                onPressed: () {
+                                  _onTabChange(
+                                    1,
+                                  ); // To take care of occasional missing events
+                                },
+                              ),
+                              GButton(
+                                margin: EdgeInsets.fromLTRB(0, 6, 0, 6),
+                                icon: Icons.folder_shared,
+                                iconColor:
+                                    Theme.of(context).colorScheme.gNavIconColor,
+                                iconActiveColor: Theme.of(context)
+                                    .colorScheme
+                                    .gNavActiveIconColor,
+                                text: '',
+                                onPressed: () {
+                                  _onTabChange(
+                                    2,
+                                  ); // To take care of occasional missing events
+                                },
+                              ),
+                              GButton(
+                                margin: EdgeInsets.fromLTRB(0, 6, 6, 6),
+                                icon: Icons.person,
+                                iconColor:
+                                    Theme.of(context).colorScheme.gNavIconColor,
+                                iconActiveColor: Theme.of(context)
+                                    .colorScheme
+                                    .gNavActiveIconColor,
+                                text: '',
+                                onPressed: () {
+                                  _onTabChange(
+                                    3,
+                                  ); // To take care of occasional missing events
+                                },
+                              )
+                            ],
+                            selectedIndex: currentTabIndex,
+                            onTabChange: _onTabChange,
                           ),
                         ),
                       ),
                     ),
-                  ],
-                ),
-              ],),
+                  ),
+                ],
+              ),
+            ],
+          ),
         ),
       ),
     );

+ 28 - 20
lib/ui/huge_listview/draggable_scrollbar.dart

@@ -62,9 +62,10 @@ class DraggableScrollbarState extends State<DraggableScrollbar>
 
     if (widget.initialScrollIndex > 0 && widget.totalCount > 1) {
       WidgetsBinding.instance?.addPostFrameCallback((_) {
-        setState(() => thumbOffset =
-            (widget.initialScrollIndex / widget.totalCount) *
-                (thumbMax - thumbMin),);
+        setState(
+          () => thumbOffset = (widget.initialScrollIndex / widget.totalCount) *
+              (thumbMax - thumbMin),
+        );
       });
     }
 
@@ -121,7 +122,6 @@ class DraggableScrollbarState extends State<DraggableScrollbar>
     } else {
       return buildThumb();
     }
-
   }
 
   Widget buildThumb() => Container(
@@ -191,25 +191,33 @@ class DraggableScrollbarState extends State<DraggableScrollbar>
   void keyHandler(RawKeyEvent value) {
     if (value.runtimeType == RawKeyDownEvent) {
       if (value.logicalKey == LogicalKeyboardKey.arrowDown) {
-        onDragUpdate(DragUpdateDetails(
-          globalPosition: Offset.zero,
-          delta: Offset(0, 2),
-        ),);
+        onDragUpdate(
+          DragUpdateDetails(
+            globalPosition: Offset.zero,
+            delta: Offset(0, 2),
+          ),
+        );
       } else if (value.logicalKey == LogicalKeyboardKey.arrowUp) {
-        onDragUpdate(DragUpdateDetails(
-          globalPosition: Offset.zero,
-          delta: Offset(0, -2),
-        ),);
+        onDragUpdate(
+          DragUpdateDetails(
+            globalPosition: Offset.zero,
+            delta: Offset(0, -2),
+          ),
+        );
       } else if (value.logicalKey == LogicalKeyboardKey.pageDown) {
-        onDragUpdate(DragUpdateDetails(
-          globalPosition: Offset.zero,
-          delta: Offset(0, 25),
-        ),);
+        onDragUpdate(
+          DragUpdateDetails(
+            globalPosition: Offset.zero,
+            delta: Offset(0, 25),
+          ),
+        );
       } else if (value.logicalKey == LogicalKeyboardKey.pageUp) {
-        onDragUpdate(DragUpdateDetails(
-          globalPosition: Offset.zero,
-          delta: Offset(0, -25),
-        ),);
+        onDragUpdate(
+          DragUpdateDetails(
+            globalPosition: Offset.zero,
+            delta: Offset(0, -25),
+          ),
+        );
       }
     }
   }

+ 8 - 4
lib/ui/huge_listview/huge_listview.dart

@@ -5,9 +5,13 @@ import 'package:photos/ui/huge_listview/draggable_scrollbar.dart';
 import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
 
 typedef HugeListViewItemBuilder<T> = Widget Function(
-    BuildContext context, int index,);
+  BuildContext context,
+  int index,
+);
 typedef HugeListViewErrorBuilder = Widget Function(
-    BuildContext context, dynamic error,);
+  BuildContext context,
+  dynamic error,
+);
 
 class HugeListView<T> extends StatefulWidget {
   /// A [ScrollablePositionedList] controller for jumping or scrolling to an item.
@@ -61,11 +65,11 @@ class HugeListView<T> extends StatefulWidget {
     this.emptyResultBuilder,
     this.errorBuilder,
     this.firstShown,
-    this.thumbBackgroundColor = Colors.red,// Colors.white,
+    this.thumbBackgroundColor = Colors.red, // Colors.white,
     this.thumbDrawColor = Colors.yellow, //Colors.grey,
     this.thumbHeight = 48.0,
     this.isDraggableScrollbarEnabled = true,
-  })  : super(key: key);
+  }) : super(key: key);
 
   @override
   HugeListViewState<T> createState() => HugeListViewState<T>();

+ 31 - 20
lib/ui/huge_listview/lazy_loading_gallery.dart

@@ -101,8 +101,9 @@ class _LazyLoadingGalleryState extends State<LazyLoadingGallery> {
         final dayStartTime =
             DateTime(galleryDate.year, galleryDate.month, galleryDate.day);
         final result = await widget.asyncLoader(
-            dayStartTime.microsecondsSinceEpoch,
-            dayStartTime.microsecondsSinceEpoch + kMicroSecondsInDay - 1,);
+          dayStartTime.microsecondsSinceEpoch,
+          dayStartTime.microsecondsSinceEpoch + kMicroSecondsInDay - 1,
+        );
         if (mounted) {
           setState(() {
             _files = result.files;
@@ -152,7 +153,10 @@ class _LazyLoadingGalleryState extends State<LazyLoadingGallery> {
       child: Column(
         children: [
           getDayWidget(
-              context, _files[0].creationTime, widget.smallerTodayFont,),
+            context,
+            _files[0].creationTime,
+            widget.smallerTodayFont,
+          ),
           _shouldRender ? _getGallery() : PlaceHolderWidget(_files.length),
         ],
       ),
@@ -162,14 +166,17 @@ class _LazyLoadingGalleryState extends State<LazyLoadingGallery> {
   Widget _getGallery() {
     List<Widget> childGalleries = [];
     for (int index = 0; index < _files.length; index += kSubGalleryItemLimit) {
-      childGalleries.add(LazyLoadingGridView(
-        widget.tag,
-        _files.sublist(index, min(index + kSubGalleryItemLimit, _files.length)),
-        widget.asyncLoader,
-        widget.selectedFiles,
-        index == 0,
-        _files.length > kRecycleLimit,
-      ),);
+      childGalleries.add(
+        LazyLoadingGridView(
+          widget.tag,
+          _files.sublist(
+              index, min(index + kSubGalleryItemLimit, _files.length)),
+          widget.asyncLoader,
+          widget.selectedFiles,
+          index == 0,
+          _files.length > kRecycleLimit,
+        ),
+      );
     }
 
     return Column(
@@ -314,9 +321,11 @@ class _LazyLoadingGridViewState extends State<LazyLoadingGridView> {
                 tag: widget.tag + file.tag(),
                 child: ColorFiltered(
                   colorFilter: ColorFilter.mode(
-                      Colors.black.withOpacity(
-                          widget.selectedFiles.files.contains(file) ? 0.4 : 0,),
-                      BlendMode.darken,),
+                    Colors.black.withOpacity(
+                      widget.selectedFiles.files.contains(file) ? 0.4 : 0,
+                    ),
+                    BlendMode.darken,
+                  ),
                   child: ThumbnailWidget(
                     file,
                     diskLoadDeferDuration: kThumbnailDiskLoadDeferDuration,
@@ -350,12 +359,14 @@ class _LazyLoadingGridViewState extends State<LazyLoadingGridView> {
   }
 
   void _routeToDetailPage(File file, BuildContext context) {
-    final page = DetailPage(DetailPageConfiguration(
-      List.unmodifiable(widget.files),
-      widget.asyncLoader,
-      widget.files.indexOf(file),
-      widget.tag,
-    ),);
+    final page = DetailPage(
+      DetailPageConfiguration(
+        List.unmodifiable(widget.files),
+        widget.asyncLoader,
+        widget.files.indexOf(file),
+        widget.tag,
+      ),
+    );
     routeToPage(context, page);
   }
 }

+ 17 - 9
lib/ui/huge_listview/scroll_bar_thumb.dart

@@ -62,8 +62,8 @@ class ScrollBarThumb extends StatelessWidget {
               child: Material(
                 elevation: 4.0,
                 child: Container(
-                    constraints:
-                        BoxConstraints.tight(Size(height * 0.6, height)),),
+                  constraints: BoxConstraints.tight(Size(height * 0.6, height)),
+                ),
                 color: backgroundColor,
                 borderRadius: BorderRadius.only(
                   topLeft: Radius.circular(height),
@@ -100,20 +100,28 @@ class _ArrowCustomPainter extends CustomPainter {
     final baseY = size.height / 2;
 
     canvas.drawPath(
-        trianglePath(Offset(baseX - 2.0, baseY - 2.0), width, height, true),
-        paint,);
+      trianglePath(Offset(baseX - 2.0, baseY - 2.0), width, height, true),
+      paint,
+    );
     canvas.drawPath(
-        trianglePath(Offset(baseX - 2.0, baseY + 2.0), width, height, false),
-        paint,);
+      trianglePath(Offset(baseX - 2.0, baseY + 2.0), width, height, false),
+      paint,
+    );
   }
 
   static Path trianglePath(
-      Offset offset, double width, double height, bool isUp,) {
+    Offset offset,
+    double width,
+    double height,
+    bool isUp,
+  ) {
     return Path()
       ..moveTo(offset.dx, offset.dy)
       ..lineTo(offset.dx + width, offset.dy)
-      ..lineTo(offset.dx + (width / 2),
-          isUp ? offset.dy - height : offset.dy + height,)
+      ..lineTo(
+        offset.dx + (width / 2),
+        isUp ? offset.dy - height : offset.dy + height,
+      )
       ..close();
   }
 }

+ 5 - 3
lib/ui/image_editor_page.dart

@@ -308,7 +308,8 @@ class _ImageEditorPageState extends State<ImageEditorPage> {
 
     option.addOption(ClipOption.fromRect(rect));
     option.addOption(
-        FlipOption(horizontal: flipHorizontal, vertical: flipVertical),);
+      FlipOption(horizontal: flipHorizontal, vertical: flipVertical),
+    );
     if (action.hasRotateAngle) {
       option.addOption(RotateOption(radian.toInt()));
     }
@@ -363,8 +364,9 @@ class _ImageEditorPageState extends State<ImageEditorPage> {
       _logger.info("Saved edits to file " + newFile.toString());
       final existingFiles = widget.detailPageConfig.files;
       final files = (await widget.detailPageConfig.asyncLoader(
-              existingFiles[existingFiles.length - 1].creationTime,
-              existingFiles[0].creationTime,))
+        existingFiles[existingFiles.length - 1].creationTime,
+        existingFiles[0].creationTime,
+      ))
           .files;
       replacePage(
         context,

+ 4 - 2
lib/ui/landing_page_widget.dart

@@ -55,9 +55,11 @@ class _LandingPageWidgetState extends State<LandingPageWidget> {
                     Theme.of(context).colorScheme.dotsIndicatorActiveColor,
                 color: Theme.of(context).colorScheme.dotsIndicatorInactiveColor,
                 activeShape: RoundedRectangleBorder(
-                    borderRadius: BorderRadius.circular(3),),
+                  borderRadius: BorderRadius.circular(3),
+                ),
                 shape: RoundedRectangleBorder(
-                    borderRadius: BorderRadius.circular(3),),
+                  borderRadius: BorderRadius.circular(3),
+                ),
                 size: Size(100, 5),
                 activeSize: Size(100, 5),
                 spacing: EdgeInsets.all(3),

+ 25 - 22
lib/ui/loading_photos_widget.dart

@@ -45,11 +45,12 @@ class _LoadingPhotosWidgetState extends State<LoadingPhotosWidget> {
           // Do nothing, let HomeWidget refresh
         } else {
           routeToPage(
-              context,
-              BackupFolderSelectionPage(
-                shouldSelectAll: true,
-                buttonText: "Start backup",
-              ),);
+            context,
+            BackupFolderSelectionPage(
+              shouldSelectAll: true,
+              buttonText: "Start backup",
+            ),
+          );
         }
       }
     });
@@ -134,23 +135,25 @@ class _LoadingPhotosWidgetState extends State<LoadingPhotosWidget> {
                   ),
                   SizedBox(
                     height: 175,
-                    child: Stack(children: [
-                      PageView.builder(
-                        scrollDirection: Axis.vertical,
-                        controller: _pageController,
-                        itemBuilder: (context, index) {
-                          return _getMessage(_messages[index]);
-                        },
-                        itemCount: _messages.length,
-                        physics: NeverScrollableScrollPhysics(),
-                      ),
-                      Positioned(
-                        bottom: 0,
-                        left: 0,
-                        right: 0,
-                        child: BottomShadowWidget(),
-                      )
-                    ],),
+                    child: Stack(
+                      children: [
+                        PageView.builder(
+                          scrollDirection: Axis.vertical,
+                          controller: _pageController,
+                          itemBuilder: (context, index) {
+                            return _getMessage(_messages[index]);
+                          },
+                          itemCount: _messages.length,
+                          physics: NeverScrollableScrollPhysics(),
+                        ),
+                        Positioned(
+                          bottom: 0,
+                          left: 0,
+                          right: 0,
+                          child: BottomShadowWidget(),
+                        )
+                      ],
+                    ),
                   ),
                 ],
               ),

+ 37 - 32
lib/ui/location_search_widget.dart

@@ -48,7 +48,8 @@ class _LocationSearchWidgetState extends State<LocationSearchWidget> {
                 "query": pattern,
               },
               options: Options(
-                  headers: {"X-Auth-Token": Configuration.instance.getToken()},),
+                headers: {"X-Auth-Token": Configuration.instance.getToken()},
+              ),
             )
             .then((response) {
           if (_searchString == pattern) {
@@ -63,21 +64,23 @@ class _LocationSearchWidgetState extends State<LocationSearchWidget> {
       },
       onSuggestionSelected: (suggestion) {
         Navigator.pop(context);
-        Navigator.of(context).push(MaterialPageRoute(
+        Navigator.of(context).push(
+          MaterialPageRoute(
             builder: (context) => LocationSearchResultsPage(
-                  ViewPort(
-                      Location(
-                          suggestion['geometry']['viewport']['northeast']
-                              ['lat'],
-                          suggestion['geometry']['viewport']['northeast']
-                              ['lng'],),
-                      Location(
-                          suggestion['geometry']['viewport']['southwest']
-                              ['lat'],
-                          suggestion['geometry']['viewport']['southwest']
-                              ['lng'],),),
-                  suggestion['name'],
-                ),),);
+              ViewPort(
+                Location(
+                  suggestion['geometry']['viewport']['northeast']['lat'],
+                  suggestion['geometry']['viewport']['northeast']['lng'],
+                ),
+                Location(
+                  suggestion['geometry']['viewport']['southwest']['lat'],
+                  suggestion['geometry']['viewport']['southwest']['lng'],
+                ),
+              ),
+              suggestion['name'],
+            ),
+          ),
+        );
       },
     );
   }
@@ -95,25 +98,27 @@ class LocationSearchResultWidget extends StatelessWidget {
     return Container(
       padding: new EdgeInsets.symmetric(vertical: 6.0, horizontal: 6.0),
       margin: EdgeInsets.symmetric(vertical: 6.0),
-      child: Column(children: <Widget>[
-        Row(
-          mainAxisAlignment: MainAxisAlignment.start,
-          children: <Widget>[
-            Icon(
-              Icons.location_on,
-            ),
-            Padding(padding: EdgeInsets.only(left: 20.0)),
-            Flexible(
-              child: Container(
-                child: Text(
-                  name,
-                  overflow: TextOverflow.clip,
+      child: Column(
+        children: <Widget>[
+          Row(
+            mainAxisAlignment: MainAxisAlignment.start,
+            children: <Widget>[
+              Icon(
+                Icons.location_on,
+              ),
+              Padding(padding: EdgeInsets.only(left: 20.0)),
+              Flexible(
+                child: Container(
+                  child: Text(
+                    name,
+                    overflow: TextOverflow.clip,
+                  ),
                 ),
               ),
-            ),
-          ],
-        ),
-      ],),
+            ],
+          ),
+        ],
+      ),
     );
   }
 }

+ 30 - 27
lib/ui/lock_screen.dart

@@ -26,35 +26,37 @@ class _LockScreenState extends State<LockScreen> {
     return Scaffold(
       body: Center(
         child: Column(
-            crossAxisAlignment: CrossAxisAlignment.center,
-            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
-            children: [
-              Stack(
-                alignment: Alignment.center,
-                children: [
-                  Image.asset(MediaQuery.of(context).platformBrightness ==
-                          Brightness.light
+          crossAxisAlignment: CrossAxisAlignment.center,
+          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
+          children: [
+            Stack(
+              alignment: Alignment.center,
+              children: [
+                Image.asset(
+                  MediaQuery.of(context).platformBrightness == Brightness.light
                       ? 'assets/loading_photos_light.png'
-                      : 'assets/loading_photos_dark.png',),
-                  SizedBox(
-                    width: 172,
-                    child: GradientButton(
-                      child: Text(
-                        'Unlock',
-                        style: gradientButtonTextTheme(),
-                      ),
-                      linearGradientColors: const [
-                        Color(0xFF2CD267),
-                        Color(0xFF1DB954),
-                      ],
-                      onTap: () async {
-                        _showLockScreen();
-                      },
+                      : 'assets/loading_photos_dark.png',
+                ),
+                SizedBox(
+                  width: 172,
+                  child: GradientButton(
+                    child: Text(
+                      'Unlock',
+                      style: gradientButtonTextTheme(),
                     ),
+                    linearGradientColors: const [
+                      Color(0xFF2CD267),
+                      Color(0xFF1DB954),
+                    ],
+                    onTap: () async {
+                      _showLockScreen();
+                    },
                   ),
-                ],
-              ),
-            ],),
+                ),
+              ],
+            ),
+          ],
+        ),
       ),
     );
   }
@@ -63,7 +65,8 @@ class _LockScreenState extends State<LockScreen> {
     _logger.info("Showing lockscreen");
     try {
       final result = await requestAuthentication(
-          "Please authenticate to view your memories",);
+        "Please authenticate to view your memories",
+      );
       if (result) {
         AppLock.of(context).didUnlock();
       }

+ 16 - 8
lib/ui/login_page.dart

@@ -75,8 +75,10 @@ class _LoginPageState extends State<LoginPage> {
               Padding(
                 padding:
                     const EdgeInsets.symmetric(vertical: 30, horizontal: 20),
-                child: Text('Welcome back!',
-                    style: Theme.of(context).textTheme.headline4,),
+                child: Text(
+                  'Welcome back!',
+                  style: Theme.of(context).textTheme.headline4,
+                ),
               ),
               Padding(
                 padding: const EdgeInsets.fromLTRB(20, 24, 20, 0),
@@ -89,8 +91,9 @@ class _LoginPageState extends State<LoginPage> {
                     contentPadding:
                         EdgeInsets.symmetric(horizontal: 15, vertical: 15),
                     border: UnderlineInputBorder(
-                        borderSide: BorderSide.none,
-                        borderRadius: BorderRadius.circular(6),),
+                      borderSide: BorderSide.none,
+                      borderRadius: BorderRadius.circular(6),
+                    ),
                     suffixIcon: _emailIsValid
                         ? Icon(
                             Icons.check,
@@ -141,7 +144,8 @@ class _LoginPageState extends State<LoginPage> {
                               .copyWith(fontSize: 12),
                           children: [
                             TextSpan(
-                                text: "By clicking log in, I agree to the ",),
+                              text: "By clicking log in, I agree to the ",
+                            ),
                             TextSpan(
                               text: "terms of service",
                               style: TextStyle(
@@ -153,7 +157,9 @@ class _LoginPageState extends State<LoginPage> {
                                     MaterialPageRoute(
                                       builder: (BuildContext context) {
                                         return WebPage(
-                                            "terms", "https://ente.io/terms",);
+                                          "terms",
+                                          "https://ente.io/terms",
+                                        );
                                       },
                                     ),
                                   );
@@ -170,8 +176,10 @@ class _LoginPageState extends State<LoginPage> {
                                   Navigator.of(context).push(
                                     MaterialPageRoute(
                                       builder: (BuildContext context) {
-                                        return WebPage("privacy",
-                                            "https://ente.io/privacy",);
+                                        return WebPage(
+                                          "privacy",
+                                          "https://ente.io/privacy",
+                                        );
                                       },
                                     ),
                                   );

+ 56 - 30
lib/ui/manage_links_widget.dart

@@ -137,12 +137,15 @@ class _ManageSharedLinkWidgetState extends State<ManageSharedLinkWidget> {
                                   inputResult == 'ok' &&
                                   _textFieldController.text.trim().isNotEmpty) {
                                 var propToUpdate = await _getEncryptedPassword(
-                                    _textFieldController.text,);
+                                  _textFieldController.text,
+                                );
                                 await _updateUrlSettings(context, propToUpdate);
                               }
                             } else {
                               await _updateUrlSettings(
-                                  context, {'disablePassword': true},);
+                                context,
+                                {'disablePassword': true},
+                              );
                             }
                             setState(() {});
                           },
@@ -166,25 +169,31 @@ class _ManageSharedLinkWidgetState extends State<ManageSharedLinkWidget> {
                           onChanged: (value) async {
                             if (!value) {
                               final choice = await showChoiceDialog(
-                                  context,
-                                  'Disable downloads',
-                                  'Are you sure that you want to disable the download button for files?',
-                                  firstAction: 'No',
-                                  secondAction: 'Yes',
-                                  firstActionColor:
-                                      Theme.of(context).colorScheme.greenText,
-                                  secondActionColor: Theme.of(context)
-                                      .colorScheme
-                                      .inverseBackgroundColor,);
+                                context,
+                                'Disable downloads',
+                                'Are you sure that you want to disable the download button for files?',
+                                firstAction: 'No',
+                                secondAction: 'Yes',
+                                firstActionColor:
+                                    Theme.of(context).colorScheme.greenText,
+                                secondActionColor: Theme.of(context)
+                                    .colorScheme
+                                    .inverseBackgroundColor,
+                              );
                               if (choice != DialogUserChoice.secondChoice) {
                                 return;
                               }
                             }
                             await _updateUrlSettings(
-                                context, {'enableDownload': value},);
+                              context,
+                              {'enableDownload': value},
+                            );
                             if (!value) {
-                              showErrorDialog(context, "Please note",
-                                  "Viewers can still take screenshots or save a copy of your photos using external tools",);
+                              showErrorDialog(
+                                context,
+                                "Please note",
+                                "Viewers can still take screenshots or save a copy of your photos using external tools",
+                              );
                             }
                             setState(() {});
                           },
@@ -262,7 +271,9 @@ class _ManageSharedLinkWidgetState extends State<ManageSharedLinkWidget> {
                       }
                       if (newValidTill >= 0) {
                         await _updateUrlSettings(
-                            context, {'validTill': newValidTill},);
+                          context,
+                          {'validTill': newValidTill},
+                        );
                         setState(() {});
                       }
                       Navigator.of(context).pop('');
@@ -333,10 +344,11 @@ class _ManageSharedLinkWidgetState extends State<ManageSharedLinkWidget> {
   Future<String> _displayLinkPasswordInput(BuildContext context) async {
     _textFieldController.clear();
     return showDialog<String>(
-        context: context,
-        builder: (context) {
-          bool _passwordVisible = false;
-          return StatefulBuilder(builder: (context, setState) {
+      context: context,
+      builder: (context) {
+        bool _passwordVisible = false;
+        return StatefulBuilder(
+          builder: (context, setState) {
             return AlertDialog(
               title: Text('Enter password'),
               content: TextFormField(
@@ -369,8 +381,10 @@ class _ManageSharedLinkWidgetState extends State<ManageSharedLinkWidget> {
               ),
               actions: <Widget>[
                 TextButton(
-                  child: Text('Cancel',
-                      style: Theme.of(context).textTheme.subtitle2,),
+                  child: Text(
+                    'Cancel',
+                    style: Theme.of(context).textTheme.subtitle2,
+                  ),
                   onPressed: () {
                     Navigator.pop(context, 'cancel');
                   },
@@ -387,18 +401,26 @@ class _ManageSharedLinkWidgetState extends State<ManageSharedLinkWidget> {
                 ),
               ],
             );
-          },);
-        },);
+          },
+        );
+      },
+    );
   }
 
   Future<Map<String, dynamic>> _getEncryptedPassword(String pass) async {
-    assert(Sodium.cryptoPwhashAlgArgon2id13 == Sodium.cryptoPwhashAlgDefault,
-        "mismatch in expected default pw hashing algo",);
+    assert(
+      Sodium.cryptoPwhashAlgArgon2id13 == Sodium.cryptoPwhashAlgDefault,
+      "mismatch in expected default pw hashing algo",
+    );
     int memLimit = Sodium.cryptoPwhashMemlimitInteractive;
     int opsLimit = Sodium.cryptoPwhashOpslimitInteractive;
     final kekSalt = CryptoUtil.getSaltToDeriveKey();
     final result = await CryptoUtil.deriveKey(
-        utf8.encode(pass), kekSalt, memLimit, opsLimit,);
+      utf8.encode(pass),
+      kekSalt,
+      memLimit,
+      opsLimit,
+    );
     return {
       'passHash': Sodium.bin2base64(result),
       'nonce': Sodium.bin2base64(kekSalt),
@@ -408,7 +430,9 @@ class _ManageSharedLinkWidgetState extends State<ManageSharedLinkWidget> {
   }
 
   Future<void> _updateUrlSettings(
-      BuildContext context, Map<String, dynamic> prop,) async {
+    BuildContext context,
+    Map<String, dynamic> prop,
+  ) async {
     final dialog = createProgressDialog(context, "Please wait...");
     await dialog.show();
     try {
@@ -451,7 +475,8 @@ class _ManageSharedLinkWidgetState extends State<ManageSharedLinkWidget> {
     List<Text> options = [];
     for (int i = 50; i > 0; i--) {
       options.add(
-          Text(i.toString(), style: Theme.of(context).textTheme.subtitle1),);
+        Text(i.toString(), style: Theme.of(context).textTheme.subtitle1),
+      );
     }
     return showCupertinoModalPopup(
       context: context,
@@ -493,7 +518,8 @@ class _ManageSharedLinkWidgetState extends State<ManageSharedLinkWidget> {
                     onPressed: () async {
                       await _updateUrlSettings(context, {
                         'deviceLimit': int.tryParse(
-                            options[_selectedDeviceLimitIndex].data,),
+                          options[_selectedDeviceLimitIndex].data,
+                        ),
                       });
                       setState(() {});
                       Navigator.of(context).pop('');

+ 57 - 44
lib/ui/memories_widget.dart

@@ -95,7 +95,9 @@ class _MemoryWidgetState extends State<MemoryWidget> {
     return GestureDetector(
       onTap: () async {
         await routeToPage(
-            context, FullScreenMemory(title, widget.memories, index),);
+          context,
+          FullScreenMemory(title, widget.memories, index),
+        );
         setState(() {});
       },
       child: SizedBox(
@@ -261,9 +263,12 @@ class _FullScreenMemoryState extends State<FullScreenMemory> {
                 ),
                 Text(
                   getFormattedDate(
-                      DateTime.fromMicrosecondsSinceEpoch(file.creationTime),),
+                    DateTime.fromMicrosecondsSinceEpoch(file.creationTime),
+                  ),
                   style: Theme.of(context).textTheme.subtitle1.copyWith(
-                      fontSize: 14, color: Colors.white,), //same for both themes
+                        fontSize: 14,
+                        color: Colors.white,
+                      ), //same for both themes
                 ),
               ],
             ),
@@ -271,16 +276,17 @@ class _FullScreenMemoryState extends State<FullScreenMemory> {
         ),
         flexibleSpace: Container(
           decoration: BoxDecoration(
-              gradient: LinearGradient(
-            begin: Alignment.topCenter,
-            end: Alignment.bottomCenter,
-            colors: [
-              Colors.black.withOpacity(0.6),
-              Colors.black.withOpacity(0.5),
-              Colors.transparent,
-            ],
-            stops: const [0, 0.6, 1],
-          ),),
+            gradient: LinearGradient(
+              begin: Alignment.topCenter,
+              end: Alignment.bottomCenter,
+              colors: [
+                Colors.black.withOpacity(0.6),
+                Colors.black.withOpacity(0.5),
+                Colors.transparent,
+              ],
+              stops: const [0, 0.6, 1],
+            ),
+          ),
         ),
         backgroundColor: Color(0x00000000),
         elevation: 0,
@@ -288,12 +294,15 @@ class _FullScreenMemoryState extends State<FullScreenMemory> {
       extendBodyBehindAppBar: true,
       body: Container(
         color: Colors.black,
-        child: Stack(alignment: Alignment.bottomCenter, children: [
-          _buildSwiper(),
-          bottomGradient(),
-          _buildTitleText(),
-          _buildBottomIcons(),
-        ],),
+        child: Stack(
+          alignment: Alignment.bottomCenter,
+          children: [
+            _buildSwiper(),
+            bottomGradient(),
+            _buildTitleText(),
+            _buildBottomIcons(),
+          ],
+        ),
       ),
     );
   }
@@ -307,11 +316,13 @@ class _FullScreenMemoryState extends State<FullScreenMemory> {
         child: AnimatedOpacity(
           opacity: _opacity,
           duration: Duration(milliseconds: 500),
-          child: Text(widget.title,
-              style: Theme.of(context)
-                  .textTheme
-                  .headline4
-                  .copyWith(color: Colors.white),),
+          child: Text(
+            widget.title,
+            style: Theme.of(context)
+                .textTheme
+                .headline4
+                .copyWith(color: Colors.white),
+          ),
         ),
       ),
     );
@@ -320,17 +331,18 @@ class _FullScreenMemoryState extends State<FullScreenMemory> {
   Widget _buildBottomIcons() {
     final file = widget.memories[_index].file;
     return Container(
-        alignment: Alignment.bottomRight,
-        padding: EdgeInsets.fromLTRB(0, 0, 26, 20),
-        child: IconButton(
-          icon: Icon(
-            Icons.adaptive.share,
-            color: Colors.white,
-          ), //same for both themes
-          onPressed: () {
-            share(context, [file]);
-          },
-        ),);
+      alignment: Alignment.bottomRight,
+      padding: EdgeInsets.fromLTRB(0, 0, 26, 20),
+      child: IconButton(
+        icon: Icon(
+          Icons.adaptive.share,
+          color: Colors.white,
+        ), //same for both themes
+        onPressed: () {
+          share(context, [file]);
+        },
+      ),
+    );
   }
 
   Widget bottomGradient() {
@@ -338,15 +350,16 @@ class _FullScreenMemoryState extends State<FullScreenMemory> {
       height: 124,
       width: double.infinity,
       decoration: BoxDecoration(
-          gradient: LinearGradient(
-        begin: Alignment.bottomCenter,
-        end: Alignment.topCenter,
-        colors: [
-          Colors.black.withOpacity(0.5), //same for both themes
-          Colors.transparent,
-        ],
-        stops: const [0, 0.8],
-      ),),
+        gradient: LinearGradient(
+          begin: Alignment.bottomCenter,
+          end: Alignment.topCenter,
+          colors: [
+            Colors.black.withOpacity(0.5), //same for both themes
+            Colors.transparent,
+          ],
+          stops: const [0, 0.8],
+        ),
+      ),
     );
   }
 

+ 90 - 87
lib/ui/nav_bar.dart

@@ -77,65 +77,65 @@ class _GNavState extends State<GNav> {
     selectedIndex = widget.selectedIndex;
 
     return Container(
-        color: widget.backgroundColor ?? Colors.transparent,
-        // padding: EdgeInsets.all(12),
-        // alignment: Alignment.center,
-        child: Row(
-            mainAxisAlignment: widget.mainAxisAlignment,
-            children: widget.tabs
-                .map((t) => GButton(
-                      key: t.key,
-                      border: t.border ?? widget.tabBorder,
-                      activeBorder: t.activeBorder ?? widget.tabActiveBorder,
-                      borderRadius:
-                          t.borderRadius ?? widget.tabBorderRadius != null
-                              ? BorderRadius.all(
-                                  Radius.circular(widget.tabBorderRadius),)
-                              : const BorderRadius.all(Radius.circular(100.0)),
-                      debug: widget.debug ?? false,
-                      margin: t.margin ?? widget.tabMargin,
-                      active: selectedIndex == widget.tabs.indexOf(t),
-                      gap: t.gap ?? widget.gap,
-                      iconActiveColor: t.iconActiveColor ?? widget.activeColor,
-                      iconColor: t.iconColor ?? widget.color,
-                      iconSize: t.iconSize ?? widget.iconSize,
-                      textColor: t.textColor ?? widget.activeColor,
-                      rippleColor: t.rippleColor ??
-                          widget.rippleColor ??
-                          Colors.transparent,
-                      hoverColor: t.hoverColor ??
-                          widget.hoverColor ??
-                          Colors.transparent,
-                      padding: t.padding ?? widget.padding,
-                      icon: t.icon,
-                      haptic: widget.haptic ?? true,
-                      leading: t.leading,
-                      curve: widget.curve ?? Curves.easeInCubic,
-                      backgroundGradient:
-                          t.backgroundGradient ?? widget.tabBackgroundGradient,
-                      backgroundColor: t.backgroundColor ??
-                          widget.tabBackgroundColor ??
-                          Colors.transparent,
-                      duration:
-                          widget.duration ?? const Duration(milliseconds: 500),
-                      onPressed: () {
-                        if (!clickable) return;
-                        setState(() {
-                          selectedIndex = widget.tabs.indexOf(t);
-                          clickable = false;
-                        });
-                        widget.onTabChange(selectedIndex);
+      color: widget.backgroundColor ?? Colors.transparent,
+      // padding: EdgeInsets.all(12),
+      // alignment: Alignment.center,
+      child: Row(
+        mainAxisAlignment: widget.mainAxisAlignment,
+        children: widget.tabs
+            .map(
+              (t) => GButton(
+                key: t.key,
+                border: t.border ?? widget.tabBorder,
+                activeBorder: t.activeBorder ?? widget.tabActiveBorder,
+                borderRadius: t.borderRadius ?? widget.tabBorderRadius != null
+                    ? BorderRadius.all(
+                        Radius.circular(widget.tabBorderRadius),
+                      )
+                    : const BorderRadius.all(Radius.circular(100.0)),
+                debug: widget.debug ?? false,
+                margin: t.margin ?? widget.tabMargin,
+                active: selectedIndex == widget.tabs.indexOf(t),
+                gap: t.gap ?? widget.gap,
+                iconActiveColor: t.iconActiveColor ?? widget.activeColor,
+                iconColor: t.iconColor ?? widget.color,
+                iconSize: t.iconSize ?? widget.iconSize,
+                textColor: t.textColor ?? widget.activeColor,
+                rippleColor:
+                    t.rippleColor ?? widget.rippleColor ?? Colors.transparent,
+                hoverColor:
+                    t.hoverColor ?? widget.hoverColor ?? Colors.transparent,
+                padding: t.padding ?? widget.padding,
+                icon: t.icon,
+                haptic: widget.haptic ?? true,
+                leading: t.leading,
+                curve: widget.curve ?? Curves.easeInCubic,
+                backgroundGradient:
+                    t.backgroundGradient ?? widget.tabBackgroundGradient,
+                backgroundColor: t.backgroundColor ??
+                    widget.tabBackgroundColor ??
+                    Colors.transparent,
+                duration: widget.duration ?? const Duration(milliseconds: 500),
+                onPressed: () {
+                  if (!clickable) return;
+                  setState(() {
+                    selectedIndex = widget.tabs.indexOf(t);
+                    clickable = false;
+                  });
+                  widget.onTabChange(selectedIndex);
 
-                        Future.delayed(
-                            widget.duration ??
-                                const Duration(milliseconds: 500), () {
-                          setState(() {
-                            clickable = true;
-                          });
-                        });
-                      },
-                    ),)
-                .toList(),),);
+                  Future.delayed(
+                      widget.duration ?? const Duration(milliseconds: 500), () {
+                    setState(() {
+                      clickable = true;
+                    });
+                  });
+                },
+              ),
+            )
+            .toList(),
+      ),
+    );
   }
 }
 
@@ -237,31 +237,31 @@ class _GButtonState extends State<GButton> {
 }
 
 class Button extends StatefulWidget {
-  const Button(
-      {Key key,
-      this.icon,
-      this.iconSize,
-      this.leading,
-      this.iconActiveColor,
-      this.iconColor,
-      this.text,
-      this.gap = 0,
-      this.color,
-      this.rippleColor,
-      this.hoverColor,
-      this.onPressed,
-      this.duration,
-      this.curve,
-      this.padding = const EdgeInsets.all(25),
-      this.margin = const EdgeInsets.all(0),
-      this.active = false,
-      this.debug,
-      this.gradient,
-      this.borderRadius = const BorderRadius.all(Radius.circular(100.0)),
-      this.border,
-      this.activeBorder,
-      this.shadow,})
-      : super(key: key);
+  const Button({
+    Key key,
+    this.icon,
+    this.iconSize,
+    this.leading,
+    this.iconActiveColor,
+    this.iconColor,
+    this.text,
+    this.gap = 0,
+    this.color,
+    this.rippleColor,
+    this.hoverColor,
+    this.onPressed,
+    this.duration,
+    this.curve,
+    this.padding = const EdgeInsets.all(25),
+    this.margin = const EdgeInsets.all(0),
+    this.active = false,
+    this.debug,
+    this.gradient,
+    this.borderRadius = const BorderRadius.all(Radius.circular(100.0)),
+    this.border,
+    this.activeBorder,
+    this.shadow,
+  }) : super(key: key);
 
   final IconData icon;
   final double iconSize;
@@ -317,7 +317,8 @@ class _ButtonState extends State<Button> with TickerProviderStateMixin {
   Widget build(BuildContext context) {
     var curveValue = expandController
         .drive(
-            CurveTween(curve: _expanded ? widget.curve : widget.curve.flipped),)
+          CurveTween(curve: _expanded ? widget.curve : widget.curve.flipped),
+        )
         .value;
 
     _expanded = !widget.active;
@@ -370,9 +371,11 @@ class _ButtonState extends State<Button> with TickerProviderStateMixin {
             ),
             child: FittedBox(
               fit: BoxFit.fitHeight,
-              child: Stack(children: [
-                Align(alignment: Alignment.centerLeft, child: icon),
-              ],),
+              child: Stack(
+                children: [
+                  Align(alignment: Alignment.centerLeft, child: icon),
+                ],
+              ),
             ),
           ),
         ),

+ 24 - 11
lib/ui/ott_verification_page.dart

@@ -69,7 +69,10 @@ class _OTTVerificationPageState extends State<OTTVerificationPage> {
         onPressedFunction: () {
           if (widget.isChangeEmail) {
             UserService.instance.changeEmail(
-                context, widget.email, _verificationCodeController.text,);
+              context,
+              widget.email,
+              _verificationCodeController.text,
+            );
           } else {
             UserService.instance
                 .verifyEmail(context, _verificationCodeController.text);
@@ -89,8 +92,10 @@ class _OTTVerificationPageState extends State<OTTVerificationPage> {
           children: [
             Padding(
               padding: const EdgeInsets.fromLTRB(20, 30, 20, 15),
-              child: Text('Verify email',
-                  style: Theme.of(context).textTheme.headline4,),
+              child: Text(
+                'Verify email',
+                style: Theme.of(context).textTheme.headline4,
+              ),
             ),
             Padding(
               padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
@@ -111,9 +116,11 @@ class _OTTVerificationPageState extends State<OTTVerificationPage> {
                               children: [
                                 TextSpan(text: "We've sent a mail to "),
                                 TextSpan(
-                                    text: widget.email,
-                                    style: TextStyle(
-                                        color: Theme.of(context).buttonColor,),)
+                                  text: widget.email,
+                                  style: TextStyle(
+                                    color: Theme.of(context).buttonColor,
+                                  ),
+                                )
                               ],
                             ),
                           ),
@@ -144,8 +151,9 @@ class _OTTVerificationPageState extends State<OTTVerificationPage> {
                   hintText: 'Tap to enter code',
                   contentPadding: EdgeInsets.all(15),
                   border: UnderlineInputBorder(
-                      borderSide: BorderSide.none,
-                      borderRadius: BorderRadius.circular(6),),
+                    borderSide: BorderSide.none,
+                    borderRadius: BorderRadius.circular(6),
+                  ),
                 ),
                 controller: _verificationCodeController,
                 autofocus: false,
@@ -166,13 +174,18 @@ class _OTTVerificationPageState extends State<OTTVerificationPage> {
                 children: [
                   TextButton(
                     onPressed: () {
-                      UserService.instance.getOtt(context, widget.email,
-                          isCreateAccountScreen: widget.isCreateAccountScreen,);
+                      UserService.instance.getOtt(
+                        context,
+                        widget.email,
+                        isCreateAccountScreen: widget.isCreateAccountScreen,
+                      );
                     },
                     child: Text(
                       "Resend email",
                       style: Theme.of(context).textTheme.subtitle1.copyWith(
-                          fontSize: 14, decoration: TextDecoration.underline,),
+                            fontSize: 14,
+                            decoration: TextDecoration.underline,
+                          ),
                     ),
                   )
                 ],

+ 127 - 98
lib/ui/password_entry_page.dart

@@ -59,7 +59,9 @@ class _PasswordEntryPageState extends State<PasswordEntryPage> {
     _volatilePassword = Configuration.instance.getVolatilePassword();
     if (_volatilePassword != null) {
       Future.delayed(
-          Duration.zero, () => _showRecoveryCodeDialog(_volatilePassword),);
+        Duration.zero,
+        () => _showRecoveryCodeDialog(_volatilePassword),
+      );
     }
     _password1FocusNode.addListener(() {
       setState(() {
@@ -108,16 +110,17 @@ class _PasswordEntryPageState extends State<PasswordEntryPage> {
       ),
       body: _getBody(title),
       floatingActionButton: DynamicFAB(
-          isKeypadOpen: isKeypadOpen,
-          isFormValid: _passwordsMatch,
-          buttonText: title,
-          onPressedFunction: () {
-            if (widget.mode == PasswordEntryMode.set) {
-              _showRecoveryCodeDialog(_passwordController1.text);
-            } else {
-              _updatePassword();
-            }
-          },),
+        isKeypadOpen: isKeypadOpen,
+        isFormValid: _passwordsMatch,
+        buttonText: title,
+        onPressedFunction: () {
+          if (widget.mode == PasswordEntryMode.set) {
+            _showRecoveryCodeDialog(_passwordController1.text);
+          } else {
+            _updatePassword();
+          }
+        },
+      ),
       floatingActionButtonLocation: fabLocation(),
       floatingActionButtonAnimator: NoScalingAnimation(),
     );
@@ -146,8 +149,10 @@ class _PasswordEntryPageState extends State<PasswordEntryPage> {
                 Padding(
                   padding:
                       const EdgeInsets.symmetric(vertical: 30, horizontal: 20),
-                  child: Text(buttonTextAndHeading,
-                      style: Theme.of(context).textTheme.headline4,),
+                  child: Text(
+                    buttonTextAndHeading,
+                    style: Theme.of(context).textTheme.headline4,
+                  ),
                 ),
                 Padding(
                   padding: const EdgeInsets.symmetric(horizontal: 20),
@@ -166,22 +171,26 @@ class _PasswordEntryPageState extends State<PasswordEntryPage> {
                 Padding(
                   padding: const EdgeInsets.symmetric(horizontal: 20),
                   child: RichText(
-                      text: TextSpan(
-                          style: Theme.of(context)
-                              .textTheme
-                              .subtitle1
-                              .copyWith(fontSize: 14),
-                          children: [
+                    text: TextSpan(
+                      style: Theme.of(context)
+                          .textTheme
+                          .subtitle1
+                          .copyWith(fontSize: 14),
+                      children: [
                         TextSpan(
-                            text:
-                                "We don't store this password, so if you forget, ",),
+                          text:
+                              "We don't store this password, so if you forget, ",
+                        ),
                         TextSpan(
                           text: "we cannot decrypt your data",
                           style: Theme.of(context).textTheme.subtitle1.copyWith(
-                              fontSize: 14,
-                              decoration: TextDecoration.underline,),
+                                fontSize: 14,
+                                decoration: TextDecoration.underline,
+                              ),
                         ),
-                      ],),),
+                      ],
+                    ),
+                  ),
                 ),
                 Padding(padding: EdgeInsets.all(12)),
                 Visibility(
@@ -209,8 +218,9 @@ class _PasswordEntryPageState extends State<PasswordEntryPage> {
                       hintText: "Password",
                       contentPadding: EdgeInsets.all(20),
                       border: UnderlineInputBorder(
-                          borderSide: BorderSide.none,
-                          borderRadius: BorderRadius.circular(6),),
+                        borderSide: BorderSide.none,
+                        borderRadius: BorderRadius.circular(6),
+                      ),
                       suffixIcon: _password1InFocus
                           ? IconButton(
                               icon: Icon(
@@ -274,7 +284,9 @@ class _PasswordEntryPageState extends State<PasswordEntryPage> {
                           filled: true,
                           hintText: "Confirm password",
                           contentPadding: EdgeInsets.symmetric(
-                              horizontal: 20, vertical: 20,),
+                            horizontal: 20,
+                            vertical: 20,
+                          ),
                           suffixIcon: _password2InFocus
                               ? IconButton(
                                   icon: Icon(
@@ -301,8 +313,9 @@ class _PasswordEntryPageState extends State<PasswordEntryPage> {
                                     )
                                   : null,
                           border: UnderlineInputBorder(
-                              borderSide: BorderSide.none,
-                              borderRadius: BorderRadius.circular(6),),
+                            borderSide: BorderSide.none,
+                            borderRadius: BorderRadius.circular(6),
+                          ),
                         ),
                         focusNode: _password2FocusNode,
                         onChanged: (cnfPassword) {
@@ -321,66 +334,74 @@ class _PasswordEntryPageState extends State<PasswordEntryPage> {
                       visible:
                           ((_passwordInInputBox != '') && _password1InFocus),
                       child: Positioned(
-                          bottom: 24,
-                          child: Row(
-                            children: [
-                              SizedBox(
-                                width: MediaQuery.of(context).size.width,
-                                child: Padding(
-                                  padding: const EdgeInsets.symmetric(
-                                      horizontal: 20,),
-                                  child: Container(
-                                    decoration: BoxDecoration(
-                                      boxShadow: [
-                                        BoxShadow(
-                                          spreadRadius: 0.5,
-                                          color: Theme.of(context).hintColor,
-                                          offset: Offset(0, -0.325),
-                                        ),
-                                      ],
-                                      borderRadius: BorderRadius.only(
-                                        topLeft: Radius.zero,
-                                        topRight: Radius.zero,
-                                        bottomLeft: Radius.circular(5),
-                                        bottomRight: Radius.circular(5),
+                        bottom: 24,
+                        child: Row(
+                          children: [
+                            SizedBox(
+                              width: MediaQuery.of(context).size.width,
+                              child: Padding(
+                                padding: const EdgeInsets.symmetric(
+                                  horizontal: 20,
+                                ),
+                                child: Container(
+                                  decoration: BoxDecoration(
+                                    boxShadow: [
+                                      BoxShadow(
+                                        spreadRadius: 0.5,
+                                        color: Theme.of(context).hintColor,
+                                        offset: Offset(0, -0.325),
                                       ),
-                                      color: Theme.of(context)
-                                          .dialogTheme
-                                          .backgroundColor,
+                                    ],
+                                    borderRadius: BorderRadius.only(
+                                      topLeft: Radius.zero,
+                                      topRight: Radius.zero,
+                                      bottomLeft: Radius.circular(5),
+                                      bottomRight: Radius.circular(5),
                                     ),
-                                    width: double.infinity,
-                                    child: Column(
-                                        crossAxisAlignment:
-                                            CrossAxisAlignment.start,
-                                        children: [
-                                          Padding(
-                                            padding: const EdgeInsets.fromLTRB(
-                                                4.0, 4, 4.0, 4.0,),
-                                            child: Row(
-                                              children: [
-                                                Padding(
-                                                    padding:
-                                                        EdgeInsets.symmetric(
-                                                            horizontal: 10,
-                                                            vertical: 5,),
-                                                    child: Text(
-                                                      'Password Strength: $passwordStrengthText',
-                                                      style: TextStyle(
-                                                          color:
-                                                              passwordStrengthColor,),
-                                                    ),),
-                                              ],
+                                    color: Theme.of(context)
+                                        .dialogTheme
+                                        .backgroundColor,
+                                  ),
+                                  width: double.infinity,
+                                  child: Column(
+                                    crossAxisAlignment:
+                                        CrossAxisAlignment.start,
+                                    children: [
+                                      Padding(
+                                        padding: const EdgeInsets.fromLTRB(
+                                          4.0,
+                                          4,
+                                          4.0,
+                                          4.0,
+                                        ),
+                                        child: Row(
+                                          children: [
+                                            Padding(
+                                              padding: EdgeInsets.symmetric(
+                                                horizontal: 10,
+                                                vertical: 5,
+                                              ),
+                                              child: Text(
+                                                'Password Strength: $passwordStrengthText',
+                                                style: TextStyle(
+                                                  color: passwordStrengthColor,
+                                                ),
+                                              ),
                                             ),
-                                          ),
-                                        ],),
+                                          ],
+                                        ),
+                                      ),
+                                    ],
                                   ),
                                 ),
                               ),
-                              SizedBox(
-                                width: 20,
-                              ),
-                            ],
-                          ),),
+                            ),
+                            SizedBox(
+                              width: 20,
+                            ),
+                          ],
+                        ),
+                      ),
                     ),
                   ],
                   clipBehavior: Clip.none,
@@ -395,7 +416,9 @@ class _PasswordEntryPageState extends State<PasswordEntryPage> {
                       MaterialPageRoute(
                         builder: (BuildContext context) {
                           return WebPage(
-                              "How it works", "https://ente.io/architecture",);
+                            "How it works",
+                            "https://ente.io/architecture",
+                          );
                         },
                       ),
                     );
@@ -404,10 +427,12 @@ class _PasswordEntryPageState extends State<PasswordEntryPage> {
                     padding: EdgeInsets.symmetric(horizontal: 20),
                     child: RichText(
                       text: TextSpan(
-                          text: "How it works",
-                          style: Theme.of(context).textTheme.subtitle1.copyWith(
+                        text: "How it works",
+                        style: Theme.of(context).textTheme.subtitle1.copyWith(
                               fontSize: 14,
-                              decoration: TextDecoration.underline,),),
+                              decoration: TextDecoration.underline,
+                            ),
+                      ),
                     ),
                   ),
                 ),
@@ -473,21 +498,25 @@ class _PasswordEntryPageState extends State<PasswordEntryPage> {
       }
 
       routeToPage(
-          context,
-          RecoveryKeyPage(
-            result.privateKeyAttributes.recoveryKey,
-            "Continue",
-            showAppBar: false,
-            isDismissible: false,
-            onDone: onDone,
-            showProgressBar: true,
-          ),);
+        context,
+        RecoveryKeyPage(
+          result.privateKeyAttributes.recoveryKey,
+          "Continue",
+          showAppBar: false,
+          isDismissible: false,
+          onDone: onDone,
+          showProgressBar: true,
+        ),
+      );
     } catch (e) {
       _logger.severe(e);
       await dialog.hide();
       if (e is UnsupportedError) {
-        showErrorDialog(context, "Insecure device",
-            "Sorry, we could not generate secure keys on this device.\n\nplease sign up from a different device.",);
+        showErrorDialog(
+          context,
+          "Insecure device",
+          "Sorry, we could not generate secure keys on this device.\n\nplease sign up from a different device.",
+        );
       } else {
         showGenericErrorDialog(context);
       }

+ 24 - 18
lib/ui/password_reentry_page.dart

@@ -63,8 +63,9 @@ class _PasswordReentryPageState extends State<PasswordReentryPage> {
           await dialog.show();
           try {
             await Configuration.instance.decryptAndSaveSecrets(
-                _passwordController.text,
-                Configuration.instance.getKeyAttributes(),);
+              _passwordController.text,
+              Configuration.instance.getKeyAttributes(),
+            );
           } catch (e) {
             Logger("PRP").warning(e);
             await dialog.hide();
@@ -90,8 +91,10 @@ class _PasswordReentryPageState extends State<PasswordReentryPage> {
               Padding(
                 padding:
                     const EdgeInsets.symmetric(vertical: 30, horizontal: 20),
-                child: Text('Welcome back!',
-                    style: Theme.of(context).textTheme.headline4,),
+                child: Text(
+                  'Welcome back!',
+                  style: Theme.of(context).textTheme.headline4,
+                ),
               ),
               Padding(
                 padding: const EdgeInsets.fromLTRB(20, 24, 20, 0),
@@ -102,8 +105,9 @@ class _PasswordReentryPageState extends State<PasswordReentryPage> {
                     filled: true,
                     contentPadding: EdgeInsets.all(20),
                     border: UnderlineInputBorder(
-                        borderSide: BorderSide.none,
-                        borderRadius: BorderRadius.circular(6),),
+                      borderSide: BorderSide.none,
+                      borderRadius: BorderRadius.circular(6),
+                    ),
                     suffixIcon: _passwordInFocus
                         ? IconButton(
                             icon: Icon(
@@ -159,13 +163,14 @@ class _PasswordReentryPageState extends State<PasswordReentryPage> {
                       },
                       child: Container(
                         child: Center(
-                          child: Text("Forgot password",
-                              style: Theme.of(context)
-                                  .textTheme
-                                  .subtitle1
-                                  .copyWith(
+                          child: Text(
+                            "Forgot password",
+                            style:
+                                Theme.of(context).textTheme.subtitle1.copyWith(
                                       fontSize: 14,
-                                      decoration: TextDecoration.underline,),),
+                                      decoration: TextDecoration.underline,
+                                    ),
+                          ),
                         ),
                       ),
                     ),
@@ -182,13 +187,14 @@ class _PasswordReentryPageState extends State<PasswordReentryPage> {
                       },
                       child: Container(
                         child: Center(
-                          child: Text("Change email",
-                              style: Theme.of(context)
-                                  .textTheme
-                                  .subtitle1
-                                  .copyWith(
+                          child: Text(
+                            "Change email",
+                            style:
+                                Theme.of(context).textTheme.subtitle1.copyWith(
                                       fontSize: 14,
-                                      decoration: TextDecoration.underline,),),
+                                      decoration: TextDecoration.underline,
+                                    ),
+                          ),
                         ),
                       ),
                     ),

+ 93 - 86
lib/ui/payment/payment_web_page.dart

@@ -52,69 +52,69 @@ class _PaymentWebPageState extends State<PaymentWebPage> {
       return loadWidget;
     }
     return WillPopScope(
-        onWillPop: () async => _buildPageExitWidget(context),
-        child: Scaffold(
-          appBar: AppBar(
-            title: const Text('Subscription'),
-          ),
-          body: Column(
-            children: <Widget>[
-              (progress != 1.0)
-                  ? LinearProgressIndicator(value: progress)
-                  : Container(),
-              Expanded(
-                child: InAppWebView(
-                  initialUrlRequest: URLRequest(url: initPaymentUrl),
-                  onProgressChanged:
-                      (InAppWebViewController controller, int progress) {
-                    setState(() {
-                      this.progress = progress / 100;
-                    });
-                  },
-                  initialOptions: InAppWebViewGroupOptions(
-                    crossPlatform: InAppWebViewOptions(
-                      useShouldOverrideUrlLoading: true,
-                    ),
+      onWillPop: () async => _buildPageExitWidget(context),
+      child: Scaffold(
+        appBar: AppBar(
+          title: const Text('Subscription'),
+        ),
+        body: Column(
+          children: <Widget>[
+            (progress != 1.0)
+                ? LinearProgressIndicator(value: progress)
+                : Container(),
+            Expanded(
+              child: InAppWebView(
+                initialUrlRequest: URLRequest(url: initPaymentUrl),
+                onProgressChanged:
+                    (InAppWebViewController controller, int progress) {
+                  setState(() {
+                    this.progress = progress / 100;
+                  });
+                },
+                initialOptions: InAppWebViewGroupOptions(
+                  crossPlatform: InAppWebViewOptions(
+                    useShouldOverrideUrlLoading: true,
                   ),
-                  shouldOverrideUrlLoading:
-                      (controller, navigationAction) async {
-                    var loadingUri = navigationAction.request.url;
-                    _logger.info("Loading url $loadingUri");
-                    // handle the payment response
-                    if (_isPaymentActionComplete(loadingUri)) {
-                      await _handlePaymentResponse(loadingUri);
-                      return NavigationActionPolicy.CANCEL;
-                    }
-                    return NavigationActionPolicy.ALLOW;
-                  },
-                  onConsoleMessage: (controller, consoleMessage) {
-                    _logger.info(consoleMessage);
-                  },
-                  onLoadStart: (controller, navigationAction) async {
-                    if (!_dialog.isShowing()) {
-                      await _dialog.show();
-                    }
-                  },
-                  onLoadError: (controller, navigationAction, code, msg) async {
-                    if (_dialog.isShowing()) {
-                      await _dialog.hide();
-                    }
-                  },
-                  onLoadHttpError:
-                      (controller, navigationAction, code, msg) async {
-                    _logger.info("onHttpError with $code and msg = $msg");
-                  },
-                  onLoadStop: (controller, navigationAction) async {
-                    _logger.info("loadStart" + navigationAction.toString());
-                    if (_dialog.isShowing()) {
-                      await _dialog.hide();
-                    }
-                  },
                 ),
+                shouldOverrideUrlLoading: (controller, navigationAction) async {
+                  var loadingUri = navigationAction.request.url;
+                  _logger.info("Loading url $loadingUri");
+                  // handle the payment response
+                  if (_isPaymentActionComplete(loadingUri)) {
+                    await _handlePaymentResponse(loadingUri);
+                    return NavigationActionPolicy.CANCEL;
+                  }
+                  return NavigationActionPolicy.ALLOW;
+                },
+                onConsoleMessage: (controller, consoleMessage) {
+                  _logger.info(consoleMessage);
+                },
+                onLoadStart: (controller, navigationAction) async {
+                  if (!_dialog.isShowing()) {
+                    await _dialog.show();
+                  }
+                },
+                onLoadError: (controller, navigationAction, code, msg) async {
+                  if (_dialog.isShowing()) {
+                    await _dialog.hide();
+                  }
+                },
+                onLoadHttpError:
+                    (controller, navigationAction, code, msg) async {
+                  _logger.info("onHttpError with $code and msg = $msg");
+                },
+                onLoadStop: (controller, navigationAction) async {
+                  _logger.info("loadStart" + navigationAction.toString());
+                  if (_dialog.isShowing()) {
+                    await _dialog.hide();
+                  }
+                },
               ),
-            ].where((Object o) => o != null).toList(),
-          ),
-        ),);
+            ),
+          ].where((Object o) => o != null).toList(),
+        ),
+      ),
+    );
   }
 
   @override
@@ -146,10 +146,12 @@ class _PaymentWebPageState extends State<PaymentWebPage> {
         title: Text('Are you sure you want to exit?'),
         actions: <Widget>[
           TextButton(
-            child: Text('Yes',
-                style: TextStyle(
-                  color: Colors.redAccent,
-                ),),
+            child: Text(
+              'Yes',
+              style: TextStyle(
+                color: Colors.redAccent,
+              ),
+            ),
             onPressed: () => Navigator.of(context).pop(true),
           ),
           TextButton(
@@ -188,19 +190,21 @@ class _PaymentWebPageState extends State<PaymentWebPage> {
 
   Future<void> _handlePaymentFailure(String reason) async {
     await showDialog(
-        context: context,
-        barrierDismissible: false,
-        builder: (context) => AlertDialog(
-                title: Text('Payment failed'),
-                content:
-                    Text("Unfortunately your payment failed due to $reason"),
-                actions: <Widget>[
-                  TextButton(
-                      child: Text('Ok'),
-                      onPressed: () {
-                        Navigator.of(context).pop('dialog');
-                      },),
-                ],),);
+      context: context,
+      barrierDismissible: false,
+      builder: (context) => AlertDialog(
+        title: Text('Payment failed'),
+        content: Text("Unfortunately your payment failed due to $reason"),
+        actions: <Widget>[
+          TextButton(
+            child: Text('Ok'),
+            onPressed: () {
+              Navigator.of(context).pop('dialog');
+            },
+          ),
+        ],
+      ),
+    );
     Navigator.of(context).pop(true);
   }
 
@@ -210,8 +214,10 @@ class _PaymentWebPageState extends State<PaymentWebPage> {
     await _dialog.show();
     try {
       var response = await billingService.verifySubscription(
-          widget.planId, checkoutSessionID,
-          paymentProvider: kStripe,);
+        widget.planId,
+        checkoutSessionID,
+        paymentProvider: kStripe,
+      );
       await _dialog.hide();
       if (response != null) {
         var content = widget.actionType == 'buy'
@@ -241,13 +247,14 @@ class _PaymentWebPageState extends State<PaymentWebPage> {
         content: Text(content),
         actions: <Widget>[
           TextButton(
-              child: Text(
-                'Ok',
-                style: TextStyle(color: Theme.of(context).buttonColor),
-              ),
-              onPressed: () {
-                Navigator.of(context).pop('dialog');
-              },),
+            child: Text(
+              'Ok',
+              style: TextStyle(color: Theme.of(context).buttonColor),
+            ),
+            onPressed: () {
+              Navigator.of(context).pop('dialog');
+            },
+          ),
         ],
       ),
     ).then((val) => Navigator.pop(context, true));

+ 102 - 69
lib/ui/payment/stripe_subscription_page.dart

@@ -117,31 +117,36 @@ class _StripeSubscriptionPageState extends State<StripeSubscriptionPage> {
     final appBar = PreferredSize(
       preferredSize: Size(double.infinity, 60),
       child: Container(
-          decoration: BoxDecoration(boxShadow: [
+        decoration: BoxDecoration(
+          boxShadow: [
             BoxShadow(
-                color: Theme.of(context).backgroundColor,
-                blurRadius: 16,
-                offset: Offset(0, 8),)
-          ],),
-          child: widget.isOnboarding
-              ? AppBar(
-                  elevation: 0,
-                  title: Hero(
-                      tag: "subscription",
-                      child: StepProgressIndicator(
-                        totalSteps: 4,
-                        currentStep: 4,
-                        selectedColor: Theme.of(context).buttonColor,
-                        roundedEdges: Radius.circular(10),
-                        unselectedColor: Theme.of(context)
-                            .colorScheme
-                            .stepProgressUnselectedColor,
-                      ),),
-                )
-              : AppBar(
-                  elevation: 0,
-                  title: Text("Subscription"),
-                ),),
+              color: Theme.of(context).backgroundColor,
+              blurRadius: 16,
+              offset: Offset(0, 8),
+            )
+          ],
+        ),
+        child: widget.isOnboarding
+            ? AppBar(
+                elevation: 0,
+                title: Hero(
+                  tag: "subscription",
+                  child: StepProgressIndicator(
+                    totalSteps: 4,
+                    currentStep: 4,
+                    selectedColor: Theme.of(context).buttonColor,
+                    roundedEdges: Radius.circular(10),
+                    unselectedColor: Theme.of(context)
+                        .colorScheme
+                        .stepProgressUnselectedColor,
+                  ),
+                ),
+              )
+            : AppBar(
+                elevation: 0,
+                title: Text("Subscription"),
+              ),
+      ),
     );
     return Scaffold(
       appBar: appBar,
@@ -176,15 +181,18 @@ class _StripeSubscriptionPageState extends State<StripeSubscriptionPage> {
   Widget _buildPlans() {
     final widgets = <Widget>[];
 
-    widgets.add(SubscriptionHeaderWidget(
-      isOnboarding: widget.isOnboarding,
-      currentUsage: _userDetails.getFamilyOrPersonalUsage(),
-    ),);
+    widgets.add(
+      SubscriptionHeaderWidget(
+        isOnboarding: widget.isOnboarding,
+        currentUsage: _userDetails.getFamilyOrPersonalUsage(),
+      ),
+    );
 
     widgets.addAll([
       Column(
-          mainAxisAlignment: MainAxisAlignment.center,
-          children: _getStripePlanWidgets(),),
+        mainAxisAlignment: MainAxisAlignment.center,
+        children: _getStripePlanWidgets(),
+      ),
       Padding(padding: EdgeInsets.all(4)),
     ]);
 
@@ -218,16 +226,19 @@ class _StripeSubscriptionPageState extends State<StripeSubscriptionPage> {
                   break;
                 case kPlayStore:
                   launch(
-                      "https://play.google.com/store/account/subscriptions?sku=" +
-                          _currentSubscription.productID +
-                          "&package=io.ente.photos",);
+                    "https://play.google.com/store/account/subscriptions?sku=" +
+                        _currentSubscription.productID +
+                        "&package=io.ente.photos",
+                  );
                   break;
                 case kAppStore:
                   launch("https://apps.apple.com/account/billing");
                   break;
                 default:
                   _logger.severe(
-                      "unexpected payment provider ", _currentSubscription,);
+                    "unexpected payment provider ",
+                    _currentSubscription,
+                  );
               }
             },
             child: Container(
@@ -236,17 +247,18 @@ class _StripeSubscriptionPageState extends State<StripeSubscriptionPage> {
                 children: [
                   RichText(
                     text: TextSpan(
-                        text: !_isStripeSubscriber
-                            ? "visit ${_currentSubscription.paymentProvider} to manage your subscription"
-                            : "Payment details",
-                        style: TextStyle(
-                          color: Theme.of(context).colorScheme.onSurface,
-                          fontFamily: 'Inter-Medium',
-                          fontSize: 14,
-                          decoration: _isStripeSubscriber
-                              ? TextDecoration.underline
-                              : TextDecoration.none,
-                        ),),
+                      text: !_isStripeSubscriber
+                          ? "visit ${_currentSubscription.paymentProvider} to manage your subscription"
+                          : "Payment details",
+                      style: TextStyle(
+                        color: Theme.of(context).colorScheme.onSurface,
+                        fontFamily: 'Inter-Medium',
+                        fontSize: 14,
+                        decoration: _isStripeSubscriber
+                            ? TextDecoration.underline
+                            : TextDecoration.none,
+                      ),
+                    ),
                     textAlign: TextAlign.center,
                   ),
                 ],
@@ -316,21 +328,26 @@ class _StripeSubscriptionPageState extends State<StripeSubscriptionPage> {
   Future<void> _launchFamilyPortal() async {
     if (_userDetails.subscription.productID == kFreeProductID) {
       await showErrorDialog(
-          context,
-          "Now you can share your storage plan with your family members!",
-          "Customers on paid plans can add up to 5 family members without paying extra. Each member gets their own private space.",);
+        context,
+        "Now you can share your storage plan with your family members!",
+        "Customers on paid plans can add up to 5 family members without paying extra. Each member gets their own private space.",
+      );
       return;
     }
     await _dialog.show();
     try {
       final String jwtToken = await _userService.getFamiliesToken();
       final bool familyExist = _userDetails.isPartOfFamily();
-      Navigator.of(context).push(MaterialPageRoute(
-        builder: (BuildContext context) {
-          return WebPage("Family",
-              '$kFamilyPlanManagementUrl?token=$jwtToken&isFamilyCreated=$familyExist',);
-        },
-      ),).then((value) => onWebPaymentGoBack);
+      Navigator.of(context).push(
+        MaterialPageRoute(
+          builder: (BuildContext context) {
+            return WebPage(
+              "Family",
+              '$kFamilyPlanManagementUrl?token=$jwtToken&isFamilyCreated=$familyExist',
+            );
+          },
+        ),
+      ).then((value) => onWebPaymentGoBack);
     } catch (e) {
       await _dialog.hide();
       showGenericErrorDialog(context);
@@ -357,15 +374,22 @@ class _StripeSubscriptionPageState extends State<StripeSubscriptionPage> {
         bool confirmAction = false;
         if (isRenewCancelled) {
           var choice = await showChoiceDialog(
-              context, title, "are you sure you want to renew?",
-              firstAction: "no", secondAction: "yes",);
+            context,
+            title,
+            "are you sure you want to renew?",
+            firstAction: "no",
+            secondAction: "yes",
+          );
           confirmAction = choice == DialogUserChoice.secondChoice;
         } else {
           var choice = await showChoiceDialog(
-              context, title, 'are you sure you want to cancel?',
-              firstAction: 'yes, cancel',
-              secondAction: 'no',
-              actionType: ActionType.critical,);
+            context,
+            title,
+            'are you sure you want to cancel?',
+            firstAction: 'yes, cancel',
+            secondAction: 'no',
+            actionType: ActionType.critical,
+          );
           confirmAction = choice == DialogUserChoice.firstChoice;
         }
         if (confirmAction) {
@@ -384,7 +408,9 @@ class _StripeSubscriptionPageState extends State<StripeSubscriptionPage> {
       await _fetchSub();
     } catch (e) {
       showToast(
-          context, isRenewCancelled ? 'failed to renew' : 'failed to cancel',);
+        context,
+        isRenewCancelled ? 'failed to renew' : 'failed to cancel',
+      );
     }
     await _dialog.hide();
   }
@@ -414,24 +440,31 @@ class _StripeSubscriptionPageState extends State<StripeSubscriptionPage> {
               if (!_isStripeSubscriber &&
                   _hasActiveSubscription &&
                   _currentSubscription.productID != kFreeProductID) {
-                showErrorDialog(context, "Sorry",
-                    "please cancel your existing subscription from ${_currentSubscription.paymentProvider} first",);
+                showErrorDialog(
+                  context,
+                  "Sorry",
+                  "please cancel your existing subscription from ${_currentSubscription.paymentProvider} first",
+                );
                 return;
               }
               if (_userDetails.getFamilyOrPersonalUsage() > plan.storage) {
                 showErrorDialog(
-                    context, "Sorry", "you cannot downgrade to this plan",);
+                  context,
+                  "Sorry",
+                  "you cannot downgrade to this plan",
+                );
                 return;
               }
               String stripPurChaseAction = 'buy';
               if (_isStripeSubscriber && _hasActiveSubscription) {
                 // confirm if user wants to change plan or not
                 var result = await showChoiceDialog(
-                    context,
-                    "Confirm plan change",
-                    "Are you sure you want to change your plan?",
-                    firstAction: "No",
-                    secondAction: 'Yes',);
+                  context,
+                  "Confirm plan change",
+                  "Are you sure you want to change your plan?",
+                  firstAction: "No",
+                  secondAction: 'Yes',
+                );
                 if (result != DialogUserChoice.secondChoice) {
                   return;
                 }

+ 10 - 6
lib/ui/payment/subscription_common_widgets.dart

@@ -10,9 +10,11 @@ class SubscriptionHeaderWidget extends StatefulWidget {
   final bool isOnboarding;
   final int currentUsage;
 
-  const SubscriptionHeaderWidget(
-      {Key key, this.isOnboarding, this.currentUsage,})
-      : super(key: key);
+  const SubscriptionHeaderWidget({
+    Key key,
+    this.isOnboarding,
+    this.currentUsage,
+  }) : super(key: key);
 
   @override
   State<StatefulWidget> createState() {
@@ -57,8 +59,9 @@ class _SubscriptionHeaderWidgetState extends State<SubscriptionHeaderWidget> {
             text: TextSpan(
               children: [
                 TextSpan(
-                    text: "Current usage is ",
-                    style: Theme.of(context).textTheme.subtitle1,),
+                  text: "Current usage is ",
+                  style: Theme.of(context).textTheme.subtitle1,
+                ),
                 TextSpan(
                   text: formatBytes(widget.currentUsage),
                   style: Theme.of(context)
@@ -86,7 +89,8 @@ class ValidityWidget extends StatelessWidget {
       return Container();
     }
     var endDate = getDateAndMonthAndYear(
-        DateTime.fromMicrosecondsSinceEpoch(currentSubscription.expiryTime),);
+      DateTime.fromMicrosecondsSinceEpoch(currentSubscription.expiryTime),
+    );
     var message = "Renews on $endDate";
     if (currentSubscription.productID == kFreeProductID) {
       message = "Free plan valid till $endDate";

+ 46 - 28
lib/ui/payment/subscription_page.dart

@@ -99,11 +99,12 @@ class _SubscriptionPageState extends State<SubscriptionPage> {
             _logger.warning("Could not complete payment ", e);
             await _dialog.hide();
             showErrorDialog(
-                context,
-                "payment failed",
-                "please talk to " +
-                    (Platform.isAndroid ? "PlayStore" : "AppStore") +
-                    " support if you were charged",);
+              context,
+              "payment failed",
+              "please talk to " +
+                  (Platform.isAndroid ? "PlayStore" : "AppStore") +
+                  " support if you were charged",
+            );
             return;
           }
         } else if (Platform.isIOS && purchase.pendingCompletePurchase) {
@@ -175,10 +176,12 @@ class _SubscriptionPageState extends State<SubscriptionPage> {
 
   Widget _buildPlans() {
     final widgets = <Widget>[];
-    widgets.add(SubscriptionHeaderWidget(
-      isOnboarding: widget.isOnboarding,
-      currentUsage: _userDetails.getFamilyOrPersonalUsage(),
-    ),);
+    widgets.add(
+      SubscriptionHeaderWidget(
+        isOnboarding: widget.isOnboarding,
+        currentUsage: _userDetails.getFamilyOrPersonalUsage(),
+      ),
+    );
 
     widgets.addAll([
       Column(
@@ -213,9 +216,10 @@ class _SubscriptionPageState extends State<SubscriptionPage> {
               }
               if (Platform.isAndroid) {
                 launch(
-                    "https://play.google.com/store/account/subscriptions?sku=" +
-                        _currentSubscription.productID +
-                        "&package=io.ente.photos",);
+                  "https://play.google.com/store/account/subscriptions?sku=" +
+                      _currentSubscription.productID +
+                      "&package=io.ente.photos",
+                );
               } else {
                 launch("https://apps.apple.com/account/billing");
               }
@@ -307,8 +311,11 @@ class _SubscriptionPageState extends State<SubscriptionPage> {
               if (isActive) {
                 return;
               }
-              showErrorDialog(context, "Sorry",
-                  "Please visit web.ente.io to manage your subscription",);
+              showErrorDialog(
+                context,
+                "Sorry",
+                "Please visit web.ente.io to manage your subscription",
+              );
             },
             child: SubscriptionPlanWidget(
               storage: plan.storage,
@@ -357,7 +364,10 @@ class _SubscriptionPageState extends State<SubscriptionPage> {
               }
               if (_userDetails.getFamilyOrPersonalUsage() > plan.storage) {
                 showErrorDialog(
-                    context, "Sorry", "you cannot downgrade to this plan",);
+                  context,
+                  "Sorry",
+                  "you cannot downgrade to this plan",
+                );
                 return;
               }
               await _dialog.show();
@@ -365,8 +375,9 @@ class _SubscriptionPageState extends State<SubscriptionPage> {
                   await InAppPurchaseConnection.instance
                       .queryProductDetails({productID});
               if (response.notFoundIDs.isNotEmpty) {
-                _logger.severe("Could not find products: " +
-                    response.notFoundIDs.toString(),);
+                _logger.severe(
+                  "Could not find products: " + response.notFoundIDs.toString(),
+                );
                 await _dialog.hide();
                 showGenericErrorDialog(context);
                 return;
@@ -380,8 +391,10 @@ class _SubscriptionPageState extends State<SubscriptionPage> {
                     await InAppPurchaseConnection.instance
                         .queryProductDetails({_currentSubscription.productID});
                 if (existingProductDetailsResponse.notFoundIDs.isNotEmpty) {
-                  _logger.severe("Could not find existing products: " +
-                      response.notFoundIDs.toString(),);
+                  _logger.severe(
+                    "Could not find existing products: " +
+                        response.notFoundIDs.toString(),
+                  );
                   await _dialog.hide();
                   showGenericErrorDialog(context);
                   return;
@@ -451,21 +464,26 @@ class _SubscriptionPageState extends State<SubscriptionPage> {
   Future<void> _launchFamilyPortal() async {
     if (_userDetails.subscription.productID == kFreeProductID) {
       await showErrorDialog(
-          context,
-          "Now you can share your storage plan with your family members!",
-          "Customers on paid plans can add up to 5 family members without paying extra. Each member gets their own private space.",);
+        context,
+        "Now you can share your storage plan with your family members!",
+        "Customers on paid plans can add up to 5 family members without paying extra. Each member gets their own private space.",
+      );
       return;
     }
     await _dialog.show();
     try {
       final String jwtToken = await _userService.getFamiliesToken();
       final bool familyExist = _userDetails.isPartOfFamily();
-      Navigator.of(context).push(MaterialPageRoute(
-        builder: (BuildContext context) {
-          return WebPage("Family",
-              '$kFamilyPlanManagementUrl?token=$jwtToken&isFamilyCreated=$familyExist',);
-        },
-      ),);
+      Navigator.of(context).push(
+        MaterialPageRoute(
+          builder: (BuildContext context) {
+            return WebPage(
+              "Family",
+              '$kFamilyPlanManagementUrl?token=$jwtToken&isFamilyCreated=$familyExist',
+            );
+          },
+        ),
+      );
     } catch (e) {
       await _dialog.hide();
       showGenericErrorDialog(context);

+ 7 - 3
lib/ui/payment/subscription_plan_widget.dart

@@ -58,9 +58,13 @@ class SubscriptionPlanWidget extends StatelessWidget {
                       .headline6
                       .copyWith(color: textColor),
                 ),
-                Text(_displayPrice(),
-                    style: Theme.of(context).textTheme.headline6.copyWith(
-                        color: textColor, fontWeight: FontWeight.normal,),),
+                Text(
+                  _displayPrice(),
+                  style: Theme.of(context).textTheme.headline6.copyWith(
+                        color: textColor,
+                        fontWeight: FontWeight.normal,
+                      ),
+                ),
               ],
             ),
           ],

+ 41 - 31
lib/ui/progress_dialog.dart

@@ -21,9 +21,15 @@ bool _barrierDismissible = true, _showLogs = false;
 Color _barrierColor;
 
 TextStyle _progressTextStyle = TextStyle(
-        color: Colors.black, fontSize: 12.0, fontWeight: FontWeight.w400,),
+      color: Colors.black,
+      fontSize: 12.0,
+      fontWeight: FontWeight.w400,
+    ),
     _messageStyle = TextStyle(
-        color: Colors.black, fontSize: 18.0, fontWeight: FontWeight.w600,);
+      color: Colors.black,
+      fontSize: 18.0,
+      fontWeight: FontWeight.w600,
+    );
 
 double _dialogElevation = 8.0, _borderRadius = 8.0;
 Color _backgroundColor = Colors.white;
@@ -56,21 +62,22 @@ class ProgressDialog {
     _barrierColor = barrierColor ?? barrierColor;
   }
 
-  void style(
-      {Widget child,
-      double progress,
-      double maxProgress,
-      String message,
-      Widget progressWidget,
-      Color backgroundColor,
-      TextStyle progressTextStyle,
-      TextStyle messageTextStyle,
-      double elevation,
-      TextAlign textAlign,
-      double borderRadius,
-      Curve insetAnimCurve,
-      EdgeInsets padding,
-      Alignment progressWidgetAlignment,}) {
+  void style({
+    Widget child,
+    double progress,
+    double maxProgress,
+    String message,
+    Widget progressWidget,
+    Color backgroundColor,
+    TextStyle progressTextStyle,
+    TextStyle messageTextStyle,
+    double elevation,
+    TextAlign textAlign,
+    double borderRadius,
+    Curve insetAnimCurve,
+    EdgeInsets padding,
+    Alignment progressWidgetAlignment,
+  }) {
     if (_isShowing) return;
     if (_progressDialogType == ProgressDialogType.Download) {
       _progress = progress ?? _progress;
@@ -92,13 +99,14 @@ class ProgressDialog {
         progressWidgetAlignment ?? _progressWidgetAlignment;
   }
 
-  void update(
-      {double progress,
-      double maxProgress,
-      String message,
-      Widget progressWidget,
-      TextStyle progressTextStyle,
-      TextStyle messageTextStyle,}) {
+  void update({
+    double progress,
+    double maxProgress,
+    String message,
+    Widget progressWidget,
+    TextStyle progressTextStyle,
+    TextStyle messageTextStyle,
+  }) {
     if (_progressDialogType == ProgressDialogType.Download) {
       _progress = progress ?? _progress;
     }
@@ -152,8 +160,9 @@ class ProgressDialog {
                 insetAnimationDuration: Duration(milliseconds: 100),
                 elevation: _dialogElevation,
                 shape: RoundedRectangleBorder(
-                    borderRadius:
-                        BorderRadius.all(Radius.circular(_borderRadius)),),
+                  borderRadius:
+                      BorderRadius.all(Radius.circular(_borderRadius)),
+                ),
                 child: _dialog,
               ),
             );
@@ -232,11 +241,12 @@ class _BodyState extends State<_Body> {
                   Row(
                     children: <Widget>[
                       Expanded(
-                          child: Text(
-                        _dialogMessage,
-                        style: _messageStyle,
-                        textDirection: _direction,
-                      ),),
+                        child: Text(
+                          _dialogMessage,
+                          style: _messageStyle,
+                          textDirection: _direction,
+                        ),
+                      ),
                     ],
                   ),
                   SizedBox(height: 4.0),

+ 73 - 57
lib/ui/recovery_key_page.dart

@@ -22,16 +22,18 @@ class RecoveryKeyPage extends StatefulWidget {
   final String subText;
   final bool showProgressBar;
 
-  const RecoveryKeyPage(this.recoveryKey, this.doneText,
-      {Key key,
-      this.showAppBar,
-      this.onDone,
-      this.isDismissible,
-      this.title,
-      this.text,
-      this.subText,
-      this.showProgressBar = false,})
-      : super(key: key);
+  const RecoveryKeyPage(
+    this.recoveryKey,
+    this.doneText, {
+    Key key,
+    this.showAppBar,
+    this.onDone,
+    this.isDismissible,
+    this.title,
+    this.text,
+    this.subText,
+    this.showProgressBar = false,
+  }) : super(key: key);
 
   @override
   _RecoveryKeyPageState createState() => _RecoveryKeyPageState();
@@ -40,14 +42,16 @@ class RecoveryKeyPage extends StatefulWidget {
 class _RecoveryKeyPageState extends State<RecoveryKeyPage> {
   bool _hasTriedToSave = false;
   final _recoveryKeyFile = io.File(
-      Configuration.instance.getTempDirectory() + "ente-recovery-key.txt",);
+    Configuration.instance.getTempDirectory() + "ente-recovery-key.txt",
+  );
 
   @override
   Widget build(BuildContext context) {
     final String recoveryKey = bip39.entropyToMnemonic(widget.recoveryKey);
     if (recoveryKey.split(' ').length != kMnemonicKeyWordCount) {
       throw AssertionError(
-          'recovery code should have $kMnemonicKeyWordCount words',);
+        'recovery code should have $kMnemonicKeyWordCount words',
+      );
     }
 
     return Scaffold(
@@ -74,22 +78,25 @@ class _RecoveryKeyPageState extends State<RecoveryKeyPage> {
               : null,
       body: Padding(
         padding: EdgeInsets.fromLTRB(
-            20,
-            widget.showAppBar
-                ? 40
-                : widget.showProgressBar
-                    ? 32
-                    : 120,
-            20,
-            20,),
+          20,
+          widget.showAppBar
+              ? 40
+              : widget.showProgressBar
+                  ? 32
+                  : 120,
+          20,
+          20,
+        ),
         child: Column(
           crossAxisAlignment: CrossAxisAlignment.stretch,
           mainAxisSize: MainAxisSize.max,
           children: [
             widget.showAppBar
                 ? const SizedBox.shrink()
-                : Text(widget.title ?? "Recovery key",
-                    style: Theme.of(context).textTheme.headline4,),
+                : Text(
+                    widget.title ?? "Recovery key",
+                    style: Theme.of(context).textTheme.headline4,
+                  ),
             Padding(padding: EdgeInsets.all(widget.showAppBar ? 0 : 12)),
             Text(
               widget.text ??
@@ -116,7 +123,8 @@ class _RecoveryKeyPageState extends State<RecoveryKeyPage> {
                     GestureDetector(
                       onTap: () async {
                         await Clipboard.setData(
-                            ClipboardData(text: recoveryKey),);
+                          ClipboardData(text: recoveryKey),
+                        );
                         showToast(context, "Recovery key copied to clipboard");
                         setState(() {
                           _hasTriedToSave = true;
@@ -150,12 +158,13 @@ class _RecoveryKeyPageState extends State<RecoveryKeyPage> {
               height: 80,
               width: double.infinity,
               child: Padding(
-                  child: Text(
-                    widget.subText ??
-                        "We don’t store this key, please save this in a safe place.",
-                    style: Theme.of(context).textTheme.bodyText1,
-                  ),
-                  padding: EdgeInsets.symmetric(vertical: 20),),
+                child: Text(
+                  widget.subText ??
+                      "We don’t store this key, please save this in a safe place.",
+                  style: Theme.of(context).textTheme.bodyText1,
+                ),
+                padding: EdgeInsets.symmetric(vertical: 20),
+              ),
             ),
             Expanded(
               child: Container(
@@ -163,9 +172,10 @@ class _RecoveryKeyPageState extends State<RecoveryKeyPage> {
                 width: double.infinity,
                 padding: EdgeInsets.fromLTRB(10, 10, 10, 24),
                 child: Column(
-                    mainAxisAlignment: MainAxisAlignment.end,
-                    crossAxisAlignment: CrossAxisAlignment.stretch,
-                    children: _saveOptions(context, recoveryKey),),
+                  mainAxisAlignment: MainAxisAlignment.end,
+                  crossAxisAlignment: CrossAxisAlignment.stretch,
+                  children: _saveOptions(context, recoveryKey),
+                ),
               ),
             )
           ],
@@ -177,37 +187,43 @@ class _RecoveryKeyPageState extends State<RecoveryKeyPage> {
   List<Widget> _saveOptions(BuildContext context, String recoveryKey) {
     List<Widget> childrens = [];
     if (!_hasTriedToSave) {
-      childrens.add(ElevatedButton(
-        child: Text('Do this later'),
-        style: Theme.of(context).colorScheme.optionalActionButtonStyle,
-        onPressed: () async {
-          await _saveKeys();
-        },
-      ),);
+      childrens.add(
+        ElevatedButton(
+          child: Text('Do this later'),
+          style: Theme.of(context).colorScheme.optionalActionButtonStyle,
+          onPressed: () async {
+            await _saveKeys();
+          },
+        ),
+      );
       childrens.add(SizedBox(height: 10));
     }
 
-    childrens.add(GradientButton(
-      child: Text(
-        'Save key',
-        style: gradientButtonTextTheme(),
+    childrens.add(
+      GradientButton(
+        child: Text(
+          'Save key',
+          style: gradientButtonTextTheme(),
+        ),
+        linearGradientColors: const [
+          Color(0xFF2CD267),
+          Color(0xFF1DB954),
+        ],
+        onTap: () async {
+          await _shareRecoveryKey(recoveryKey);
+        },
       ),
-      linearGradientColors: const [
-        Color(0xFF2CD267),
-        Color(0xFF1DB954),
-      ],
-      onTap: () async {
-        await _shareRecoveryKey(recoveryKey);
-      },
-    ),);
+    );
     if (_hasTriedToSave) {
       childrens.add(SizedBox(height: 10));
-      childrens.add(ElevatedButton(
-        child: Text(widget.doneText),
-        onPressed: () async {
-          await _saveKeys();
-        },
-      ),);
+      childrens.add(
+        ElevatedButton(
+          child: Text(widget.doneText),
+          onPressed: () async {
+            await _saveKeys();
+          },
+        ),
+      );
     }
     childrens.add(SizedBox(height: 12));
     return childrens;

+ 43 - 40
lib/ui/recovery_page.dart

@@ -31,37 +31,38 @@ class _RecoveryPageState extends State<RecoveryPage> {
         ),
       ),
       floatingActionButton: DynamicFAB(
-          isKeypadOpen: false,
-          isFormValid: _recoveryKey.text.isNotEmpty,
-          buttonText: 'Recover',
-          onPressedFunction: () async {
-            final dialog = createProgressDialog(context, "Decrypting...");
-            await dialog.show();
-            try {
-              await Configuration.instance.recover(_recoveryKey.text.trim());
-              await dialog.hide();
-              showToast(context, "Recovery successful!");
-              Navigator.of(context).pushReplacement(
-                MaterialPageRoute(
-                  builder: (BuildContext context) {
-                    return WillPopScope(
-                      onWillPop: () async => false,
-                      child: PasswordEntryPage(
-                        mode: PasswordEntryMode.reset,
-                      ),
-                    );
-                  },
-                ),
-              );
-            } catch (e) {
-              await dialog.hide();
-              String errMessage = 'the recovery key you entered is incorrect';
-              if (e is AssertionError) {
-                errMessage = '$errMessage : ${e.message}';
-              }
-              showErrorDialog(context, "incorrect recovery key", errMessage);
+        isKeypadOpen: false,
+        isFormValid: _recoveryKey.text.isNotEmpty,
+        buttonText: 'Recover',
+        onPressedFunction: () async {
+          final dialog = createProgressDialog(context, "Decrypting...");
+          await dialog.show();
+          try {
+            await Configuration.instance.recover(_recoveryKey.text.trim());
+            await dialog.hide();
+            showToast(context, "Recovery successful!");
+            Navigator.of(context).pushReplacement(
+              MaterialPageRoute(
+                builder: (BuildContext context) {
+                  return WillPopScope(
+                    onWillPop: () async => false,
+                    child: PasswordEntryPage(
+                      mode: PasswordEntryMode.reset,
+                    ),
+                  );
+                },
+              ),
+            );
+          } catch (e) {
+            await dialog.hide();
+            String errMessage = 'the recovery key you entered is incorrect';
+            if (e is AssertionError) {
+              errMessage = '$errMessage : ${e.message}';
             }
-          },),
+            showErrorDialog(context, "incorrect recovery key", errMessage);
+          }
+        },
+      ),
       floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
       floatingActionButtonAnimator: NoScalingAnimation(),
       body: Column(
@@ -72,8 +73,10 @@ class _RecoveryPageState extends State<RecoveryPage> {
                 Padding(
                   padding:
                       const EdgeInsets.symmetric(vertical: 30, horizontal: 20),
-                  child: Text('Forgot password',
-                      style: Theme.of(context).textTheme.headline4,),
+                  child: Text(
+                    'Forgot password',
+                    style: Theme.of(context).textTheme.headline4,
+                  ),
                 ),
                 Padding(
                   padding: const EdgeInsets.fromLTRB(20, 24, 20, 0),
@@ -83,8 +86,9 @@ class _RecoveryPageState extends State<RecoveryPage> {
                       hintText: "Enter your recovery key",
                       contentPadding: EdgeInsets.all(20),
                       border: UnderlineInputBorder(
-                          borderSide: BorderSide.none,
-                          borderRadius: BorderRadius.circular(6),),
+                        borderSide: BorderSide.none,
+                        borderRadius: BorderRadius.circular(6),
+                      ),
                     ),
                     style: TextStyle(
                       fontSize: 14,
@@ -122,12 +126,11 @@ class _RecoveryPageState extends State<RecoveryPage> {
                         child: Center(
                           child: Text(
                             "No recovery key?",
-                            style: Theme.of(context)
-                                .textTheme
-                                .subtitle1
-                                .copyWith(
-                                    fontSize: 14,
-                                    decoration: TextDecoration.underline,),
+                            style:
+                                Theme.of(context).textTheme.subtitle1.copyWith(
+                                      fontSize: 14,
+                                      decoration: TextDecoration.underline,
+                                    ),
                           ),
                         ),
                       ),

+ 9 - 3
lib/ui/rename_dialog.dart

@@ -74,12 +74,18 @@ class _RenameDialogState extends State<RenameDialog> {
           onPressed: () {
             if (_newName.trim().isEmpty) {
               showErrorDialog(
-                  context, "Empty name", "${widget.type} name cannot be empty",);
+                context,
+                "Empty name",
+                "${widget.type} name cannot be empty",
+              );
               return;
             }
             if (_newName.trim().length > widget.maxLength) {
-              showErrorDialog(context, "Name too large",
-                  "${widget.type} name should be less than ${widget.maxLength} characters",);
+              showErrorDialog(
+                context,
+                "Name too large",
+                "${widget.type} name should be less than ${widget.maxLength} characters",
+              );
               return;
             }
             Navigator.of(context).pop(_newName.trim());

+ 4 - 1
lib/ui/sessions_page.dart

@@ -120,7 +120,10 @@ class _SessionsPageState extends State<SessionsPage> {
       await dialog.hide();
       _logger.severe('failed to terminate', e, s);
       showErrorDialog(
-          context, 'Oops', "Something went wrong, please try again",);
+        context,
+        'Oops',
+        "Something went wrong, please try again",
+      );
     }
   }
 

+ 3 - 1
lib/ui/set_wallpaper_dialog.dart

@@ -73,7 +73,9 @@ class _SetWallpaperDialogState extends State<SetWallpaperDialog> {
             await dialog.show();
             try {
               await WallpaperManagerFlutter().setwallpaperfromFile(
-                  await getFile(widget.file), _lockscreenValue,);
+                await getFile(widget.file),
+                _lockscreenValue,
+              );
               await dialog.hide();
               showToast(context, "Wallpaper set successfully");
             } catch (e, s) {

+ 16 - 6
lib/ui/settings/account_section_widget.dart

@@ -50,7 +50,9 @@ class AccountSectionWidgetState extends State<AccountSectionWidget> {
             );
           },
           child: SettingsTextItem(
-              text: "Subscription plan", icon: Icons.navigate_next,),
+            text: "Subscription plan",
+            icon: Icons.navigate_next,
+          ),
         ),
         SectionOptionDivider,
         GestureDetector(
@@ -74,9 +76,14 @@ class AccountSectionWidgetState extends State<AccountSectionWidget> {
               return;
             }
             routeToPage(
-                context,
-                RecoveryKeyPage(recoveryKey, "OK",
-                    showAppBar: true, onDone: () {},),);
+              context,
+              RecoveryKeyPage(
+                recoveryKey,
+                "OK",
+                showAppBar: true,
+                onDone: () {},
+              ),
+            );
           },
           child:
               SettingsTextItem(text: "Recovery key", icon: Icons.navigate_next),
@@ -130,7 +137,9 @@ class AccountSectionWidgetState extends State<AccountSectionWidget> {
             );
           },
           child: SettingsTextItem(
-              text: "Change password", icon: Icons.navigate_next,),
+            text: "Change password",
+            icon: Icons.navigate_next,
+          ),
         ),
       ],
     );
@@ -138,6 +147,7 @@ class AccountSectionWidgetState extends State<AccountSectionWidget> {
 
   Future<String> _getOrCreateRecoveryKey() async {
     return Sodium.bin2hex(
-        await UserService.instance.getOrCreateRecoveryKey(context),);
+      await UserService.instance.getOrCreateRecoveryKey(context),
+    );
   }
 }

+ 2 - 1
lib/ui/settings/app_version_widget.dart

@@ -34,7 +34,8 @@ class _AppVersionWidgetState extends State<AppVersionWidget> {
                 createProgressDialog(context, "Starting network inspector...");
             await dialog.show();
             await Future.delayed(
-                Duration(milliseconds: kDummyDelayDurationInMilliseconds),);
+              Duration(milliseconds: kDummyDelayDurationInMilliseconds),
+            );
             await dialog.hide();
             Network.instance.getAlice().showInspector();
           }

Some files were not shown because too many files changed in this diff