From 40832f0ea7f1835975be25c4ae736c67d1a38b30 Mon Sep 17 00:00:00 2001 From: Fynn Petersen-Frey <10599762+fyfrey@users.noreply.github.com> Date: Thu, 23 Mar 2023 16:25:58 +0100 Subject: [PATCH] refactor(mobile): store backup settings on device (#2054) Co-authored-by: Fynn Petersen-Frey Co-authored-by: Alex Tran --- .../backup/models/backup_state.model.dart | 8 +++- .../backup/providers/backup.provider.dart | 10 ++-- .../backup/services/backup.service.dart | 25 ---------- .../backup/views/backup_controller_page.dart | 23 +++------- .../modules/home/ui/home_page_app_bar.dart | 4 +- .../models/authentication_state.model.dart | 12 ++--- .../providers/authentication.provider.dart | 46 ------------------- mobile/lib/shared/models/store.dart | 1 + mobile/lib/shared/services/api.service.dart | 2 - 9 files changed, 26 insertions(+), 105 deletions(-) diff --git a/mobile/lib/modules/backup/models/backup_state.model.dart b/mobile/lib/modules/backup/models/backup_state.model.dart index ab08d1f4ba..cfec7513ef 100644 --- a/mobile/lib/modules/backup/models/backup_state.model.dart +++ b/mobile/lib/modules/backup/models/backup_state.model.dart @@ -15,6 +15,7 @@ class BackUpState { final double progressInPercentage; final CancellationToken cancelToken; final ServerInfoResponseDto serverInfo; + final bool autoBackup; final bool backgroundBackup; final bool backupRequireWifi; final bool backupRequireCharging; @@ -40,6 +41,7 @@ class BackUpState { required this.progressInPercentage, required this.cancelToken, required this.serverInfo, + required this.autoBackup, required this.backgroundBackup, required this.backupRequireWifi, required this.backupRequireCharging, @@ -58,6 +60,7 @@ class BackUpState { double? progressInPercentage, CancellationToken? cancelToken, ServerInfoResponseDto? serverInfo, + bool? autoBackup, bool? backgroundBackup, bool? backupRequireWifi, bool? backupRequireCharging, @@ -75,6 +78,7 @@ class BackUpState { progressInPercentage: progressInPercentage ?? this.progressInPercentage, cancelToken: cancelToken ?? this.cancelToken, serverInfo: serverInfo ?? this.serverInfo, + autoBackup: autoBackup ?? this.autoBackup, backgroundBackup: backgroundBackup ?? this.backgroundBackup, backupRequireWifi: backupRequireWifi ?? this.backupRequireWifi, backupRequireCharging: @@ -92,7 +96,7 @@ class BackUpState { @override String toString() { - return 'BackUpState(backupProgress: $backupProgress, allAssetsInDatabase: $allAssetsInDatabase, progressInPercentage: $progressInPercentage, cancelToken: $cancelToken, serverInfo: $serverInfo, backgroundBackup: $backgroundBackup, backupRequireWifi: $backupRequireWifi, backupRequireCharging: $backupRequireCharging, backupTriggerDelay: $backupTriggerDelay, availableAlbums: $availableAlbums, selectedBackupAlbums: $selectedBackupAlbums, excludedBackupAlbums: $excludedBackupAlbums, allUniqueAssets: $allUniqueAssets, selectedAlbumsBackupAssetsIds: $selectedAlbumsBackupAssetsIds, currentUploadAsset: $currentUploadAsset)'; + return 'BackUpState(backupProgress: $backupProgress, allAssetsInDatabase: $allAssetsInDatabase, progressInPercentage: $progressInPercentage, cancelToken: $cancelToken, serverInfo: $serverInfo, autoBackup: $autoBackup, backgroundBackup: $backgroundBackup, backupRequireWifi: $backupRequireWifi, backupRequireCharging: $backupRequireCharging, backupTriggerDelay: $backupTriggerDelay, availableAlbums: $availableAlbums, selectedBackupAlbums: $selectedBackupAlbums, excludedBackupAlbums: $excludedBackupAlbums, allUniqueAssets: $allUniqueAssets, selectedAlbumsBackupAssetsIds: $selectedAlbumsBackupAssetsIds, currentUploadAsset: $currentUploadAsset)'; } @override @@ -106,6 +110,7 @@ class BackUpState { other.progressInPercentage == progressInPercentage && other.cancelToken == cancelToken && other.serverInfo == serverInfo && + other.autoBackup == autoBackup && other.backgroundBackup == backgroundBackup && other.backupRequireWifi == backupRequireWifi && other.backupRequireCharging == backupRequireCharging && @@ -128,6 +133,7 @@ class BackUpState { progressInPercentage.hashCode ^ cancelToken.hashCode ^ serverInfo.hashCode ^ + autoBackup.hashCode ^ backgroundBackup.hashCode ^ backupRequireWifi.hashCode ^ backupRequireCharging.hashCode ^ diff --git a/mobile/lib/modules/backup/providers/backup.provider.dart b/mobile/lib/modules/backup/providers/backup.provider.dart index 337af7135b..835da7960b 100644 --- a/mobile/lib/modules/backup/providers/backup.provider.dart +++ b/mobile/lib/modules/backup/providers/backup.provider.dart @@ -39,6 +39,7 @@ class BackupNotifier extends StateNotifier { allAssetsInDatabase: const [], progressInPercentage: 0, cancelToken: CancellationToken(), + autoBackup: Store.get(StoreKey.autoBackup, false), backgroundBackup: false, backupRequireWifi: Store.get(StoreKey.backupRequireWifi, true), backupRequireCharging: @@ -121,6 +122,11 @@ class BackupNotifier extends StateNotifier { _updateBackupAssetCount(); } + void setAutoBackup(bool enabled) { + Store.put(StoreKey.autoBackup, enabled); + state = state.copyWith(autoBackup: enabled); + } + void configureBackgroundBackup({ bool? enabled, bool? requireWifi, @@ -550,8 +556,7 @@ class BackupNotifier extends StateNotifier { } // Check if this device is enable backup by the user - if ((_authState.deviceInfo.deviceId == _authState.deviceId) && - _authState.deviceInfo.isAutoBackup) { + if (state.autoBackup) { // check if backup is alreayd in process - then return if (state.backupProgress == BackUpProgressEnum.inProgress) { log.info("[_resumeBackup] Backup is already in progress - abort"); @@ -567,7 +572,6 @@ class BackupNotifier extends StateNotifier { log.info("[_resumeBackup] Start back up"); await startBackupProcess(); } - return; } diff --git a/mobile/lib/modules/backup/services/backup.service.dart b/mobile/lib/modules/backup/services/backup.service.dart index 88921c3f03..348fa69d15 100644 --- a/mobile/lib/modules/backup/services/backup.service.dart +++ b/mobile/lib/modules/backup/services/backup.service.dart @@ -363,31 +363,6 @@ class BackupService { return "OTHER"; } } - - Future setAutoBackup( - bool status, - String deviceId, - DeviceTypeEnum deviceType, - ) async { - try { - var updatedDeviceInfo = await _apiService.deviceInfoApi.upsertDeviceInfo( - UpsertDeviceInfoDto( - deviceId: deviceId, - deviceType: deviceType, - isAutoBackup: status, - ), - ); - - if (updatedDeviceInfo == null) { - throw Exception("Error updating device info"); - } - - return updatedDeviceInfo; - } catch (e) { - debugPrint("Error setAutoBackup: ${e.toString()}"); - throw Error(); - } - } } class MultipartRequest extends http.MultipartRequest { diff --git a/mobile/lib/modules/backup/views/backup_controller_page.dart b/mobile/lib/modules/backup/views/backup_controller_page.dart index 9df9a307ee..1ee66f9737 100644 --- a/mobile/lib/modules/backup/views/backup_controller_page.dart +++ b/mobile/lib/modules/backup/views/backup_controller_page.dart @@ -10,9 +10,7 @@ import 'package:immich_mobile/modules/backup/providers/error_backup_list.provide import 'package:immich_mobile/modules/backup/providers/ios_background_settings.provider.dart'; import 'package:immich_mobile/modules/backup/ui/current_backup_asset_info_box.dart'; import 'package:immich_mobile/modules/backup/ui/ios_debug_info_tile.dart'; -import 'package:immich_mobile/modules/login/models/authentication_state.model.dart'; import 'package:immich_mobile/modules/backup/models/backup_state.model.dart'; -import 'package:immich_mobile/modules/login/providers/authentication.provider.dart'; import 'package:immich_mobile/modules/backup/providers/backup.provider.dart'; import 'package:immich_mobile/routing/router.dart'; import 'package:immich_mobile/shared/providers/websocket.provider.dart'; @@ -26,7 +24,6 @@ class BackupControllerPage extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { BackUpState backupState = ref.watch(backupProvider); - AuthenticationState authenticationState = ref.watch(authenticationProvider); final settings = ref.watch(iOSBackgroundSettingsProvider.notifier).settings; final appRefreshDisabled = @@ -102,11 +99,11 @@ class BackupControllerPage extends HookConsumerWidget { } ListTile buildAutoBackupController() { - var backUpOption = authenticationState.deviceInfo.isAutoBackup + final isAutoBackup = backupState.autoBackup; + final backUpOption = isAutoBackup ? "backup_controller_page_status_on".tr() : "backup_controller_page_status_off".tr(); - var isAutoBackup = authenticationState.deviceInfo.isAutoBackup; - var backupBtnText = authenticationState.deviceInfo.isAutoBackup + final backupBtnText = isAutoBackup ? "backup_controller_page_turn_off".tr() : "backup_controller_page_turn_on".tr(); return ListTile( @@ -134,17 +131,9 @@ class BackupControllerPage extends HookConsumerWidget { Padding( padding: const EdgeInsets.only(top: 8.0), child: ElevatedButton( - onPressed: () { - if (isAutoBackup) { - ref - .read(authenticationProvider.notifier) - .setAutoBackup(false); - } else { - ref - .read(authenticationProvider.notifier) - .setAutoBackup(true); - } - }, + onPressed: () => ref + .read(backupProvider.notifier) + .setAutoBackup(!isAutoBackup), child: Text( backupBtnText, style: const TextStyle( diff --git a/mobile/lib/modules/home/ui/home_page_app_bar.dart b/mobile/lib/modules/home/ui/home_page_app_bar.dart index 0352001d6d..aa33f89818 100644 --- a/mobile/lib/modules/home/ui/home_page_app_bar.dart +++ b/mobile/lib/modules/home/ui/home_page_app_bar.dart @@ -28,8 +28,8 @@ class HomePageAppBar extends ConsumerWidget with PreferredSizeWidget { @override Widget build(BuildContext context, WidgetRef ref) { final BackUpState backupState = ref.watch(backupProvider); - bool isEnableAutoBackup = backupState.backgroundBackup || - ref.watch(authenticationProvider).deviceInfo.isAutoBackup; + final bool isEnableAutoBackup = + backupState.backgroundBackup || backupState.autoBackup; final ServerInfoState serverInfoState = ref.watch(serverInfoProvider); AuthenticationState authState = ref.watch(authenticationProvider); diff --git a/mobile/lib/modules/login/models/authentication_state.model.dart b/mobile/lib/modules/login/models/authentication_state.model.dart index 4805d499bd..f59167c349 100644 --- a/mobile/lib/modules/login/models/authentication_state.model.dart +++ b/mobile/lib/modules/login/models/authentication_state.model.dart @@ -11,7 +11,6 @@ class AuthenticationState { final bool isAdmin; final bool shouldChangePassword; final String profileImagePath; - final DeviceInfoResponseDto deviceInfo; AuthenticationState({ required this.deviceId, required this.deviceType, @@ -23,7 +22,6 @@ class AuthenticationState { required this.isAdmin, required this.shouldChangePassword, required this.profileImagePath, - required this.deviceInfo, }); AuthenticationState copyWith({ @@ -37,7 +35,6 @@ class AuthenticationState { bool? isAdmin, bool? shouldChangePassword, String? profileImagePath, - DeviceInfoResponseDto? deviceInfo, }) { return AuthenticationState( deviceId: deviceId ?? this.deviceId, @@ -50,13 +47,12 @@ class AuthenticationState { isAdmin: isAdmin ?? this.isAdmin, shouldChangePassword: shouldChangePassword ?? this.shouldChangePassword, profileImagePath: profileImagePath ?? this.profileImagePath, - deviceInfo: deviceInfo ?? this.deviceInfo, ); } @override String toString() { - return 'AuthenticationState(deviceId: $deviceId, deviceType: $deviceType, userId: $userId, userEmail: $userEmail, isAuthenticated: $isAuthenticated, firstName: $firstName, lastName: $lastName, isAdmin: $isAdmin, shouldChangePassword: $shouldChangePassword, profileImagePath: $profileImagePath, deviceInfo: $deviceInfo)'; + return 'AuthenticationState(deviceId: $deviceId, deviceType: $deviceType, userId: $userId, userEmail: $userEmail, isAuthenticated: $isAuthenticated, firstName: $firstName, lastName: $lastName, isAdmin: $isAdmin, shouldChangePassword: $shouldChangePassword, profileImagePath: $profileImagePath)'; } @override @@ -73,8 +69,7 @@ class AuthenticationState { other.lastName == lastName && other.isAdmin == isAdmin && other.shouldChangePassword == shouldChangePassword && - other.profileImagePath == profileImagePath && - other.deviceInfo == deviceInfo; + other.profileImagePath == profileImagePath; } @override @@ -88,7 +83,6 @@ class AuthenticationState { lastName.hashCode ^ isAdmin.hashCode ^ shouldChangePassword.hashCode ^ - profileImagePath.hashCode ^ - deviceInfo.hashCode; + profileImagePath.hashCode; } } diff --git a/mobile/lib/modules/login/providers/authentication.provider.dart b/mobile/lib/modules/login/providers/authentication.provider.dart index 77c083fea3..76e6b74820 100644 --- a/mobile/lib/modules/login/providers/authentication.provider.dart +++ b/mobile/lib/modules/login/providers/authentication.provider.dart @@ -5,7 +5,6 @@ import 'package:flutter/services.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/shared/models/store.dart'; import 'package:immich_mobile/modules/login/models/authentication_state.model.dart'; -import 'package:immich_mobile/modules/backup/services/backup.service.dart'; import 'package:immich_mobile/shared/models/user.dart'; import 'package:immich_mobile/shared/providers/api.provider.dart'; import 'package:immich_mobile/shared/services/api.service.dart'; @@ -16,7 +15,6 @@ import 'package:openapi/api.dart'; class AuthenticationNotifier extends StateNotifier { AuthenticationNotifier( this._deviceInfoService, - this._backupService, this._apiService, ) : super( AuthenticationState( @@ -30,19 +28,10 @@ class AuthenticationNotifier extends StateNotifier { isAdmin: false, shouldChangePassword: false, isAuthenticated: false, - deviceInfo: DeviceInfoResponseDto( - id: 0, - userId: "", - deviceId: "", - deviceType: DeviceTypeEnum.ANDROID, - createdAt: "", - isAutoBackup: false, - ), ), ); final DeviceInfoService _deviceInfoService; - final BackupService _backupService; final ApiService _apiService; Future login( @@ -103,18 +92,6 @@ class AuthenticationNotifier extends StateNotifier { } } - setAutoBackup(bool backupState) async { - var deviceInfo = await _deviceInfoService.getDeviceInfo(); - var deviceId = deviceInfo["deviceId"]; - - DeviceTypeEnum deviceType = deviceInfo["deviceType"]; - - DeviceInfoResponseDto updatedDeviceInfo = - await _backupService.setAutoBackup(backupState, deviceId, deviceType); - - state = state.copyWith(deviceInfo: updatedDeviceInfo); - } - updateUserProfileImagePath(String path) { state = state.copyWith(profileImagePath: path); } @@ -174,28 +151,6 @@ class AuthenticationNotifier extends StateNotifier { deviceType: deviceInfo["deviceType"], ); } - - // Register device info - try { - DeviceInfoResponseDto? deviceInfo = - await _apiService.deviceInfoApi.upsertDeviceInfo( - UpsertDeviceInfoDto( - deviceId: state.deviceId, - deviceType: state.deviceType, - ), - ); - - if (deviceInfo == null) { - debugPrint('Device Info Response is null'); - return false; - } - - state = state.copyWith(deviceInfo: deviceInfo); - } catch (e) { - debugPrint("ERROR Register Device Info: $e"); - return e is ApiException && e.innerException is SocketException; - } - return true; } } @@ -204,7 +159,6 @@ final authenticationProvider = StateNotifierProvider((ref) { return AuthenticationNotifier( ref.watch(deviceInfoServiceProvider), - ref.watch(backupServiceProvider), ref.watch(apiServiceProvider), ); }); diff --git a/mobile/lib/shared/models/store.dart b/mobile/lib/shared/models/store.dart index 69a620131f..6c88b7e82c 100644 --- a/mobile/lib/shared/models/store.dart +++ b/mobile/lib/shared/models/store.dart @@ -151,6 +151,7 @@ enum StoreKey { serverUrl(10, type: String), accessToken(11, type: String), serverEndpoint(12, type: String), + autoBackup(13, type: bool), // user settings from [AppSettingsEnum] below: loadPreview(100, type: bool), loadOriginal(101, type: bool), diff --git a/mobile/lib/shared/services/api.service.dart b/mobile/lib/shared/services/api.service.dart index e4576214ee..c957023f96 100644 --- a/mobile/lib/shared/services/api.service.dart +++ b/mobile/lib/shared/services/api.service.dart @@ -16,7 +16,6 @@ class ApiService { late AssetApi assetApi; late SearchApi searchApi; late ServerInfoApi serverInfoApi; - late DeviceInfoApi deviceInfoApi; ApiService() { final endpoint = Store.tryGet(StoreKey.serverEndpoint); @@ -38,7 +37,6 @@ class ApiService { assetApi = AssetApi(_apiClient); serverInfoApi = ServerInfoApi(_apiClient); searchApi = SearchApi(_apiClient); - deviceInfoApi = DeviceInfoApi(_apiClient); } Future resolveAndSetEndpoint(String serverUrl) async {