diff --git a/mobile/lib/modules/backup/providers/manual_upload.provider.dart b/mobile/lib/modules/backup/providers/manual_upload.provider.dart index 6d585e289ac9e..4d643b9a1660c 100644 --- a/mobile/lib/modules/backup/providers/manual_upload.provider.dart +++ b/mobile/lib/modules/backup/providers/manual_upload.provider.dart @@ -274,7 +274,7 @@ class ManualUploadNotifier extends StateNotifier { // The app is currently in background. Perform the necessary cleanups which // are on-hold for upload completion if (appState != AppStateEnum.active && appState != AppStateEnum.resumed) { - ref.read(appStateProvider.notifier).handleAppInactivity(); + ref.read(backupProvider.notifier).cancelBackup(); } } diff --git a/mobile/lib/shared/providers/app_state.provider.dart b/mobile/lib/shared/providers/app_state.provider.dart index d2d3f1e1e5bf5..44fff2c07fe64 100644 --- a/mobile/lib/shared/providers/app_state.provider.dart +++ b/mobile/lib/shared/providers/app_state.provider.dart @@ -28,13 +28,10 @@ enum AppStateEnum { } class AppStateNotiifer extends StateNotifier { - final Ref ref; + final Ref _ref; + bool _wasPaused = false; - AppStateNotiifer(this.ref) : super(AppStateEnum.active); - - void updateAppState(AppStateEnum appState) { - state = appState; - } + AppStateNotiifer(this._ref) : super(AppStateEnum.active); AppStateEnum getAppState() { return state; @@ -43,65 +40,72 @@ class AppStateNotiifer extends StateNotifier { void handleAppResume() { state = AppStateEnum.resumed; - var isAuthenticated = ref.watch(authenticationProvider).isAuthenticated; - final permission = ref.watch(galleryPermissionNotifier); + // no need to resume because app was never really paused + if (!_wasPaused) return; + _wasPaused = false; + + final isAuthenticated = _ref.read(authenticationProvider).isAuthenticated; + final permission = _ref.read(galleryPermissionNotifier); // Needs to be logged in and have gallery permissions if (isAuthenticated && (permission.isGranted || permission.isLimited)) { - ref.read(backupProvider.notifier).resumeBackup(); - ref.read(backgroundServiceProvider).resumeServiceIfEnabled(); - ref.read(serverInfoProvider.notifier).getServerVersion(); - switch (ref.read(tabProvider)) { + _ref.read(backupProvider.notifier).resumeBackup(); + _ref.read(backgroundServiceProvider).resumeServiceIfEnabled(); + _ref.read(serverInfoProvider.notifier).getServerVersion(); + switch (_ref.read(tabProvider)) { case TabEnum.home: - ref.read(assetProvider.notifier).getAllAsset(); - ref.read(assetProvider.notifier).getPartnerAssets(); + _ref.read(assetProvider.notifier).getAllAsset(); + _ref.read(assetProvider.notifier).getPartnerAssets(); case TabEnum.search: // nothing to do case TabEnum.sharing: - ref.read(assetProvider.notifier).getPartnerAssets(); - ref.read(sharedAlbumProvider.notifier).getAllSharedAlbums(); + _ref.read(assetProvider.notifier).getPartnerAssets(); + _ref.read(sharedAlbumProvider.notifier).getAllSharedAlbums(); case TabEnum.library: - ref.read(albumProvider.notifier).getAllAlbums(); + _ref.read(albumProvider.notifier).getAllAlbums(); } } - ref.watch(websocketProvider.notifier).connect(); + _ref.read(websocketProvider.notifier).connect(); - ref.watch(releaseInfoProvider.notifier).checkGithubReleaseInfo(); + _ref.read(releaseInfoProvider.notifier).checkGithubReleaseInfo(); - ref - .watch(notificationPermissionProvider.notifier) + _ref + .read(notificationPermissionProvider.notifier) .getNotificationPermission(); - ref.watch(galleryPermissionNotifier.notifier).getGalleryPermissionStatus(); + _ref.read(galleryPermissionNotifier.notifier).getGalleryPermissionStatus(); - ref.read(iOSBackgroundSettingsProvider.notifier).refresh(); + _ref.read(iOSBackgroundSettingsProvider.notifier).refresh(); - ref.invalidate(memoryFutureProvider); + _ref.invalidate(memoryFutureProvider); } void handleAppInactivity() { state = AppStateEnum.inactive; - - // Do not handle inactivity if manual upload is in progress - if (ref.watch(backupProvider.notifier).backupProgress != - BackUpProgressEnum.manualInProgress) { - ImmichLogger().flush(); - ref.read(websocketProvider.notifier).disconnect(); - ref.read(backupProvider.notifier).cancelBackup(); - } + // do not stop/clean up anything on inactivity: issued on every orientation change } void handleAppPause() { state = AppStateEnum.paused; + _wasPaused = true; + // Do not cancel backup if manual upload is in progress + if (_ref.read(backupProvider.notifier).backupProgress != + BackUpProgressEnum.manualInProgress) { + _ref.read(backupProvider.notifier).cancelBackup(); + } + _ref.read(websocketProvider.notifier).disconnect(); + ImmichLogger().flush(); } void handleAppDetached() { state = AppStateEnum.detached; - ref.watch(manualUploadProvider.notifier).cancelBackup(); + // no guarantee this is called at all + _ref.read(manualUploadProvider.notifier).cancelBackup(); } void handleAppHidden() { state = AppStateEnum.hidden; + // do not stop/clean up anything on inactivity: issued on every orientation change } } diff --git a/mobile/lib/shared/providers/websocket.provider.dart b/mobile/lib/shared/providers/websocket.provider.dart index 83fcb000fe7dc..f49bc668685cb 100644 --- a/mobile/lib/shared/providers/websocket.provider.dart +++ b/mobile/lib/shared/providers/websocket.provider.dart @@ -63,21 +63,19 @@ class WebsocketState { } class WebsocketNotifier extends StateNotifier { - WebsocketNotifier(this.ref) + WebsocketNotifier(this._ref) : super( WebsocketState(socket: null, isConnected: false, pendingChanges: []), - ) { - debounce = Debounce( - const Duration(milliseconds: 500), - ); - } + ); - final log = Logger('WebsocketNotifier'); - final Ref ref; - late final Debounce debounce; + final _log = Logger('WebsocketNotifier'); + final Ref _ref; + final Debounce _debounce = Debounce(const Duration(milliseconds: 500)); - connect() { - var authenticationState = ref.read(authenticationProvider); + /// Connects websocket to server unless already connected + void connect() { + if (state.isConnected) return; + final authenticationState = _ref.read(authenticationProvider); if (authenticationState.isAuthenticated) { final accessToken = Store.get(StoreKey.accessToken); @@ -118,7 +116,7 @@ class WebsocketNotifier extends StateNotifier { }); socket.on('error', (errorMessage) { - log.severe("Websocket Error - $errorMessage"); + _log.severe("Websocket Error - $errorMessage"); state = WebsocketState( isConnected: false, socket: null, @@ -138,7 +136,7 @@ class WebsocketNotifier extends StateNotifier { } } - disconnect() { + void disconnect() { debugPrint("Attempting to disconnect from websocket"); var socket = state.socket?.disconnect(); @@ -152,30 +150,30 @@ class WebsocketNotifier extends StateNotifier { } } - stopListenToEvent(String eventName) { + void stopListenToEvent(String eventName) { debugPrint("Stop listening to event $eventName"); state.socket?.off(eventName); } - listenUploadEvent() { + void listenUploadEvent() { debugPrint("Start listening to event on_upload_success"); state.socket?.on('on_upload_success', _handleOnUploadSuccess); } - addPendingChange(PendingAction action, dynamic value) { + void addPendingChange(PendingAction action, dynamic value) { state = state.copyWith( pendingChanges: [...state.pendingChanges, PendingChange(action, value)], ); } - handlePendingChanges() { + void handlePendingChanges() { final deleteChanges = state.pendingChanges .where((c) => c.action == PendingAction.assetDelete) .toList(); if (deleteChanges.isNotEmpty) { List remoteIds = deleteChanges.map((a) => a.value.toString()).toList(); - ref.read(syncServiceProvider).handleRemoteAssetRemoval(remoteIds); + _ref.read(syncServiceProvider).handleRemoteAssetRemoval(remoteIds); state = state.copyWith( pendingChanges: state.pendingChanges .where((c) => c.action != PendingAction.assetDelete) @@ -184,27 +182,27 @@ class WebsocketNotifier extends StateNotifier { } } - _handleOnUploadSuccess(dynamic data) { + void _handleOnUploadSuccess(dynamic data) { final dto = AssetResponseDto.fromJson(data); if (dto != null) { final newAsset = Asset.remote(dto); - ref.watch(assetProvider.notifier).onNewAssetUploaded(newAsset); + _ref.watch(assetProvider.notifier).onNewAssetUploaded(newAsset); } } - _handleOnConfigUpdate(dynamic _) { - ref.read(serverInfoProvider.notifier).getServerFeatures(); - ref.read(serverInfoProvider.notifier).getServerConfig(); + void _handleOnConfigUpdate(dynamic _) { + _ref.read(serverInfoProvider.notifier).getServerFeatures(); + _ref.read(serverInfoProvider.notifier).getServerConfig(); } // Refresh updated assets - _handleServerUpdates(dynamic _) { - ref.read(assetProvider.notifier).getAllAsset(); + void _handleServerUpdates(dynamic _) { + _ref.read(assetProvider.notifier).getAllAsset(); } - _handleOnAssetDelete(dynamic data) { + void _handleOnAssetDelete(dynamic data) { addPendingChange(PendingAction.assetDelete, data); - debounce(handlePendingChanges); + _debounce(handlePendingChanges); } }