瀏覽代碼

Merge branch 'main' into picker

ashilkn 2 年之前
父節點
當前提交
c2da85e7f0

+ 0 - 0
fastlane/metadata/android/en-US/changelogs/419.txt → fastlane/metadata/android/en-US/changelogs/420.txt


+ 29 - 0
lib/core/network/ente_interceptor.dart

@@ -0,0 +1,29 @@
+import 'package:dio/dio.dart';
+import 'package:flutter/foundation.dart';
+import 'package:photos/core/configuration.dart';
+import 'package:shared_preferences/shared_preferences.dart';
+import 'package:uuid/uuid.dart';
+
+class EnteRequestInterceptor extends Interceptor {
+  final SharedPreferences _preferences;
+  final String enteEndpoint;
+
+  EnteRequestInterceptor(this._preferences, this.enteEndpoint);
+
+  @override
+  void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
+    if (kDebugMode) {
+      assert(
+        options.baseUrl == enteEndpoint,
+        "interceptor should only be used for API endpoint",
+      );
+    }
+    // ignore: prefer_const_constructors
+    options.headers.putIfAbsent("x-request-id", () => Uuid().v4().toString());
+    final String? tokenValue = _preferences.getString(Configuration.tokenKey);
+    if (tokenValue != null) {
+      options.headers.putIfAbsent("X-Auth-Token", () => tokenValue);
+    }
+    return super.onRequest(options, handler);
+  }
+}

+ 5 - 30
lib/core/network.dart → lib/core/network/network.dart

@@ -2,16 +2,14 @@ import 'dart:io';
 
 
 import 'package:dio/dio.dart';
 import 'package:dio/dio.dart';
 import 'package:fk_user_agent/fk_user_agent.dart';
 import 'package:fk_user_agent/fk_user_agent.dart';
-import 'package:flutter/foundation.dart';
 import 'package:package_info_plus/package_info_plus.dart';
 import 'package:package_info_plus/package_info_plus.dart';
-import 'package:photos/core/configuration.dart';
 import 'package:photos/core/constants.dart';
 import 'package:photos/core/constants.dart';
+import 'package:photos/core/network/ente_interceptor.dart';
 import 'package:shared_preferences/shared_preferences.dart';
 import 'package:shared_preferences/shared_preferences.dart';
-import 'package:uuid/uuid.dart';
 
 
 int kConnectTimeout = 15000;
 int kConnectTimeout = 15000;
 
 
-class Network {
+class NetworkClient {
   // apiEndpoint points to the Ente server's API endpoint
   // apiEndpoint points to the Ente server's API endpoint
   static const apiEndpoint = String.fromEnvironment(
   static const apiEndpoint = String.fromEnvironment(
     "endpoint",
     "endpoint",
@@ -46,37 +44,14 @@ class Network {
         },
         },
       ),
       ),
     );
     );
-    _enteDio.interceptors.add(EnteRequestInterceptor(preferences));
+    _enteDio.interceptors.add(EnteRequestInterceptor(preferences, apiEndpoint));
   }
   }
 
 
-  Network._privateConstructor();
+  NetworkClient._privateConstructor();
 
 
-  static Network instance = Network._privateConstructor();
+  static NetworkClient instance = NetworkClient._privateConstructor();
 
 
   Dio getDio() => _dio;
   Dio getDio() => _dio;
 
 
   Dio get enteDio => _enteDio;
   Dio get enteDio => _enteDio;
 }
 }
-
-class EnteRequestInterceptor extends Interceptor {
-  final SharedPreferences _preferences;
-
-  EnteRequestInterceptor(this._preferences);
-
-  @override
-  void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
-    if (kDebugMode) {
-      assert(
-        options.baseUrl == Network.apiEndpoint,
-        "interceptor should only be used for API endpoint",
-      );
-    }
-    // ignore: prefer_const_constructors
-    options.headers.putIfAbsent("x-request-id", () => Uuid().v4().toString());
-    final String? tokenValue = _preferences.getString(Configuration.tokenKey);
-    if (tokenValue != null) {
-      options.headers.putIfAbsent("X-Auth-Token", () => tokenValue);
-    }
-    return super.onRequest(options, handler);
-  }
-}

+ 2 - 2
lib/main.dart

@@ -12,7 +12,7 @@ import 'package:photos/core/configuration.dart';
 import 'package:photos/core/constants.dart';
 import 'package:photos/core/constants.dart';
 import 'package:photos/core/error-reporting/super_logging.dart';
 import 'package:photos/core/error-reporting/super_logging.dart';
 import 'package:photos/core/errors.dart';
 import 'package:photos/core/errors.dart';
-import 'package:photos/core/network.dart';
+import 'package:photos/core/network/network.dart';
 import 'package:photos/db/upload_locks_db.dart';
 import 'package:photos/db/upload_locks_db.dart';
 import 'package:photos/ente_theme_data.dart';
 import 'package:photos/ente_theme_data.dart';
 import 'package:photos/services/app_lifecycle_service.dart';
 import 'package:photos/services/app_lifecycle_service.dart';
@@ -135,7 +135,7 @@ Future<void> _init(bool isBackground, {String via = ''}) async {
   }
   }
   CryptoUtil.init();
   CryptoUtil.init();
   await NotificationService.instance.init();
   await NotificationService.instance.init();
-  await Network.instance.init();
+  await NetworkClient.instance.init();
   await Configuration.instance.init();
   await Configuration.instance.init();
   await UserService.instance.init();
   await UserService.instance.init();
   await UserRemoteFlagService.instance.init();
   await UserRemoteFlagService.instance.init();

+ 2 - 2
lib/services/billing_service.dart

@@ -7,7 +7,7 @@ import 'package:flutter/material.dart';
 import 'package:in_app_purchase/in_app_purchase.dart';
 import 'package:in_app_purchase/in_app_purchase.dart';
 import 'package:logging/logging.dart';
 import 'package:logging/logging.dart';
 import 'package:photos/core/errors.dart';
 import 'package:photos/core/errors.dart';
-import 'package:photos/core/network.dart';
+import 'package:photos/core/network/network.dart';
 import 'package:photos/models/billing_plan.dart';
 import 'package:photos/models/billing_plan.dart';
 import 'package:photos/models/subscription.dart';
 import 'package:photos/models/subscription.dart';
 import 'package:photos/models/user_details.dart';
 import 'package:photos/models/user_details.dart';
@@ -32,7 +32,7 @@ class BillingService {
   static final BillingService instance = BillingService._privateConstructor();
   static final BillingService instance = BillingService._privateConstructor();
 
 
   final _logger = Logger("BillingService");
   final _logger = Logger("BillingService");
-  final _enteDio = Network.instance.enteDio;
+  final _enteDio = NetworkClient.instance.enteDio;
 
 
   bool _isOnSubscriptionPage = false;
   bool _isOnSubscriptionPage = false;
 
 

+ 2 - 2
lib/services/collections_service.dart

@@ -12,7 +12,7 @@ import 'package:photos/core/configuration.dart';
 import 'package:photos/core/constants.dart';
 import 'package:photos/core/constants.dart';
 import 'package:photos/core/errors.dart';
 import 'package:photos/core/errors.dart';
 import 'package:photos/core/event_bus.dart';
 import 'package:photos/core/event_bus.dart';
-import 'package:photos/core/network.dart';
+import 'package:photos/core/network/network.dart';
 import 'package:photos/db/collections_db.dart';
 import 'package:photos/db/collections_db.dart';
 import 'package:photos/db/device_files_db.dart';
 import 'package:photos/db/device_files_db.dart';
 import 'package:photos/db/files_db.dart';
 import 'package:photos/db/files_db.dart';
@@ -50,7 +50,7 @@ class CollectionsService {
   late Configuration _config;
   late Configuration _config;
   late SharedPreferences _prefs;
   late SharedPreferences _prefs;
 
 
-  final _enteDio = Network.instance.enteDio;
+  final _enteDio = NetworkClient.instance.enteDio;
   final _localPathToCollectionID = <String, int>{};
   final _localPathToCollectionID = <String, int>{};
   final _collectionIDToCollections = <int, Collection>{};
   final _collectionIDToCollections = <int, Collection>{};
   final _cachedKeys = <int, Uint8List>{};
   final _cachedKeys = <int, Uint8List>{};

+ 2 - 2
lib/services/deduplication_service.dart

@@ -1,13 +1,13 @@
 import 'package:logging/logging.dart';
 import 'package:logging/logging.dart';
 import 'package:photos/core/errors.dart';
 import 'package:photos/core/errors.dart';
-import 'package:photos/core/network.dart';
+import 'package:photos/core/network/network.dart';
 import 'package:photos/db/files_db.dart';
 import 'package:photos/db/files_db.dart';
 import 'package:photos/models/duplicate_files.dart';
 import 'package:photos/models/duplicate_files.dart';
 import 'package:photos/models/file.dart';
 import 'package:photos/models/file.dart';
 
 
 class DeduplicationService {
 class DeduplicationService {
   final _logger = Logger("DeduplicationService");
   final _logger = Logger("DeduplicationService");
-  final _enteDio = Network.instance.enteDio;
+  final _enteDio = NetworkClient.instance.enteDio;
 
 
   DeduplicationService._privateConstructor();
   DeduplicationService._privateConstructor();
 
 

+ 2 - 2
lib/services/feature_flag_service.dart

@@ -5,7 +5,7 @@ import 'package:flutter/foundation.dart';
 import 'package:logging/logging.dart';
 import 'package:logging/logging.dart';
 import 'package:photos/core/configuration.dart';
 import 'package:photos/core/configuration.dart';
 import 'package:photos/core/constants.dart';
 import 'package:photos/core/constants.dart';
-import 'package:photos/core/network.dart';
+import 'package:photos/core/network/network.dart';
 import 'package:shared_preferences/shared_preferences.dart';
 import 'package:shared_preferences/shared_preferences.dart';
 
 
 class FeatureFlagService {
 class FeatureFlagService {
@@ -69,7 +69,7 @@ class FeatureFlagService {
 
 
   Future<void> fetchFeatureFlags() async {
   Future<void> fetchFeatureFlags() async {
     try {
     try {
-      final response = await Network.instance
+      final response = await NetworkClient.instance
           .getDio()
           .getDio()
           .get("https://static.ente.io/feature_flags.json");
           .get("https://static.ente.io/feature_flags.json");
       final flagsResponse = FeatureFlags.fromMap(response.data);
       final flagsResponse = FeatureFlags.fromMap(response.data);

+ 2 - 2
lib/services/file_magic_service.dart

@@ -7,7 +7,7 @@ import 'package:logging/logging.dart';
 import 'package:photos/core/configuration.dart';
 import 'package:photos/core/configuration.dart';
 import 'package:photos/core/constants.dart';
 import 'package:photos/core/constants.dart';
 import 'package:photos/core/event_bus.dart';
 import 'package:photos/core/event_bus.dart';
-import 'package:photos/core/network.dart';
+import 'package:photos/core/network/network.dart';
 import 'package:photos/db/files_db.dart';
 import 'package:photos/db/files_db.dart';
 import 'package:photos/events/files_updated_event.dart';
 import 'package:photos/events/files_updated_event.dart';
 import 'package:photos/events/force_reload_home_gallery_event.dart';
 import 'package:photos/events/force_reload_home_gallery_event.dart';
@@ -26,7 +26,7 @@ class FileMagicService {
 
 
   FileMagicService._privateConstructor() {
   FileMagicService._privateConstructor() {
     _filesDB = FilesDB.instance;
     _filesDB = FilesDB.instance;
-    _enteDio = Network.instance.enteDio;
+    _enteDio = NetworkClient.instance.enteDio;
   }
   }
 
 
   static final FileMagicService instance =
   static final FileMagicService instance =

+ 2 - 2
lib/services/files_service.dart

@@ -2,7 +2,7 @@ import 'package:dio/dio.dart';
 import 'package:logging/logging.dart';
 import 'package:logging/logging.dart';
 import 'package:path/path.dart';
 import 'package:path/path.dart';
 import 'package:photos/core/configuration.dart';
 import 'package:photos/core/configuration.dart';
-import 'package:photos/core/network.dart';
+import 'package:photos/core/network/network.dart';
 import 'package:photos/db/files_db.dart';
 import 'package:photos/db/files_db.dart';
 import 'package:photos/extensions/list.dart';
 import 'package:photos/extensions/list.dart';
 import 'package:photos/models/file.dart';
 import 'package:photos/models/file.dart';
@@ -17,7 +17,7 @@ class FilesService {
   late Configuration _config;
   late Configuration _config;
 
 
   FilesService._privateConstructor() {
   FilesService._privateConstructor() {
-    _enteDio = Network.instance.enteDio;
+    _enteDio = NetworkClient.instance.enteDio;
     _logger = Logger("FilesService");
     _logger = Logger("FilesService");
     _filesDB = FilesDB.instance;
     _filesDB = FilesDB.instance;
     _config = Configuration.instance;
     _config = Configuration.instance;

+ 4 - 0
lib/services/local_sync_service.dart

@@ -171,6 +171,10 @@ class LocalSyncService {
   }
   }
 
 
   Future<bool> syncAll() async {
   Future<bool> syncAll() async {
+    if (!Configuration.instance.isLoggedIn()) {
+      _logger.warning("syncCall called when user is not logged in");
+      return false;
+    }
     final stopwatch = EnteWatch("localSyncAll")..start();
     final stopwatch = EnteWatch("localSyncAll")..start();
 
 
     final localAssets = await getAllLocalAssets();
     final localAssets = await getAllLocalAssets();

+ 2 - 2
lib/services/push_service.dart

@@ -4,7 +4,7 @@ import 'package:logging/logging.dart';
 import 'package:photos/core/configuration.dart';
 import 'package:photos/core/configuration.dart';
 import 'package:photos/core/constants.dart';
 import 'package:photos/core/constants.dart';
 import 'package:photos/core/event_bus.dart';
 import 'package:photos/core/event_bus.dart';
-import 'package:photos/core/network.dart';
+import 'package:photos/core/network/network.dart';
 import 'package:photos/events/signed_in_event.dart';
 import 'package:photos/events/signed_in_event.dart';
 import 'package:photos/services/sync_service.dart';
 import 'package:photos/services/sync_service.dart';
 import 'package:shared_preferences/shared_preferences.dart';
 import 'package:shared_preferences/shared_preferences.dart';
@@ -74,7 +74,7 @@ class PushService {
     String fcmToken,
     String fcmToken,
     String? apnsToken,
     String? apnsToken,
   ) async {
   ) async {
-    await Network.instance.enteDio.post(
+    await NetworkClient.instance.enteDio.post(
       "/push/token",
       "/push/token",
       data: {
       data: {
         "fcmToken": fcmToken,
         "fcmToken": fcmToken,

+ 4 - 4
lib/services/search_service.dart

@@ -1,6 +1,6 @@
 import 'package:logging/logging.dart';
 import 'package:logging/logging.dart';
 import 'package:photos/core/event_bus.dart';
 import 'package:photos/core/event_bus.dart';
-import 'package:photos/core/network.dart';
+import 'package:photos/core/network/network.dart';
 import 'package:photos/data/holidays.dart';
 import 'package:photos/data/holidays.dart';
 import 'package:photos/data/months.dart';
 import 'package:photos/data/months.dart';
 import 'package:photos/data/years.dart';
 import 'package:photos/data/years.dart';
@@ -21,7 +21,7 @@ import 'package:tuple/tuple.dart';
 
 
 class SearchService {
 class SearchService {
   Future<List<File>>? _cachedFilesFuture;
   Future<List<File>>? _cachedFilesFuture;
-  final _enteDio = Network.instance.enteDio;
+  final _enteDio = NetworkClient.instance.enteDio;
   final _logger = Logger((SearchService).toString());
   final _logger = Logger((SearchService).toString());
   final _collectionService = CollectionsService.instance;
   final _collectionService = CollectionsService.instance;
   static const _maximumResultsLimit = 20;
   static const _maximumResultsLimit = 20;
@@ -115,8 +115,8 @@ class SearchService {
         break;
         break;
       }
       }
 
 
-      if (!c.collection.isHidden() && c.collection.type != CollectionType
-          .uncategorized &&
+      if (!c.collection.isHidden() &&
+          c.collection.type != CollectionType.uncategorized &&
           c.collection.name!.toLowerCase().contains(
           c.collection.name!.toLowerCase().contains(
                 query.toLowerCase(),
                 query.toLowerCase(),
               )) {
               )) {

+ 2 - 2
lib/services/sync_service.dart

@@ -9,7 +9,7 @@ import 'package:photos/core/configuration.dart';
 import 'package:photos/core/constants.dart';
 import 'package:photos/core/constants.dart';
 import 'package:photos/core/errors.dart';
 import 'package:photos/core/errors.dart';
 import 'package:photos/core/event_bus.dart';
 import 'package:photos/core/event_bus.dart';
-import 'package:photos/core/network.dart';
+import 'package:photos/core/network/network.dart';
 import 'package:photos/db/device_files_db.dart';
 import 'package:photos/db/device_files_db.dart';
 import 'package:photos/db/files_db.dart';
 import 'package:photos/db/files_db.dart';
 import 'package:photos/events/permission_granted_event.dart';
 import 'package:photos/events/permission_granted_event.dart';
@@ -28,7 +28,7 @@ class SyncService {
   final _logger = Logger("SyncService");
   final _logger = Logger("SyncService");
   final _localSyncService = LocalSyncService.instance;
   final _localSyncService = LocalSyncService.instance;
   final _remoteSyncService = RemoteSyncService.instance;
   final _remoteSyncService = RemoteSyncService.instance;
-  final _enteDio = Network.instance.enteDio;
+  final _enteDio = NetworkClient.instance.enteDio;
   final _uploader = FileUploader.instance;
   final _uploader = FileUploader.instance;
   bool _syncStopRequested = false;
   bool _syncStopRequested = false;
   Completer<bool>? _existingSync;
   Completer<bool>? _existingSync;

+ 2 - 2
lib/services/trash_sync_service.dart

@@ -4,7 +4,7 @@ import 'package:dio/dio.dart';
 import 'package:logging/logging.dart';
 import 'package:logging/logging.dart';
 import 'package:photos/core/constants.dart';
 import 'package:photos/core/constants.dart';
 import 'package:photos/core/event_bus.dart';
 import 'package:photos/core/event_bus.dart';
-import 'package:photos/core/network.dart';
+import 'package:photos/core/network/network.dart';
 import 'package:photos/db/trash_db.dart';
 import 'package:photos/db/trash_db.dart';
 import 'package:photos/events/collection_updated_event.dart';
 import 'package:photos/events/collection_updated_event.dart';
 import 'package:photos/events/force_reload_trash_page_event.dart';
 import 'package:photos/events/force_reload_trash_page_event.dart';
@@ -29,7 +29,7 @@ class TrashSyncService {
 
 
   static final TrashSyncService instance =
   static final TrashSyncService instance =
       TrashSyncService._privateConstructor();
       TrashSyncService._privateConstructor();
-  final _enteDio = Network.instance.enteDio;
+  final _enteDio = NetworkClient.instance.enteDio;
 
 
   void init(SharedPreferences preferences) {
   void init(SharedPreferences preferences) {
     _prefs = preferences;
     _prefs = preferences;

+ 2 - 2
lib/services/update_service.dart

@@ -4,7 +4,7 @@ import 'package:flutter/foundation.dart';
 import 'package:logging/logging.dart';
 import 'package:logging/logging.dart';
 import 'package:package_info_plus/package_info_plus.dart';
 import 'package:package_info_plus/package_info_plus.dart';
 import 'package:photos/core/constants.dart';
 import 'package:photos/core/constants.dart';
-import 'package:photos/core/network.dart';
+import 'package:photos/core/network/network.dart';
 import 'package:photos/services/notification_service.dart';
 import 'package:photos/services/notification_service.dart';
 import 'package:shared_preferences/shared_preferences.dart';
 import 'package:shared_preferences/shared_preferences.dart';
 import 'package:tuple/tuple.dart';
 import 'package:tuple/tuple.dart';
@@ -98,7 +98,7 @@ class UpdateService {
   }
   }
 
 
   Future<LatestVersionInfo> _getLatestVersionInfo() async {
   Future<LatestVersionInfo> _getLatestVersionInfo() async {
-    final response = await Network.instance
+    final response = await NetworkClient.instance
         .getDio()
         .getDio()
         .get("https://ente.io/release-info/independent.json");
         .get("https://ente.io/release-info/independent.json");
     return LatestVersionInfo.fromMap(response.data["latestVersion"]);
     return LatestVersionInfo.fromMap(response.data["latestVersion"]);

+ 2 - 2
lib/services/user_remote_flag_service.dart

@@ -4,13 +4,13 @@ import 'dart:io';
 import 'package:collection/collection.dart';
 import 'package:collection/collection.dart';
 import 'package:logging/logging.dart';
 import 'package:logging/logging.dart';
 import 'package:photos/core/event_bus.dart';
 import 'package:photos/core/event_bus.dart';
-import 'package:photos/core/network.dart';
+import 'package:photos/core/network/network.dart';
 import 'package:photos/events/notification_event.dart';
 import 'package:photos/events/notification_event.dart';
 import 'package:photos/services/user_service.dart';
 import 'package:photos/services/user_service.dart';
 import 'package:shared_preferences/shared_preferences.dart';
 import 'package:shared_preferences/shared_preferences.dart';
 
 
 class UserRemoteFlagService {
 class UserRemoteFlagService {
-  final _enteDio = Network.instance.enteDio;
+  final _enteDio = NetworkClient.instance.enteDio;
   final _logger = Logger((UserRemoteFlagService).toString());
   final _logger = Logger((UserRemoteFlagService).toString());
   late SharedPreferences _prefs;
   late SharedPreferences _prefs;
 
 

+ 3 - 3
lib/services/user_service.dart

@@ -9,7 +9,7 @@ import 'package:logging/logging.dart';
 import 'package:photos/core/configuration.dart';
 import 'package:photos/core/configuration.dart';
 import 'package:photos/core/constants.dart';
 import 'package:photos/core/constants.dart';
 import 'package:photos/core/event_bus.dart';
 import 'package:photos/core/event_bus.dart';
-import 'package:photos/core/network.dart';
+import 'package:photos/core/network/network.dart';
 import 'package:photos/db/public_keys_db.dart';
 import 'package:photos/db/public_keys_db.dart';
 import 'package:photos/events/two_factor_status_change_event.dart';
 import 'package:photos/events/two_factor_status_change_event.dart';
 import 'package:photos/events/user_details_changed_event.dart';
 import 'package:photos/events/user_details_changed_event.dart';
@@ -37,8 +37,8 @@ import 'package:shared_preferences/shared_preferences.dart';
 class UserService {
 class UserService {
   static const keyHasEnabledTwoFactor = "has_enabled_two_factor";
   static const keyHasEnabledTwoFactor = "has_enabled_two_factor";
   static const keyUserDetails = "user_details";
   static const keyUserDetails = "user_details";
-  final _dio = Network.instance.getDio();
-  final _enteDio = Network.instance.enteDio;
+  final _dio = NetworkClient.instance.getDio();
+  final _enteDio = NetworkClient.instance.enteDio;
   final _logger = Logger((UserService).toString());
   final _logger = Logger((UserService).toString());
   final _config = Configuration.instance;
   final _config = Configuration.instance;
   late SharedPreferences _preferences;
   late SharedPreferences _preferences;

+ 8 - 6
lib/ui/account/sessions_page.dart

@@ -127,17 +127,19 @@ class _SessionsPageState extends State<SessionsPage> {
   }
   }
 
 
   Future<void> _fetchActiveSessions() async {
   Future<void> _fetchActiveSessions() async {
-    _sessions = await UserService.instance
-        .getActiveSessions()
-        .onError((error, stackTrace) {
-      showToast(context, "Failed to fetch active sessions");
-      throw error!;
+    _sessions = await UserService.instance.getActiveSessions().onError((e, s) {
+      _logger.severe("failed to fetch active sessions", e, s);
+      if (mounted) {
+        showToast(context, "Failed to fetch active sessions");
+      }
     });
     });
     if (_sessions != null) {
     if (_sessions != null) {
       _sessions!.sessions.sort((first, second) {
       _sessions!.sessions.sort((first, second) {
         return second.lastUsedTime.compareTo(first.lastUsedTime);
         return second.lastUsedTime.compareTo(first.lastUsedTime);
       });
       });
-      setState(() {});
+      if (mounted) {
+        setState(() {});
+      }
     }
     }
   }
   }
 
 

+ 9 - 5
lib/ui/actions/collection/collection_file_actions.dart

@@ -16,13 +16,15 @@ extension CollectionFileActions on CollectionActions {
     BuildContext bContext,
     BuildContext bContext,
     Collection collection,
     Collection collection,
     SelectedFiles selectedFiles,
     SelectedFiles selectedFiles,
+    bool removingOthersFile,
   ) async {
   ) async {
     final actionResult = await showActionSheet(
     final actionResult = await showActionSheet(
       context: bContext,
       context: bContext,
       buttons: [
       buttons: [
         ButtonWidget(
         ButtonWidget(
-          labelText: "Yes, remove",
-          buttonType: ButtonType.neutral,
+          labelText: "Remove",
+          buttonType:
+              removingOthersFile ? ButtonType.critical : ButtonType.neutral,
           buttonSize: ButtonSize.large,
           buttonSize: ButtonSize.large,
           shouldStickToDarkTheme: true,
           shouldStickToDarkTheme: true,
           isInAlert: true,
           isInAlert: true,
@@ -48,9 +50,11 @@ extension CollectionFileActions on CollectionActions {
           isInAlert: true,
           isInAlert: true,
         ),
         ),
       ],
       ],
-      title: "Remove from album?",
-      body: "Selected items will be removed from this album. Items which are "
-          "only in this album will be moved to Uncategorized.",
+      title: removingOthersFile ? "Remove from album?" : null,
+      body: removingOthersFile
+          ? "Some of the items you are removing were "
+              "added by other people, and you will lose access to them"
+          : "Selected items will be removed from this album",
       actionSheetType: ActionSheetType.defaultActionSheet,
       actionSheetType: ActionSheetType.defaultActionSheet,
     );
     );
     if (actionResult != null && actionResult == ButtonAction.error) {
     if (actionResult != null && actionResult == ButtonAction.error) {

+ 2 - 2
lib/ui/payment/billing_questions_widget.dart

@@ -2,7 +2,7 @@ import 'dart:convert';
 
 
 import 'package:expansion_tile_card/expansion_tile_card.dart';
 import 'package:expansion_tile_card/expansion_tile_card.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/material.dart';
-import 'package:photos/core/network.dart';
+import 'package:photos/core/network/network.dart';
 import 'package:photos/ente_theme_data.dart';
 import 'package:photos/ente_theme_data.dart';
 import 'package:photos/ui/common/loading_widget.dart';
 import 'package:photos/ui/common/loading_widget.dart';
 
 
@@ -14,7 +14,7 @@ class BillingQuestionsWidget extends StatelessWidget {
   @override
   @override
   Widget build(BuildContext context) {
   Widget build(BuildContext context) {
     return FutureBuilder(
     return FutureBuilder(
-      future: Network.instance
+      future: NetworkClient.instance
           .getDio()
           .getDio()
           .get("https://static.ente.io/faq.json")
           .get("https://static.ente.io/faq.json")
           .then((response) {
           .then((response) {

+ 2 - 2
lib/ui/settings/app_update_dialog.dart

@@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
 import 'package:logging/logging.dart';
 import 'package:logging/logging.dart';
 // import 'package:open_file/open_file.dart';
 // import 'package:open_file/open_file.dart';
 import 'package:photos/core/configuration.dart';
 import 'package:photos/core/configuration.dart';
-import 'package:photos/core/network.dart';
+import 'package:photos/core/network/network.dart';
 import 'package:photos/ente_theme_data.dart';
 import 'package:photos/ente_theme_data.dart';
 import 'package:photos/services/update_service.dart';
 import 'package:photos/services/update_service.dart';
 import 'package:photos/theme/ente_theme.dart';
 import 'package:photos/theme/ente_theme.dart';
@@ -183,7 +183,7 @@ class _ApkDownloaderDialogState extends State<ApkDownloaderDialog> {
 
 
   Future<void> _downloadApk() async {
   Future<void> _downloadApk() async {
     try {
     try {
-      await Network.instance.getDio().download(
+      await NetworkClient.instance.getDio().download(
         widget.versionInfo!.url,
         widget.versionInfo!.url,
         _saveUrl,
         _saveUrl,
         onReceiveProgress: (count, _) {
         onReceiveProgress: (count, _) {

+ 7 - 4
lib/ui/sharing/user_avator_widget.dart

@@ -26,10 +26,13 @@ class UserAvatarWidget extends StatelessWidget {
     final displayChar = (user.name == null || user.name!.isEmpty)
     final displayChar = (user.name == null || user.name!.isEmpty)
         ? ((user.email.isEmpty) ? " " : user.email.substring(0, 1))
         ? ((user.email.isEmpty) ? " " : user.email.substring(0, 1))
         : user.name!.substring(0, 1);
         : user.name!.substring(0, 1);
-    final randomColor = colorScheme.avatarColors[
-        (user.id ?? 0).remainder(colorScheme.avatarColors.length)];
-    final Color decorationColor =
-        ((user.id ?? -1) == currentUserID) ? Colors.black : randomColor;
+    Color decorationColor;
+    if (user.id == null || user.id! <= 0 || user.id == currentUserID) {
+      decorationColor = Colors.black;
+    } else {
+      decorationColor = colorScheme
+          .avatarColors[(user.id!).remainder(colorScheme.avatarColors.length)];
+    }
 
 
     final avatarStyle = getAvatarStyle(context, type);
     final avatarStyle = getAvatarStyle(context, type);
     final double size = avatarStyle.item1;
     final double size = avatarStyle.item1;

+ 3 - 0
lib/ui/viewer/actions/file_selection_actions_widget.dart

@@ -316,10 +316,13 @@ class _FileSelectionActionWidgetState extends State<FileSelectionActionWidget> {
       widget.selectedFiles
       widget.selectedFiles
           .unSelectAll(split.ownedByOtherUsers.toSet(), skipNotify: true);
           .unSelectAll(split.ownedByOtherUsers.toSet(), skipNotify: true);
     }
     }
+    final bool removingOthersFile =
+        isCollectionOwner && split.ownedByOtherUsers.isNotEmpty;
     await collectionActions.showRemoveFromCollectionSheetV2(
     await collectionActions.showRemoveFromCollectionSheetV2(
       context,
       context,
       widget.collection!,
       widget.collection!,
       widget.selectedFiles,
       widget.selectedFiles,
+      removingOthersFile,
     );
     );
   }
   }
 
 

+ 2 - 4
lib/ui/viewer/file/thumbnail_widget.dart

@@ -10,7 +10,6 @@ import 'package:photos/db/files_db.dart';
 import 'package:photos/db/trash_db.dart';
 import 'package:photos/db/trash_db.dart';
 import 'package:photos/events/files_updated_event.dart';
 import 'package:photos/events/files_updated_event.dart';
 import 'package:photos/events/local_photos_updated_event.dart';
 import 'package:photos/events/local_photos_updated_event.dart';
-import 'package:photos/extensions/string_ext.dart';
 import 'package:photos/models/collection.dart';
 import 'package:photos/models/collection.dart';
 import 'package:photos/models/file.dart';
 import 'package:photos/models/file.dart';
 import 'package:photos/models/file_type.dart';
 import 'package:photos/models/file_type.dart';
@@ -128,11 +127,10 @@ class _ThumbnailWidgetState extends State<ThumbnailWidget> {
           );
           );
         } else if (widget.file!.pubMagicMetadata!.uploaderName != null) {
         } else if (widget.file!.pubMagicMetadata!.uploaderName != null) {
           contentChildren.add(
           contentChildren.add(
-            // Use uploadName hashCode as userID so that different uploader
-            // get avatar color
+            // Use -1 as userID for enforcing black avatar color
             OwnerAvatarOverlayIcon(
             OwnerAvatarOverlayIcon(
               User(
               User(
-                id: widget.file!.pubMagicMetadata!.uploaderName.sumAsciiValues,
+                id: -1,
                 email: '',
                 email: '',
                 name: widget.file!.pubMagicMetadata!.uploaderName,
                 name: widget.file!.pubMagicMetadata!.uploaderName,
               ),
               ),

+ 2 - 2
lib/utils/diff_fetcher.dart

@@ -3,7 +3,7 @@ import 'dart:math';
 
 
 import 'package:flutter_sodium/flutter_sodium.dart';
 import 'package:flutter_sodium/flutter_sodium.dart';
 import 'package:logging/logging.dart';
 import 'package:logging/logging.dart';
-import 'package:photos/core/network.dart';
+import 'package:photos/core/network/network.dart';
 import 'package:photos/db/files_db.dart';
 import 'package:photos/db/files_db.dart';
 import 'package:photos/models/file.dart';
 import 'package:photos/models/file.dart';
 import 'package:photos/models/magic_metadata.dart';
 import 'package:photos/models/magic_metadata.dart';
@@ -12,7 +12,7 @@ import 'package:photos/utils/file_download_util.dart';
 
 
 class DiffFetcher {
 class DiffFetcher {
   final _logger = Logger("DiffFetcher");
   final _logger = Logger("DiffFetcher");
-  final _enteDio = Network.instance.enteDio;
+  final _enteDio = NetworkClient.instance.enteDio;
 
 
   Future<Diff> getEncryptedFilesDiff(int collectionID, int sinceTime) async {
   Future<Diff> getEncryptedFilesDiff(int collectionID, int sinceTime) async {
     _logger.info(
     _logger.info(

+ 2 - 2
lib/utils/file_download_util.dart

@@ -5,7 +5,7 @@ import 'package:dio/dio.dart';
 import 'package:flutter_sodium/flutter_sodium.dart';
 import 'package:flutter_sodium/flutter_sodium.dart';
 import 'package:logging/logging.dart';
 import 'package:logging/logging.dart';
 import 'package:photos/core/configuration.dart';
 import 'package:photos/core/configuration.dart';
-import 'package:photos/core/network.dart';
+import 'package:photos/core/network/network.dart';
 import 'package:photos/models/file.dart' as ente;
 import 'package:photos/models/file.dart' as ente;
 import 'package:photos/services/collections_service.dart';
 import 'package:photos/services/collections_service.dart';
 import 'package:photos/utils/crypto_util.dart';
 import 'package:photos/utils/crypto_util.dart';
@@ -22,7 +22,7 @@ Future<io.File?> downloadAndDecrypt(
       ".encrypted";
       ".encrypted";
   final encryptedFile = io.File(encryptedFilePath);
   final encryptedFile = io.File(encryptedFilePath);
   final startTime = DateTime.now().millisecondsSinceEpoch;
   final startTime = DateTime.now().millisecondsSinceEpoch;
-  return Network.instance
+  return NetworkClient.instance
       .getDio()
       .getDio()
       .download(
       .download(
         file.downloadUrl,
         file.downloadUrl,

+ 3 - 3
lib/utils/file_uploader.dart

@@ -15,7 +15,7 @@ import 'package:path/path.dart';
 import 'package:photos/core/configuration.dart';
 import 'package:photos/core/configuration.dart';
 import 'package:photos/core/errors.dart';
 import 'package:photos/core/errors.dart';
 import 'package:photos/core/event_bus.dart';
 import 'package:photos/core/event_bus.dart';
-import 'package:photos/core/network.dart';
+import 'package:photos/core/network/network.dart';
 import 'package:photos/db/files_db.dart';
 import 'package:photos/db/files_db.dart';
 import 'package:photos/db/upload_locks_db.dart';
 import 'package:photos/db/upload_locks_db.dart';
 import 'package:photos/events/files_updated_event.dart';
 import 'package:photos/events/files_updated_event.dart';
@@ -44,8 +44,8 @@ class FileUploader {
   static const kFileUploadTimeout = Duration(minutes: 50);
   static const kFileUploadTimeout = Duration(minutes: 50);
 
 
   final _logger = Logger("FileUploader");
   final _logger = Logger("FileUploader");
-  final _dio = Network.instance.getDio();
-  final _enteDio = Network.instance.enteDio;
+  final _dio = NetworkClient.instance.getDio();
+  final _enteDio = NetworkClient.instance.enteDio;
   final LinkedHashMap _queue = LinkedHashMap<String, FileUploadItem>();
   final LinkedHashMap _queue = LinkedHashMap<String, FileUploadItem>();
   final _uploadLocks = UploadLocksDB.instance;
   final _uploadLocks = UploadLocksDB.instance;
   final kSafeBufferForLockExpiry = const Duration(days: 1).inMicroseconds;
   final kSafeBufferForLockExpiry = const Duration(days: 1).inMicroseconds;

+ 2 - 2
lib/utils/thumbnail_util.dart

@@ -11,7 +11,7 @@ import 'package:photos/core/cache/thumbnail_in_memory_cache.dart';
 import 'package:photos/core/configuration.dart';
 import 'package:photos/core/configuration.dart';
 import 'package:photos/core/constants.dart';
 import 'package:photos/core/constants.dart';
 import 'package:photos/core/errors.dart';
 import 'package:photos/core/errors.dart';
-import 'package:photos/core/network.dart';
+import 'package:photos/core/network/network.dart';
 import 'package:photos/models/file.dart';
 import 'package:photos/models/file.dart';
 import 'package:photos/utils/crypto_util.dart';
 import 'package:photos/utils/crypto_util.dart';
 import 'package:photos/utils/file_download_util.dart';
 import 'package:photos/utils/file_download_util.dart';
@@ -129,7 +129,7 @@ Future<void> _downloadAndDecryptThumbnail(FileDownloadItem item) async {
   final file = item.file;
   final file = item.file;
   Uint8List encryptedThumbnail;
   Uint8List encryptedThumbnail;
   try {
   try {
-    encryptedThumbnail = (await Network.instance.getDio().get(
+    encryptedThumbnail = (await NetworkClient.instance.getDio().get(
               file.thumbnailUrl,
               file.thumbnailUrl,
               options: Options(
               options: Options(
                 headers: {"X-Auth-Token": Configuration.instance.getToken()},
                 headers: {"X-Auth-Token": Configuration.instance.getToken()},

+ 2 - 2
lib/utils/trash_diff_fetcher.dart

@@ -3,7 +3,7 @@ import 'dart:math';
 
 
 import 'package:flutter_sodium/flutter_sodium.dart';
 import 'package:flutter_sodium/flutter_sodium.dart';
 import 'package:logging/logging.dart';
 import 'package:logging/logging.dart';
-import 'package:photos/core/network.dart';
+import 'package:photos/core/network/network.dart';
 import 'package:photos/models/magic_metadata.dart';
 import 'package:photos/models/magic_metadata.dart';
 import 'package:photos/models/trash_file.dart';
 import 'package:photos/models/trash_file.dart';
 import 'package:photos/utils/crypto_util.dart';
 import 'package:photos/utils/crypto_util.dart';
@@ -11,7 +11,7 @@ import 'package:photos/utils/file_download_util.dart';
 
 
 class TrashDiffFetcher {
 class TrashDiffFetcher {
   final _logger = Logger("TrashDiffFetcher");
   final _logger = Logger("TrashDiffFetcher");
-  final _enteDio = Network.instance.enteDio;
+  final _enteDio = NetworkClient.instance.enteDio;
 
 
   Future<Diff> getTrashFilesDiff(int sinceTime) async {
   Future<Diff> getTrashFilesDiff(int sinceTime) async {
     try {
     try {

+ 1 - 1
pubspec.yaml

@@ -12,7 +12,7 @@ description: ente photos application
 # Read more about iOS versioning at
 # Read more about iOS versioning at
 # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
 # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
 
 
-version: 0.7.19+419
+version: 0.7.20+420
 
 
 environment:
 environment:
   sdk: '>=2.17.0 <3.0.0'
   sdk: '>=2.17.0 <3.0.0'