mirror of
https://github.com/immich-app/immich.git
synced 2024-12-25 10:43:13 +02: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:
parent
32a065afc7
commit
40832f0ea7
@ -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 ^
|
||||
|
@ -39,6 +39,7 @@ class BackupNotifier extends StateNotifier<BackUpState> {
|
||||
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<BackUpState> {
|
||||
_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<BackUpState> {
|
||||
}
|
||||
|
||||
// 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<BackUpState> {
|
||||
log.info("[_resumeBackup] Start back up");
|
||||
await startBackupProcess();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -363,31 +363,6 @@ class BackupService {
|
||||
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 {
|
||||
|
@ -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(
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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<AuthenticationState> {
|
||||
AuthenticationNotifier(
|
||||
this._deviceInfoService,
|
||||
this._backupService,
|
||||
this._apiService,
|
||||
) : super(
|
||||
AuthenticationState(
|
||||
@ -30,19 +28,10 @@ class AuthenticationNotifier extends StateNotifier<AuthenticationState> {
|
||||
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<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) {
|
||||
state = state.copyWith(profileImagePath: path);
|
||||
}
|
||||
@ -174,28 +151,6 @@ class AuthenticationNotifier extends StateNotifier<AuthenticationState> {
|
||||
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<AuthenticationNotifier, AuthenticationState>((ref) {
|
||||
return AuthenticationNotifier(
|
||||
ref.watch(deviceInfoServiceProvider),
|
||||
ref.watch(backupServiceProvider),
|
||||
ref.watch(apiServiceProvider),
|
||||
);
|
||||
});
|
||||
|
@ -151,6 +151,7 @@ enum StoreKey<T> {
|
||||
serverUrl<String>(10, type: String),
|
||||
accessToken<String>(11, type: String),
|
||||
serverEndpoint<String>(12, type: String),
|
||||
autoBackup<bool>(13, type: bool),
|
||||
// user settings from [AppSettingsEnum] below:
|
||||
loadPreview<bool>(100, type: bool),
|
||||
loadOriginal<bool>(101, type: bool),
|
||||
|
@ -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<String> resolveAndSetEndpoint(String serverUrl) async {
|
||||
|
Loading…
Reference in New Issue
Block a user