0
Fork 0
mirror of https://github.com/immich-app/immich.git synced 2025-02-11 01:18:24 -05:00

refactor(mobile): store backup settings on device (#2054)

Co-authored-by: Fynn Petersen-Frey <zoodyy@users.noreply.github.com>
Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
This commit is contained in:
Fynn Petersen-Frey 2023-03-23 16:25:58 +01:00 committed by GitHub
parent 32a065afc7
commit 40832f0ea7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 26 additions and 105 deletions

View file

@ -15,6 +15,7 @@ class BackUpState {
final double progressInPercentage; final double progressInPercentage;
final CancellationToken cancelToken; final CancellationToken cancelToken;
final ServerInfoResponseDto serverInfo; final ServerInfoResponseDto serverInfo;
final bool autoBackup;
final bool backgroundBackup; final bool backgroundBackup;
final bool backupRequireWifi; final bool backupRequireWifi;
final bool backupRequireCharging; final bool backupRequireCharging;
@ -40,6 +41,7 @@ class BackUpState {
required this.progressInPercentage, required this.progressInPercentage,
required this.cancelToken, required this.cancelToken,
required this.serverInfo, required this.serverInfo,
required this.autoBackup,
required this.backgroundBackup, required this.backgroundBackup,
required this.backupRequireWifi, required this.backupRequireWifi,
required this.backupRequireCharging, required this.backupRequireCharging,
@ -58,6 +60,7 @@ class BackUpState {
double? progressInPercentage, double? progressInPercentage,
CancellationToken? cancelToken, CancellationToken? cancelToken,
ServerInfoResponseDto? serverInfo, ServerInfoResponseDto? serverInfo,
bool? autoBackup,
bool? backgroundBackup, bool? backgroundBackup,
bool? backupRequireWifi, bool? backupRequireWifi,
bool? backupRequireCharging, bool? backupRequireCharging,
@ -75,6 +78,7 @@ class BackUpState {
progressInPercentage: progressInPercentage ?? this.progressInPercentage, progressInPercentage: progressInPercentage ?? this.progressInPercentage,
cancelToken: cancelToken ?? this.cancelToken, cancelToken: cancelToken ?? this.cancelToken,
serverInfo: serverInfo ?? this.serverInfo, serverInfo: serverInfo ?? this.serverInfo,
autoBackup: autoBackup ?? this.autoBackup,
backgroundBackup: backgroundBackup ?? this.backgroundBackup, backgroundBackup: backgroundBackup ?? this.backgroundBackup,
backupRequireWifi: backupRequireWifi ?? this.backupRequireWifi, backupRequireWifi: backupRequireWifi ?? this.backupRequireWifi,
backupRequireCharging: backupRequireCharging:
@ -92,7 +96,7 @@ class BackUpState {
@override @override
String toString() { 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 @override
@ -106,6 +110,7 @@ class BackUpState {
other.progressInPercentage == progressInPercentage && other.progressInPercentage == progressInPercentage &&
other.cancelToken == cancelToken && other.cancelToken == cancelToken &&
other.serverInfo == serverInfo && other.serverInfo == serverInfo &&
other.autoBackup == autoBackup &&
other.backgroundBackup == backgroundBackup && other.backgroundBackup == backgroundBackup &&
other.backupRequireWifi == backupRequireWifi && other.backupRequireWifi == backupRequireWifi &&
other.backupRequireCharging == backupRequireCharging && other.backupRequireCharging == backupRequireCharging &&
@ -128,6 +133,7 @@ class BackUpState {
progressInPercentage.hashCode ^ progressInPercentage.hashCode ^
cancelToken.hashCode ^ cancelToken.hashCode ^
serverInfo.hashCode ^ serverInfo.hashCode ^
autoBackup.hashCode ^
backgroundBackup.hashCode ^ backgroundBackup.hashCode ^
backupRequireWifi.hashCode ^ backupRequireWifi.hashCode ^
backupRequireCharging.hashCode ^ backupRequireCharging.hashCode ^

View file

@ -39,6 +39,7 @@ class BackupNotifier extends StateNotifier<BackUpState> {
allAssetsInDatabase: const [], allAssetsInDatabase: const [],
progressInPercentage: 0, progressInPercentage: 0,
cancelToken: CancellationToken(), cancelToken: CancellationToken(),
autoBackup: Store.get(StoreKey.autoBackup, false),
backgroundBackup: false, backgroundBackup: false,
backupRequireWifi: Store.get(StoreKey.backupRequireWifi, true), backupRequireWifi: Store.get(StoreKey.backupRequireWifi, true),
backupRequireCharging: backupRequireCharging:
@ -121,6 +122,11 @@ class BackupNotifier extends StateNotifier<BackUpState> {
_updateBackupAssetCount(); _updateBackupAssetCount();
} }
void setAutoBackup(bool enabled) {
Store.put(StoreKey.autoBackup, enabled);
state = state.copyWith(autoBackup: enabled);
}
void configureBackgroundBackup({ void configureBackgroundBackup({
bool? enabled, bool? enabled,
bool? requireWifi, bool? requireWifi,
@ -550,8 +556,7 @@ class BackupNotifier extends StateNotifier<BackUpState> {
} }
// Check if this device is enable backup by the user // Check if this device is enable backup by the user
if ((_authState.deviceInfo.deviceId == _authState.deviceId) && if (state.autoBackup) {
_authState.deviceInfo.isAutoBackup) {
// check if backup is alreayd in process - then return // check if backup is alreayd in process - then return
if (state.backupProgress == BackUpProgressEnum.inProgress) { if (state.backupProgress == BackUpProgressEnum.inProgress) {
log.info("[_resumeBackup] Backup is already in progress - abort"); log.info("[_resumeBackup] Backup is already in progress - abort");
@ -567,7 +572,6 @@ class BackupNotifier extends StateNotifier<BackUpState> {
log.info("[_resumeBackup] Start back up"); log.info("[_resumeBackup] Start back up");
await startBackupProcess(); await startBackupProcess();
} }
return; return;
} }

View file

@ -363,31 +363,6 @@ class BackupService {
return "OTHER"; return "OTHER";
} }
} }
Future<DeviceInfoResponseDto> 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 { class MultipartRequest extends http.MultipartRequest {

View file

@ -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/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/current_backup_asset_info_box.dart';
import 'package:immich_mobile/modules/backup/ui/ios_debug_info_tile.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/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/modules/backup/providers/backup.provider.dart';
import 'package:immich_mobile/routing/router.dart'; import 'package:immich_mobile/routing/router.dart';
import 'package:immich_mobile/shared/providers/websocket.provider.dart'; import 'package:immich_mobile/shared/providers/websocket.provider.dart';
@ -26,7 +24,6 @@ class BackupControllerPage extends HookConsumerWidget {
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
BackUpState backupState = ref.watch(backupProvider); BackUpState backupState = ref.watch(backupProvider);
AuthenticationState authenticationState = ref.watch(authenticationProvider);
final settings = ref.watch(iOSBackgroundSettingsProvider.notifier).settings; final settings = ref.watch(iOSBackgroundSettingsProvider.notifier).settings;
final appRefreshDisabled = final appRefreshDisabled =
@ -102,11 +99,11 @@ class BackupControllerPage extends HookConsumerWidget {
} }
ListTile buildAutoBackupController() { ListTile buildAutoBackupController() {
var backUpOption = authenticationState.deviceInfo.isAutoBackup final isAutoBackup = backupState.autoBackup;
final backUpOption = isAutoBackup
? "backup_controller_page_status_on".tr() ? "backup_controller_page_status_on".tr()
: "backup_controller_page_status_off".tr(); : "backup_controller_page_status_off".tr();
var isAutoBackup = authenticationState.deviceInfo.isAutoBackup; final backupBtnText = isAutoBackup
var backupBtnText = authenticationState.deviceInfo.isAutoBackup
? "backup_controller_page_turn_off".tr() ? "backup_controller_page_turn_off".tr()
: "backup_controller_page_turn_on".tr(); : "backup_controller_page_turn_on".tr();
return ListTile( return ListTile(
@ -134,17 +131,9 @@ class BackupControllerPage extends HookConsumerWidget {
Padding( Padding(
padding: const EdgeInsets.only(top: 8.0), padding: const EdgeInsets.only(top: 8.0),
child: ElevatedButton( child: ElevatedButton(
onPressed: () { onPressed: () => ref
if (isAutoBackup) { .read(backupProvider.notifier)
ref .setAutoBackup(!isAutoBackup),
.read(authenticationProvider.notifier)
.setAutoBackup(false);
} else {
ref
.read(authenticationProvider.notifier)
.setAutoBackup(true);
}
},
child: Text( child: Text(
backupBtnText, backupBtnText,
style: const TextStyle( style: const TextStyle(

View file

@ -28,8 +28,8 @@ class HomePageAppBar extends ConsumerWidget with PreferredSizeWidget {
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
final BackUpState backupState = ref.watch(backupProvider); final BackUpState backupState = ref.watch(backupProvider);
bool isEnableAutoBackup = backupState.backgroundBackup || final bool isEnableAutoBackup =
ref.watch(authenticationProvider).deviceInfo.isAutoBackup; backupState.backgroundBackup || backupState.autoBackup;
final ServerInfoState serverInfoState = ref.watch(serverInfoProvider); final ServerInfoState serverInfoState = ref.watch(serverInfoProvider);
AuthenticationState authState = ref.watch(authenticationProvider); AuthenticationState authState = ref.watch(authenticationProvider);

View file

@ -11,7 +11,6 @@ class AuthenticationState {
final bool isAdmin; final bool isAdmin;
final bool shouldChangePassword; final bool shouldChangePassword;
final String profileImagePath; final String profileImagePath;
final DeviceInfoResponseDto deviceInfo;
AuthenticationState({ AuthenticationState({
required this.deviceId, required this.deviceId,
required this.deviceType, required this.deviceType,
@ -23,7 +22,6 @@ class AuthenticationState {
required this.isAdmin, required this.isAdmin,
required this.shouldChangePassword, required this.shouldChangePassword,
required this.profileImagePath, required this.profileImagePath,
required this.deviceInfo,
}); });
AuthenticationState copyWith({ AuthenticationState copyWith({
@ -37,7 +35,6 @@ class AuthenticationState {
bool? isAdmin, bool? isAdmin,
bool? shouldChangePassword, bool? shouldChangePassword,
String? profileImagePath, String? profileImagePath,
DeviceInfoResponseDto? deviceInfo,
}) { }) {
return AuthenticationState( return AuthenticationState(
deviceId: deviceId ?? this.deviceId, deviceId: deviceId ?? this.deviceId,
@ -50,13 +47,12 @@ class AuthenticationState {
isAdmin: isAdmin ?? this.isAdmin, isAdmin: isAdmin ?? this.isAdmin,
shouldChangePassword: shouldChangePassword ?? this.shouldChangePassword, shouldChangePassword: shouldChangePassword ?? this.shouldChangePassword,
profileImagePath: profileImagePath ?? this.profileImagePath, profileImagePath: profileImagePath ?? this.profileImagePath,
deviceInfo: deviceInfo ?? this.deviceInfo,
); );
} }
@override @override
String toString() { 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 @override
@ -73,8 +69,7 @@ class AuthenticationState {
other.lastName == lastName && other.lastName == lastName &&
other.isAdmin == isAdmin && other.isAdmin == isAdmin &&
other.shouldChangePassword == shouldChangePassword && other.shouldChangePassword == shouldChangePassword &&
other.profileImagePath == profileImagePath && other.profileImagePath == profileImagePath;
other.deviceInfo == deviceInfo;
} }
@override @override
@ -88,7 +83,6 @@ class AuthenticationState {
lastName.hashCode ^ lastName.hashCode ^
isAdmin.hashCode ^ isAdmin.hashCode ^
shouldChangePassword.hashCode ^ shouldChangePassword.hashCode ^
profileImagePath.hashCode ^ profileImagePath.hashCode;
deviceInfo.hashCode;
} }
} }

View file

@ -5,7 +5,6 @@ import 'package:flutter/services.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/shared/models/store.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/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/models/user.dart';
import 'package:immich_mobile/shared/providers/api.provider.dart'; import 'package:immich_mobile/shared/providers/api.provider.dart';
import 'package:immich_mobile/shared/services/api.service.dart'; import 'package:immich_mobile/shared/services/api.service.dart';
@ -16,7 +15,6 @@ import 'package:openapi/api.dart';
class AuthenticationNotifier extends StateNotifier<AuthenticationState> { class AuthenticationNotifier extends StateNotifier<AuthenticationState> {
AuthenticationNotifier( AuthenticationNotifier(
this._deviceInfoService, this._deviceInfoService,
this._backupService,
this._apiService, this._apiService,
) : super( ) : super(
AuthenticationState( AuthenticationState(
@ -30,19 +28,10 @@ class AuthenticationNotifier extends StateNotifier<AuthenticationState> {
isAdmin: false, isAdmin: false,
shouldChangePassword: false, shouldChangePassword: false,
isAuthenticated: false, isAuthenticated: false,
deviceInfo: DeviceInfoResponseDto(
id: 0,
userId: "",
deviceId: "",
deviceType: DeviceTypeEnum.ANDROID,
createdAt: "",
isAutoBackup: false,
),
), ),
); );
final DeviceInfoService _deviceInfoService; final DeviceInfoService _deviceInfoService;
final BackupService _backupService;
final ApiService _apiService; final ApiService _apiService;
Future<bool> login( Future<bool> login(
@ -103,18 +92,6 @@ class AuthenticationNotifier extends StateNotifier<AuthenticationState> {
} }
} }
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) { updateUserProfileImagePath(String path) {
state = state.copyWith(profileImagePath: path); state = state.copyWith(profileImagePath: path);
} }
@ -174,28 +151,6 @@ class AuthenticationNotifier extends StateNotifier<AuthenticationState> {
deviceType: deviceInfo["deviceType"], 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; return true;
} }
} }
@ -204,7 +159,6 @@ final authenticationProvider =
StateNotifierProvider<AuthenticationNotifier, AuthenticationState>((ref) { StateNotifierProvider<AuthenticationNotifier, AuthenticationState>((ref) {
return AuthenticationNotifier( return AuthenticationNotifier(
ref.watch(deviceInfoServiceProvider), ref.watch(deviceInfoServiceProvider),
ref.watch(backupServiceProvider),
ref.watch(apiServiceProvider), ref.watch(apiServiceProvider),
); );
}); });

View file

@ -151,6 +151,7 @@ enum StoreKey<T> {
serverUrl<String>(10, type: String), serverUrl<String>(10, type: String),
accessToken<String>(11, type: String), accessToken<String>(11, type: String),
serverEndpoint<String>(12, type: String), serverEndpoint<String>(12, type: String),
autoBackup<bool>(13, type: bool),
// user settings from [AppSettingsEnum] below: // user settings from [AppSettingsEnum] below:
loadPreview<bool>(100, type: bool), loadPreview<bool>(100, type: bool),
loadOriginal<bool>(101, type: bool), loadOriginal<bool>(101, type: bool),

View file

@ -16,7 +16,6 @@ class ApiService {
late AssetApi assetApi; late AssetApi assetApi;
late SearchApi searchApi; late SearchApi searchApi;
late ServerInfoApi serverInfoApi; late ServerInfoApi serverInfoApi;
late DeviceInfoApi deviceInfoApi;
ApiService() { ApiService() {
final endpoint = Store.tryGet(StoreKey.serverEndpoint); final endpoint = Store.tryGet(StoreKey.serverEndpoint);
@ -38,7 +37,6 @@ class ApiService {
assetApi = AssetApi(_apiClient); assetApi = AssetApi(_apiClient);
serverInfoApi = ServerInfoApi(_apiClient); serverInfoApi = ServerInfoApi(_apiClient);
searchApi = SearchApi(_apiClient); searchApi = SearchApi(_apiClient);
deviceInfoApi = DeviceInfoApi(_apiClient);
} }
Future<String> resolveAndSetEndpoint(String serverUrl) async { Future<String> resolveAndSetEndpoint(String serverUrl) async {