mirror of
				https://github.com/KevinMidboe/immich.git
				synced 2025-10-29 17:40:28 +00:00 
			
		
		
		
	fix(mobile): freeze on splash screen due to accessing bad state (#998)
This commit is contained in:
		@@ -90,6 +90,7 @@ class AuthenticationNotifier extends StateNotifier<AuthenticationState> {
 | 
			
		||||
 | 
			
		||||
      return setSuccessLoginInfo(
 | 
			
		||||
        accessToken: loginResponse.accessToken,
 | 
			
		||||
        serverUrl: serverEndpoint,
 | 
			
		||||
        isSavedLoginInfo: isSavedLoginInfo,
 | 
			
		||||
      );
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
@@ -159,16 +160,18 @@ class AuthenticationNotifier extends StateNotifier<AuthenticationState> {
 | 
			
		||||
 | 
			
		||||
  Future<bool> setSuccessLoginInfo({
 | 
			
		||||
    required String accessToken,
 | 
			
		||||
    required String serverUrl,
 | 
			
		||||
    required bool isSavedLoginInfo,
 | 
			
		||||
  }) async {
 | 
			
		||||
    Hive.box(userInfoBox).put(accessTokenKey, accessToken);
 | 
			
		||||
 | 
			
		||||
    _apiService.setAccessToken(accessToken);
 | 
			
		||||
    var userResponseDto = await _apiService.userApi.getMyUserInfo();
 | 
			
		||||
 | 
			
		||||
    if (userResponseDto != null) {
 | 
			
		||||
      var userInfoHiveBox = await Hive.openBox(userInfoBox);
 | 
			
		||||
      var deviceInfo = await _deviceInfoService.getDeviceInfo();
 | 
			
		||||
      Hive.box(userInfoBox).put(deviceIdKey, deviceInfo["deviceId"]);
 | 
			
		||||
      userInfoHiveBox.put(deviceIdKey, deviceInfo["deviceId"]);
 | 
			
		||||
      userInfoHiveBox.put(accessTokenKey, accessToken);
 | 
			
		||||
      userInfoHiveBox.put(serverEndpointKey, serverUrl);
 | 
			
		||||
 | 
			
		||||
      state = state.copyWith(
 | 
			
		||||
        isAuthenticated: true,
 | 
			
		||||
@@ -191,7 +194,7 @@ class AuthenticationNotifier extends StateNotifier<AuthenticationState> {
 | 
			
		||||
            email: "",
 | 
			
		||||
            password: "",
 | 
			
		||||
            isSaveLogin: true,
 | 
			
		||||
            serverUrl: Hive.box(userInfoBox).get(serverEndpointKey),
 | 
			
		||||
            serverUrl: serverUrl,
 | 
			
		||||
            accessToken: accessToken,
 | 
			
		||||
          ),
 | 
			
		||||
        );
 | 
			
		||||
 
 | 
			
		||||
@@ -380,6 +380,7 @@ class OAuthLoginButton extends ConsumerWidget {
 | 
			
		||||
              .setSuccessLoginInfo(
 | 
			
		||||
                accessToken: loginResponseDto.accessToken,
 | 
			
		||||
                isSavedLoginInfo: isSavedLoginInfo,
 | 
			
		||||
                serverUrl: serverEndpointController.text,
 | 
			
		||||
              );
 | 
			
		||||
 | 
			
		||||
          if (isSuccess) {
 | 
			
		||||
 
 | 
			
		||||
@@ -20,14 +20,17 @@ class SplashScreenPage extends HookConsumerWidget {
 | 
			
		||||
        Hive.box<HiveSavedLoginInfo>(hiveLoginInfoBox).get(savedLoginInfoKey);
 | 
			
		||||
 | 
			
		||||
    void performLoggingIn() async {
 | 
			
		||||
      try {
 | 
			
		||||
        if (loginInfo != null) {
 | 
			
		||||
          // Make sure API service is initialized
 | 
			
		||||
          apiService.setEndpoint(loginInfo.serverUrl);
 | 
			
		||||
 | 
			
		||||
        var isSuccess =
 | 
			
		||||
            await ref.read(authenticationProvider.notifier).setSuccessLoginInfo(
 | 
			
		||||
          var isSuccess = await ref
 | 
			
		||||
              .read(authenticationProvider.notifier)
 | 
			
		||||
              .setSuccessLoginInfo(
 | 
			
		||||
                accessToken: loginInfo.accessToken,
 | 
			
		||||
                isSavedLoginInfo: true,
 | 
			
		||||
                serverUrl: loginInfo.serverUrl,
 | 
			
		||||
              );
 | 
			
		||||
          if (isSuccess) {
 | 
			
		||||
            // Resume backup (if enable) then navigate
 | 
			
		||||
@@ -37,6 +40,9 @@ class SplashScreenPage extends HookConsumerWidget {
 | 
			
		||||
            AutoRouter.of(context).replace(const LoginRoute());
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      } catch (_) {
 | 
			
		||||
        AutoRouter.of(context).replace(const LoginRoute());
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    useEffect(
 | 
			
		||||
 
 | 
			
		||||
@@ -79,7 +79,9 @@ class AssetResponseDto {
 | 
			
		||||
  String? livePhotoVideoId;
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  bool operator ==(Object other) => identical(this, other) || other is AssetResponseDto &&
 | 
			
		||||
  bool operator ==(Object other) =>
 | 
			
		||||
      identical(this, other) ||
 | 
			
		||||
      other is AssetResponseDto &&
 | 
			
		||||
          other.type == type &&
 | 
			
		||||
          other.id == id &&
 | 
			
		||||
          other.deviceAssetId == deviceAssetId &&
 | 
			
		||||
@@ -120,7 +122,8 @@ class AssetResponseDto {
 | 
			
		||||
      (livePhotoVideoId == null ? 0 : livePhotoVideoId!.hashCode);
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  String toString() => 'AssetResponseDto[type=$type, id=$id, deviceAssetId=$deviceAssetId, ownerId=$ownerId, deviceId=$deviceId, originalPath=$originalPath, resizePath=$resizePath, createdAt=$createdAt, modifiedAt=$modifiedAt, isFavorite=$isFavorite, mimeType=$mimeType, duration=$duration, webpPath=$webpPath, encodedVideoPath=$encodedVideoPath, exifInfo=$exifInfo, smartInfo=$smartInfo, livePhotoVideoId=$livePhotoVideoId]';
 | 
			
		||||
  String toString() =>
 | 
			
		||||
      'AssetResponseDto[type=$type, id=$id, deviceAssetId=$deviceAssetId, ownerId=$ownerId, deviceId=$deviceId, originalPath=$originalPath, resizePath=$resizePath, createdAt=$createdAt, modifiedAt=$modifiedAt, isFavorite=$isFavorite, mimeType=$mimeType, duration=$duration, webpPath=$webpPath, encodedVideoPath=$encodedVideoPath, exifInfo=$exifInfo, smartInfo=$smartInfo, livePhotoVideoId=$livePhotoVideoId]';
 | 
			
		||||
 | 
			
		||||
  Map<String, dynamic> toJson() {
 | 
			
		||||
    final _json = <String, dynamic>{};
 | 
			
		||||
@@ -182,13 +185,13 @@ class AssetResponseDto {
 | 
			
		||||
      // Ensure that the map contains the required keys.
 | 
			
		||||
      // Note 1: the values aren't checked for validity beyond being non-null.
 | 
			
		||||
      // Note 2: this code is stripped in release mode!
 | 
			
		||||
      assert(() {
 | 
			
		||||
        requiredKeys.forEach((key) {
 | 
			
		||||
          assert(json.containsKey(key), 'Required key "AssetResponseDto[$key]" is missing from JSON.');
 | 
			
		||||
          assert(json[key] != null, 'Required key "AssetResponseDto[$key]" has a null value in JSON.');
 | 
			
		||||
        });
 | 
			
		||||
        return true;
 | 
			
		||||
      }());
 | 
			
		||||
      // assert(() {
 | 
			
		||||
      //   requiredKeys.forEach((key) {
 | 
			
		||||
      //     assert(json.containsKey(key), 'Required key "AssetResponseDto[$key]" is missing from JSON.');
 | 
			
		||||
      //     assert(json[key] != null, 'Required key "AssetResponseDto[$key]" has a null value in JSON.');
 | 
			
		||||
      //   });
 | 
			
		||||
      //   return true;
 | 
			
		||||
      // }());
 | 
			
		||||
 | 
			
		||||
      return AssetResponseDto(
 | 
			
		||||
        type: AssetTypeEnum.fromJson(json[r'type'])!,
 | 
			
		||||
@@ -213,7 +216,10 @@ class AssetResponseDto {
 | 
			
		||||
    return null;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static List<AssetResponseDto>? listFromJson(dynamic json, {bool growable = false,}) {
 | 
			
		||||
  static List<AssetResponseDto>? listFromJson(
 | 
			
		||||
    dynamic json, {
 | 
			
		||||
    bool growable = false,
 | 
			
		||||
  }) {
 | 
			
		||||
    final result = <AssetResponseDto>[];
 | 
			
		||||
    if (json is List && json.isNotEmpty) {
 | 
			
		||||
      for (final row in json) {
 | 
			
		||||
@@ -241,12 +247,18 @@ class AssetResponseDto {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // maps a json object with a list of AssetResponseDto-objects as value to a dart map
 | 
			
		||||
  static Map<String, List<AssetResponseDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
 | 
			
		||||
  static Map<String, List<AssetResponseDto>> mapListFromJson(
 | 
			
		||||
    dynamic json, {
 | 
			
		||||
    bool growable = false,
 | 
			
		||||
  }) {
 | 
			
		||||
    final map = <String, List<AssetResponseDto>>{};
 | 
			
		||||
    if (json is Map && json.isNotEmpty) {
 | 
			
		||||
      json = json.cast<String, dynamic>(); // ignore: parameter_assignments
 | 
			
		||||
      for (final entry in json.entries) {
 | 
			
		||||
        final value = AssetResponseDto.listFromJson(entry.value, growable: growable,);
 | 
			
		||||
        final value = AssetResponseDto.listFromJson(
 | 
			
		||||
          entry.value,
 | 
			
		||||
          growable: growable,
 | 
			
		||||
        );
 | 
			
		||||
        if (value != null) {
 | 
			
		||||
          map[entry.key] = value;
 | 
			
		||||
        }
 | 
			
		||||
@@ -274,4 +286,3 @@ class AssetResponseDto {
 | 
			
		||||
    'livePhotoVideoId',
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -43,7 +43,9 @@ class UserResponseDto {
 | 
			
		||||
  DateTime? deletedAt;
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  bool operator ==(Object other) => identical(this, other) || other is UserResponseDto &&
 | 
			
		||||
  bool operator ==(Object other) =>
 | 
			
		||||
      identical(this, other) ||
 | 
			
		||||
      other is UserResponseDto &&
 | 
			
		||||
          other.id == id &&
 | 
			
		||||
          other.email == email &&
 | 
			
		||||
          other.firstName == firstName &&
 | 
			
		||||
@@ -68,7 +70,8 @@ class UserResponseDto {
 | 
			
		||||
      (deletedAt == null ? 0 : deletedAt!.hashCode);
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  String toString() => 'UserResponseDto[id=$id, email=$email, firstName=$firstName, lastName=$lastName, createdAt=$createdAt, profileImagePath=$profileImagePath, shouldChangePassword=$shouldChangePassword, isAdmin=$isAdmin, deletedAt=$deletedAt]';
 | 
			
		||||
  String toString() =>
 | 
			
		||||
      'UserResponseDto[id=$id, email=$email, firstName=$firstName, lastName=$lastName, createdAt=$createdAt, profileImagePath=$profileImagePath, shouldChangePassword=$shouldChangePassword, isAdmin=$isAdmin, deletedAt=$deletedAt]';
 | 
			
		||||
 | 
			
		||||
  Map<String, dynamic> toJson() {
 | 
			
		||||
    final _json = <String, dynamic>{};
 | 
			
		||||
@@ -98,13 +101,13 @@ class UserResponseDto {
 | 
			
		||||
      // Ensure that the map contains the required keys.
 | 
			
		||||
      // Note 1: the values aren't checked for validity beyond being non-null.
 | 
			
		||||
      // Note 2: this code is stripped in release mode!
 | 
			
		||||
      assert(() {
 | 
			
		||||
        requiredKeys.forEach((key) {
 | 
			
		||||
          assert(json.containsKey(key), 'Required key "UserResponseDto[$key]" is missing from JSON.');
 | 
			
		||||
          assert(json[key] != null, 'Required key "UserResponseDto[$key]" has a null value in JSON.');
 | 
			
		||||
        });
 | 
			
		||||
        return true;
 | 
			
		||||
      }());
 | 
			
		||||
      // assert(() {
 | 
			
		||||
      //   requiredKeys.forEach((key) {
 | 
			
		||||
      //     assert(json.containsKey(key), 'Required key "UserResponseDto[$key]" is missing from JSON.');
 | 
			
		||||
      //     assert(json[key] != null, 'Required key "UserResponseDto[$key]" has a null value in JSON.');
 | 
			
		||||
      //   });
 | 
			
		||||
      //   return true;
 | 
			
		||||
      // }());
 | 
			
		||||
 | 
			
		||||
      return UserResponseDto(
 | 
			
		||||
        id: mapValueOfType<String>(json, r'id')!,
 | 
			
		||||
@@ -113,7 +116,8 @@ class UserResponseDto {
 | 
			
		||||
        lastName: mapValueOfType<String>(json, r'lastName')!,
 | 
			
		||||
        createdAt: mapValueOfType<String>(json, r'createdAt')!,
 | 
			
		||||
        profileImagePath: mapValueOfType<String>(json, r'profileImagePath')!,
 | 
			
		||||
        shouldChangePassword: mapValueOfType<bool>(json, r'shouldChangePassword')!,
 | 
			
		||||
        shouldChangePassword:
 | 
			
		||||
            mapValueOfType<bool>(json, r'shouldChangePassword')!,
 | 
			
		||||
        isAdmin: mapValueOfType<bool>(json, r'isAdmin')!,
 | 
			
		||||
        deletedAt: mapDateTime(json, r'deletedAt', ''),
 | 
			
		||||
      );
 | 
			
		||||
@@ -121,7 +125,10 @@ class UserResponseDto {
 | 
			
		||||
    return null;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static List<UserResponseDto>? listFromJson(dynamic json, {bool growable = false,}) {
 | 
			
		||||
  static List<UserResponseDto>? listFromJson(
 | 
			
		||||
    dynamic json, {
 | 
			
		||||
    bool growable = false,
 | 
			
		||||
  }) {
 | 
			
		||||
    final result = <UserResponseDto>[];
 | 
			
		||||
    if (json is List && json.isNotEmpty) {
 | 
			
		||||
      for (final row in json) {
 | 
			
		||||
@@ -149,12 +156,18 @@ class UserResponseDto {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // maps a json object with a list of UserResponseDto-objects as value to a dart map
 | 
			
		||||
  static Map<String, List<UserResponseDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
 | 
			
		||||
  static Map<String, List<UserResponseDto>> mapListFromJson(
 | 
			
		||||
    dynamic json, {
 | 
			
		||||
    bool growable = false,
 | 
			
		||||
  }) {
 | 
			
		||||
    final map = <String, List<UserResponseDto>>{};
 | 
			
		||||
    if (json is Map && json.isNotEmpty) {
 | 
			
		||||
      json = json.cast<String, dynamic>(); // ignore: parameter_assignments
 | 
			
		||||
      for (final entry in json.entries) {
 | 
			
		||||
        final value = UserResponseDto.listFromJson(entry.value, growable: growable,);
 | 
			
		||||
        final value = UserResponseDto.listFromJson(
 | 
			
		||||
          entry.value,
 | 
			
		||||
          growable: growable,
 | 
			
		||||
        );
 | 
			
		||||
        if (value != null) {
 | 
			
		||||
          map[entry.key] = value;
 | 
			
		||||
        }
 | 
			
		||||
@@ -176,4 +189,3 @@ class UserResponseDto {
 | 
			
		||||
    'deletedAt',
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user