1
0
mirror of https://github.com/immich-app/immich.git synced 2024-12-26 10:50:29 +02:00

fix(mobile): user get logged out upon clicking on any thing after logging in (#1808)

* fix(mobile): user get logged out upon clicking on any thing after logging in

* wip: fixing still

* fix: the actual issue

* Fix: avaialble album not updating UI
This commit is contained in:
Alex 2023-02-20 21:43:39 -06:00 committed by GitHub
parent 03d484aba2
commit 98998cccbc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 137 additions and 117 deletions

View File

@ -58,9 +58,7 @@ class BackupNotifier extends StateNotifier<BackUpState> {
fileType: '...', fileType: '...',
), ),
), ),
) { );
getBackupInfo();
}
final log = Logger('BackupNotifier'); final log = Logger('BackupNotifier');
final BackupService _backupService; final BackupService _backupService;
@ -128,55 +126,55 @@ class BackupNotifier extends StateNotifier<BackUpState> {
requireCharging != null || requireCharging != null ||
triggerDelay != null, triggerDelay != null,
); );
final bool wasEnabled = state.backgroundBackup; final bool wasEnabled = state.backgroundBackup;
final bool wasWifi = state.backupRequireWifi; final bool wasWifi = state.backupRequireWifi;
final bool wasCharging = state.backupRequireCharging; final bool wasCharging = state.backupRequireCharging;
final int oldTriggerDelay = state.backupTriggerDelay; final int oldTriggerDelay = state.backupTriggerDelay;
state = state.copyWith( state = state.copyWith(
backgroundBackup: enabled, backgroundBackup: enabled,
backupRequireWifi: requireWifi, backupRequireWifi: requireWifi,
backupRequireCharging: requireCharging, backupRequireCharging: requireCharging,
backupTriggerDelay: triggerDelay, backupTriggerDelay: triggerDelay,
); );
if (state.backgroundBackup) { if (state.backgroundBackup) {
bool success = true; bool success = true;
if (!wasEnabled) { if (!wasEnabled) {
if (!await _backgroundService.isIgnoringBatteryOptimizations()) { if (!await _backgroundService.isIgnoringBatteryOptimizations()) {
onBatteryInfo(); onBatteryInfo();
}
success &= await _backgroundService.enableService(immediate: true);
}
success &= success &&
await _backgroundService.configureService(
requireUnmetered: state.backupRequireWifi,
requireCharging: state.backupRequireCharging,
triggerUpdateDelay: state.backupTriggerDelay,
triggerMaxDelay: state.backupTriggerDelay * 10,
);
if (success) {
final box = Hive.box(backgroundBackupInfoBox);
await Future.wait([
box.put(backupRequireWifi, state.backupRequireWifi),
box.put(backupRequireCharging, state.backupRequireCharging),
box.put(backupTriggerDelay, state.backupTriggerDelay),
]);
} else {
state = state.copyWith(
backgroundBackup: wasEnabled,
backupRequireWifi: wasWifi,
backupRequireCharging: wasCharging,
backupTriggerDelay: oldTriggerDelay,
);
onError("backup_controller_page_background_configure_error");
}
} else {
final bool success = await _backgroundService.disableService();
if (!success) {
state = state.copyWith(backgroundBackup: wasEnabled);
onError("backup_controller_page_background_configure_error");
} }
success &= await _backgroundService.enableService(immediate: true);
} }
success &= success &&
await _backgroundService.configureService(
requireUnmetered: state.backupRequireWifi,
requireCharging: state.backupRequireCharging,
triggerUpdateDelay: state.backupTriggerDelay,
triggerMaxDelay: state.backupTriggerDelay * 10,
);
if (success) {
final box = Hive.box(backgroundBackupInfoBox);
await Future.wait([
box.put(backupRequireWifi, state.backupRequireWifi),
box.put(backupRequireCharging, state.backupRequireCharging),
box.put(backupTriggerDelay, state.backupTriggerDelay),
]);
} else {
state = state.copyWith(
backgroundBackup: wasEnabled,
backupRequireWifi: wasWifi,
backupRequireCharging: wasCharging,
backupTriggerDelay: oldTriggerDelay,
);
onError("backup_controller_page_background_configure_error");
}
} else {
final bool success = await _backgroundService.disableService();
if (!success) {
state = state.copyWith(backgroundBackup: wasEnabled);
onError("backup_controller_page_background_configure_error");
}
}
} }
/// ///
@ -460,6 +458,12 @@ class BackupNotifier extends StateNotifier<BackUpState> {
} }
} }
void setAvailableAlbums(availableAlbums) {
state = state.copyWith(
availableAlbums: availableAlbums,
);
}
void _onBackupError(ErrorUploadAsset errorAssetInfo) { void _onBackupError(ErrorUploadAsset errorAssetInfo) {
ref.watch(errorBackupListProvider.notifier).add(errorAssetInfo); ref.watch(errorBackupListProvider.notifier).add(errorAssetInfo);
} }
@ -573,7 +577,6 @@ class BackupNotifier extends StateNotifier<BackUpState> {
} }
Future<void> resumeBackup() async { Future<void> resumeBackup() async {
// assumes the background service is currently running // assumes the background service is currently running
// if true, waits until it has stopped to update the app state from HiveDB // if true, waits until it has stopped to update the app state from HiveDB
// before actually resuming backup by calling the internal `_resumeBackup` // before actually resuming backup by calling the internal `_resumeBackup`
@ -677,7 +680,6 @@ class BackupNotifier extends StateNotifier<BackUpState> {
_backgroundService.releaseLock(); _backgroundService.releaseLock();
} }
} }
} }
final backupProvider = final backupProvider =

View File

@ -5,7 +5,6 @@ import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:fluttertoast/fluttertoast.dart'; import 'package:fluttertoast/fluttertoast.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/constants/immich_colors.dart'; import 'package:immich_mobile/constants/immich_colors.dart';
import 'package:immich_mobile/modules/backup/models/available_album.model.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/modules/backup/ui/album_info_card.dart'; import 'package:immich_mobile/modules/backup/ui/album_info_card.dart';
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart'; import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
@ -19,20 +18,18 @@ class BackupAlbumSelectionPage extends HookConsumerWidget {
final selectedBackupAlbums = ref.watch(backupProvider).selectedBackupAlbums; final selectedBackupAlbums = ref.watch(backupProvider).selectedBackupAlbums;
final excludedBackupAlbums = ref.watch(backupProvider).excludedBackupAlbums; final excludedBackupAlbums = ref.watch(backupProvider).excludedBackupAlbums;
final isDarkTheme = Theme.of(context).brightness == Brightness.dark; final isDarkTheme = Theme.of(context).brightness == Brightness.dark;
final albums = useState<List<AvailableAlbum>>( final albums = ref.watch(backupProvider).availableAlbums;
ref.watch(backupProvider).availableAlbums,
);
useEffect( useEffect(
() { () {
ref.read(backupProvider.notifier).getBackupInfo(); ref.watch(backupProvider.notifier).getBackupInfo();
return null; return null;
}, },
[], [],
); );
buildAlbumSelectionList() { buildAlbumSelectionList() {
if (albums.value.isEmpty) { if (albums.isEmpty) {
return const Center( return const Center(
child: ImmichLoadingIndicator(), child: ImmichLoadingIndicator(),
); );
@ -42,17 +39,17 @@ class BackupAlbumSelectionPage extends HookConsumerWidget {
height: 265, height: 265,
child: ListView.builder( child: ListView.builder(
scrollDirection: Axis.horizontal, scrollDirection: Axis.horizontal,
itemCount: albums.value.length, itemCount: albums.length,
physics: const BouncingScrollPhysics(), physics: const BouncingScrollPhysics(),
itemBuilder: ((context, index) { itemBuilder: ((context, index) {
var thumbnailData = albums.value[index].thumbnailData; var thumbnailData = albums[index].thumbnailData;
return Padding( return Padding(
padding: index == 0 padding: index == 0
? const EdgeInsets.only(left: 16.00) ? const EdgeInsets.only(left: 16.00)
: const EdgeInsets.all(0), : const EdgeInsets.all(0),
child: AlbumInfoCard( child: AlbumInfoCard(
imageData: thumbnailData, imageData: thumbnailData,
albumInfo: albums.value[index], albumInfo: albums[index],
), ),
); );
}), }),
@ -142,7 +139,7 @@ class BackupAlbumSelectionPage extends HookConsumerWidget {
padding: const EdgeInsets.only(left: 16.0, right: 16, bottom: 8.0), padding: const EdgeInsets.only(left: 16.0, right: 16, bottom: 8.0),
child: TextFormField( child: TextFormField(
onChanged: (searchValue) { onChanged: (searchValue) {
albums.value = ref var avaialbleAlbums = ref
.watch(backupProvider) .watch(backupProvider)
.availableAlbums .availableAlbums
.where( .where(
@ -151,6 +148,10 @@ class BackupAlbumSelectionPage extends HookConsumerWidget {
.contains(searchValue.toLowerCase()), .contains(searchValue.toLowerCase()),
) )
.toList(); .toList();
ref
.read(backupProvider.notifier)
.setAvailableAlbums(avaialbleAlbums);
}, },
decoration: InputDecoration( decoration: InputDecoration(
contentPadding: const EdgeInsets.symmetric( contentPadding: const EdgeInsets.symmetric(

View File

@ -592,18 +592,23 @@ class BackupControllerPage extends HookConsumerWidget {
BackupInfoCard( BackupInfoCard(
title: "backup_controller_page_total".tr(), title: "backup_controller_page_total".tr(),
subtitle: "backup_controller_page_total_sub".tr(), subtitle: "backup_controller_page_total_sub".tr(),
info: "${backupState.allUniqueAssets.length}", info: ref.watch(backupProvider).availableAlbums.isEmpty
? "..."
: "${backupState.allUniqueAssets.length}",
), ),
BackupInfoCard( BackupInfoCard(
title: "backup_controller_page_backup".tr(), title: "backup_controller_page_backup".tr(),
subtitle: "backup_controller_page_backup_sub".tr(), subtitle: "backup_controller_page_backup_sub".tr(),
info: "${backupState.selectedAlbumsBackupAssetsIds.length}", info: ref.watch(backupProvider).availableAlbums.isEmpty
? "..."
: "${backupState.selectedAlbumsBackupAssetsIds.length}",
), ),
BackupInfoCard( BackupInfoCard(
title: "backup_controller_page_remainder".tr(), title: "backup_controller_page_remainder".tr(),
subtitle: "backup_controller_page_remainder_sub".tr(), subtitle: "backup_controller_page_remainder_sub".tr(),
info: info: ref.watch(backupProvider).availableAlbums.isEmpty
"${backupState.allUniqueAssets.length - backupState.selectedAlbumsBackupAssetsIds.length}", ? "..."
: "${backupState.allUniqueAssets.length - backupState.selectedAlbumsBackupAssetsIds.length}",
), ),
const Divider(), const Divider(),
buildAutoBackupController(), buildAutoBackupController(),

View File

@ -46,10 +46,10 @@ class HomePage extends HookConsumerWidget {
useEffect( useEffect(
() { () {
ref.read(websocketProvider.notifier).connect(); ref.watch(websocketProvider.notifier).connect();
ref.read(assetProvider.notifier).getAllAsset(); ref.watch(assetProvider.notifier).getAllAsset();
ref.read(albumProvider.notifier).getAllAlbums(); ref.watch(albumProvider.notifier).getAllAlbums();
ref.read(sharedAlbumProvider.notifier).getAllSharedAlbums(); ref.watch(sharedAlbumProvider.notifier).getAllSharedAlbums();
ref.watch(serverInfoProvider.notifier).getServerVersion(); ref.watch(serverInfoProvider.notifier).getServerVersion();
selectionEnabledHook.addListener(() { selectionEnabledHook.addListener(() {
@ -229,8 +229,8 @@ class HomePage extends HookConsumerWidget {
top: true, top: true,
child: Stack( child: Stack(
children: [ children: [
ref.watch(assetProvider).renderList == null ref.watch(assetProvider).renderList == null ||
|| ref.watch(assetProvider).allAssets.isEmpty ref.watch(assetProvider).allAssets.isEmpty
? buildLoadingIndicator() ? buildLoadingIndicator()
: ImmichAssetGrid( : ImmichAssetGrid(
renderList: ref.watch(assetProvider).renderList!, renderList: ref.watch(assetProvider).renderList!,

View File

@ -92,20 +92,25 @@ class AuthenticationNotifier extends StateNotifier<AuthenticationState> {
} }
Future<bool> logout() async { Future<bool> logout() async {
await Future.wait([ try {
_apiService.authenticationApi.logout(), await Future.wait([
Hive.box(userInfoBox).delete(accessTokenKey), _apiService.authenticationApi.logout(),
Store.delete(StoreKey.assetETag), Hive.box(userInfoBox).delete(accessTokenKey),
Store.delete(StoreKey.userRemoteId), Store.delete(StoreKey.assetETag),
_assetCacheService.invalidate(), Store.delete(StoreKey.userRemoteId),
_albumCacheService.invalidate(), _assetCacheService.invalidate(),
_sharedAlbumCacheService.invalidate(), _albumCacheService.invalidate(),
Hive.box<HiveSavedLoginInfo>(hiveLoginInfoBox).delete(savedLoginInfoKey) _sharedAlbumCacheService.invalidate(),
]); Hive.box<HiveSavedLoginInfo>(hiveLoginInfoBox).delete(savedLoginInfoKey)
]);
state = state.copyWith(isAuthenticated: false); state = state.copyWith(isAuthenticated: false);
return true; return true;
} catch (e) {
debugPrint("Error logging out $e");
return false;
}
} }
setAutoBackup(bool backupState) async { setAutoBackup(bool backupState) async {

View File

@ -68,7 +68,28 @@ class ChangePasswordForm extends HookConsumerWidget {
), ),
ChangePasswordButton( ChangePasswordButton(
passwordController: passwordController, passwordController: passwordController,
formKey: formKey, onPressed: () async {
if (formKey.currentState!.validate()) {
var isSuccess = await ref
.read(authenticationProvider.notifier)
.changePassword(passwordController.value.text);
if (isSuccess) {
bool res = await ref
.read(authenticationProvider.notifier)
.logout();
if (res) {
ref.read(backupProvider.notifier).cancelBackup();
ref.read(assetProvider.notifier).clearAllAsset();
ref.read(websocketProvider.notifier).disconnect();
AutoRouter.of(context)
.replace(const LoginRoute());
}
}
}
},
), ),
], ],
), ),
@ -122,7 +143,7 @@ class ConfirmPasswordInput extends StatelessWidget {
return TextFormField( return TextFormField(
obscureText: true, obscureText: true,
controller: confirmController, controller: confirmController,
decoration: InputDecoration( decoration: InputDecoration(
labelText: 'change_password_form_confirm_password'.tr(), labelText: 'change_password_form_confirm_password'.tr(),
hintText: 'change_password_form_reenter_new_password'.tr(), hintText: 'change_password_form_reenter_new_password'.tr(),
border: const OutlineInputBorder(), border: const OutlineInputBorder(),
@ -135,12 +156,11 @@ class ConfirmPasswordInput extends StatelessWidget {
class ChangePasswordButton extends ConsumerWidget { class ChangePasswordButton extends ConsumerWidget {
final TextEditingController passwordController; final TextEditingController passwordController;
final GlobalKey<FormState> formKey; final VoidCallback onPressed;
const ChangePasswordButton({ const ChangePasswordButton({
Key? key, Key? key,
required this.passwordController, required this.passwordController,
required this.formKey, required this.onPressed,
}) : super(key: key); }) : super(key: key);
@override @override
@ -153,25 +173,7 @@ class ChangePasswordButton extends ConsumerWidget {
elevation: 2, elevation: 2,
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 25), padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 25),
), ),
onPressed: () async { onPressed: onPressed,
if (formKey.currentState!.validate()) {
var isSuccess = await ref
.watch(authenticationProvider.notifier)
.changePassword(passwordController.value.text);
if (isSuccess) {
bool res =
await ref.watch(authenticationProvider.notifier).logout();
if (res) {
ref.watch(backupProvider.notifier).cancelBackup();
ref.watch(assetProvider.notifier).clearAllAsset();
ref.watch(websocketProvider.notifier).disconnect();
AutoRouter.of(context).replace(const LoginRoute());
}
}
}
},
child: Text( child: Text(
'common_change_password'.tr(), 'common_change_password'.tr(),
style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold), style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold),

View File

@ -298,10 +298,10 @@ class LoginButton extends ConsumerWidget {
), ),
onPressed: () async { onPressed: () async {
// This will remove current cache asset state of previous user login. // This will remove current cache asset state of previous user login.
ref.watch(assetProvider.notifier).clearAllAsset(); ref.read(assetProvider.notifier).clearAllAsset();
var isAuthenticated = var isAuthenticated =
await ref.watch(authenticationProvider.notifier).login( await ref.read(authenticationProvider.notifier).login(
emailController.text, emailController.text,
passwordController.text, passwordController.text,
serverEndpointController.text, serverEndpointController.text,
@ -309,12 +309,11 @@ class LoginButton extends ConsumerWidget {
if (isAuthenticated) { if (isAuthenticated) {
// Resume backup (if enable) then navigate // Resume backup (if enable) then navigate
if (ref.read(authenticationProvider).shouldChangePassword &&
if (ref.watch(authenticationProvider).shouldChangePassword && !ref.read(authenticationProvider).isAdmin) {
!ref.watch(authenticationProvider).isAdmin) {
AutoRouter.of(context).push(const ChangePasswordRoute()); AutoRouter.of(context).push(const ChangePasswordRoute());
} else { } else {
ref.watch(backupProvider.notifier).resumeBackup(); ref.read(backupProvider.notifier).resumeBackup();
AutoRouter.of(context).replace(const TabControllerRoute()); AutoRouter.of(context).replace(const TabControllerRoute());
} }
} else { } else {

View File

@ -1,5 +1,7 @@
import 'package:auto_route/auto_route.dart'; import 'package:auto_route/auto_route.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:hive/hive.dart';
import 'package:immich_mobile/constants/hive_box.dart';
import 'package:immich_mobile/routing/router.dart'; import 'package:immich_mobile/routing/router.dart';
import 'package:immich_mobile/shared/services/api.service.dart'; import 'package:immich_mobile/shared/services/api.service.dart';
@ -9,6 +11,9 @@ class AuthGuard extends AutoRouteGuard {
@override @override
void onNavigation(NavigationResolver resolver, StackRouter router) async { void onNavigation(NavigationResolver resolver, StackRouter router) async {
try { try {
var userInfoHiveBox = await Hive.openBox(userInfoBox);
var accessToken = userInfoHiveBox.get(accessTokenKey);
_apiService.setAccessToken(accessToken);
var res = await _apiService.authenticationApi.validateAccessToken(); var res = await _apiService.authenticationApi.validateAccessToken();
if (res != null && res.authStatus) { if (res != null && res.authStatus) {

View File

@ -46,6 +46,7 @@ class AssetService {
); );
} catch (e, stack) { } catch (e, stack) {
log.severe('Error while getting remote assets', e, stack); log.severe('Error while getting remote assets', e, stack);
debugPrint("[ERROR] [getRemoteAssets] $e");
return Pair(null, etag); return Pair(null, etag);
} }
} }

View File

@ -375,10 +375,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: flutter_hooks name: flutter_hooks
sha256: "2b202559a4ed3656bbb7aae9d8b335fb0037b23acc7ae3f377d1ba0b95c21aec" sha256: "6a126f703b89499818d73305e4ce1e3de33b4ae1c5512e3b8eab4b986f46774c"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.18.5+1" version: "0.18.6"
flutter_launcher_icons: flutter_launcher_icons:
dependency: "direct dev" dependency: "direct dev"
description: description:

View File

@ -14,8 +14,8 @@ dependencies:
path_provider_ios: path_provider_ios:
photo_manager: ^2.5.0 photo_manager: ^2.5.0
flutter_hooks: ^0.18.0 flutter_hooks: ^0.18.6
hooks_riverpod: ^2.0.0-dev.0 hooks_riverpod: ^2.2.0
hive: ^2.2.1 hive: ^2.2.1
hive_flutter: ^1.1.0 hive_flutter: ^1.1.0
cached_network_image: ^3.2.2 cached_network_image: ^3.2.2