diff --git a/mobile-v2/lib/domain/repositories/api/user_api.repository.dart b/mobile-v2/lib/domain/repositories/api/user_api.repository.dart index c716984c5c..c9d6ce3081 100644 --- a/mobile-v2/lib/domain/repositories/api/user_api.repository.dart +++ b/mobile-v2/lib/domain/repositories/api/user_api.repository.dart @@ -11,13 +11,8 @@ class UserApiRepository with LogMixin implements IUserApiRepository { @override Future getMyUser() async { try { - final [ - userDto as UserAdminResponseDto?, - preferencesDto as UserPreferencesResponseDto? - ] = await Future.wait([ - _usersApi.getMyUser(), - _usersApi.getMyPreferences(), - ]); + final (userDto, preferencesDto) = + await (_usersApi.getMyUser(), _usersApi.getMyPreferences()).wait; if (userDto == null) { log.e("Cannot fetch my user."); diff --git a/mobile-v2/lib/domain/services/album_sync.service.dart b/mobile-v2/lib/domain/services/album_sync.service.dart index 75ca4030f8..711ae47421 100644 --- a/mobile-v2/lib/domain/services/album_sync.service.dart +++ b/mobile-v2/lib/domain/services/album_sync.service.dart @@ -1,3 +1,4 @@ +import 'package:async/async.dart'; import 'package:immich_mobile/domain/interfaces/album.interface.dart'; import 'package:immich_mobile/domain/interfaces/album_asset.interface.dart'; import 'package:immich_mobile/domain/interfaces/album_etag.interface.dart'; @@ -14,10 +15,13 @@ import 'package:immich_mobile/utils/isolate_helper.dart'; import 'package:immich_mobile/utils/mixins/log.mixin.dart'; class AlbumSyncService with LogMixin { - const AlbumSyncService(); + AlbumSyncService(); + + final _fullDeviceSyncCache = AsyncCache.ephemeral(); Future performFullDeviceSyncIsolate() async { - return await IsolateHelper.run(performFullDeviceSync); + return await _fullDeviceSyncCache + .fetch(() async => await IsolateHelper.run(performFullDeviceSync)); } Future performFullDeviceSync() async { diff --git a/mobile-v2/lib/domain/services/asset_sync.service.dart b/mobile-v2/lib/domain/services/asset_sync.service.dart index 98f21bf5b1..0a9cf95461 100644 --- a/mobile-v2/lib/domain/services/asset_sync.service.dart +++ b/mobile-v2/lib/domain/services/asset_sync.service.dart @@ -1,5 +1,6 @@ import 'dart:async'; +import 'package:async/async.dart'; import 'package:collection/collection.dart'; import 'package:immich_mobile/domain/interfaces/api/sync_api.interface.dart'; import 'package:immich_mobile/domain/interfaces/asset.interface.dart'; @@ -13,20 +14,24 @@ import 'package:immich_mobile/utils/isolate_helper.dart'; import 'package:immich_mobile/utils/mixins/log.mixin.dart'; class AssetSyncService with LogMixin { - const AssetSyncService(); + AssetSyncService(); + + final _fullRemoteSyncCache = AsyncCache.ephemeral(); Future performFullRemoteSyncIsolate( User user, { DateTime? updatedUtil, int? limit, }) async { - return await IsolateHelper.run(() async { - return await performFullRemoteSync( - user, - updatedUtil: updatedUtil, - limit: limit, - ); - }); + return await _fullRemoteSyncCache.fetch( + () async => await IsolateHelper.run(() async { + return await performFullRemoteSync( + user, + updatedUtil: updatedUtil, + limit: limit, + ); + }), + ); } Future performFullRemoteSync( diff --git a/mobile-v2/lib/domain/services/login.service.dart b/mobile-v2/lib/domain/services/login.service.dart index 5bfdef0635..72f0413df4 100644 --- a/mobile-v2/lib/domain/services/login.service.dart +++ b/mobile-v2/lib/domain/services/login.service.dart @@ -1,8 +1,6 @@ import 'dart:async'; -import 'dart:convert'; import 'dart:io'; -import 'package:flutter/foundation.dart'; import 'package:flutter_web_auth_2/flutter_web_auth_2.dart'; import 'package:http/http.dart'; import 'package:immich_mobile/domain/interfaces/album.interface.dart'; @@ -22,6 +20,7 @@ import 'package:immich_mobile/presentation/states/gallery_permission.state.dart' import 'package:immich_mobile/presentation/states/server_info.state.dart'; import 'package:immich_mobile/service_locator.dart'; import 'package:immich_mobile/utils/immich_api_client.dart'; +import 'package:immich_mobile/utils/isolate_helper.dart'; import 'package:immich_mobile/utils/mixins/log.mixin.dart'; // Cannot add dependency repos to constructor as this requires the newly registered API client from login @@ -59,7 +58,7 @@ class LoginService with LogMixin { ); if (res.statusCode == HttpStatus.ok) { - final data = await compute(jsonDecode, res.body); + final data = await IsolateHelper.decodeJson(res.bodyBytes); final endpoint = data['api']['endpoint'].toString(); // Full URL is relative to base diff --git a/mobile-v2/lib/presentation/states/server_info.state.dart b/mobile-v2/lib/presentation/states/server_info.state.dart index d2524812e4..6eb7656fb9 100644 --- a/mobile-v2/lib/presentation/states/server_info.state.dart +++ b/mobile-v2/lib/presentation/states/server_info.state.dart @@ -12,7 +12,7 @@ class ServerInfoProvider extends ValueNotifier { super(const ServerInfo.initial()); Future fetchFeatures() async => - await Future.wait([_getFeatures(), _getConfig(), _getVersion()]); + await (_getFeatures(), _getConfig(), _getVersion()).wait; Future _getFeatures() async { final features = await _serverApiRepository.getServerFeatures(); diff --git a/mobile-v2/lib/service_locator.dart b/mobile-v2/lib/service_locator.dart index 774c6ae37f..11d5634d09 100644 --- a/mobile-v2/lib/service_locator.dart +++ b/mobile-v2/lib/service_locator.dart @@ -138,8 +138,8 @@ abstract final class ServiceLocator { static void _registerServices() { /// Special services. So they are initiated as singletons _registerSingleton(ImHostService()); - _registerSingleton(const AlbumSyncService()); - _registerSingleton(const AssetSyncService()); + _registerSingleton(AlbumSyncService()); + _registerSingleton(AssetSyncService()); /// _registerFactory(() => const LoginService()); diff --git a/mobile-v2/lib/utils/isolate_helper.dart b/mobile-v2/lib/utils/isolate_helper.dart index 06cd4d8cef..d672ca6cbb 100644 --- a/mobile-v2/lib/utils/isolate_helper.dart +++ b/mobile-v2/lib/utils/isolate_helper.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'dart:convert'; import 'dart:isolate'; import 'dart:ui'; @@ -82,4 +83,11 @@ class IsolateHelper { } }); } + + static Future> decodeJson(Uint8List json) async { + return await Isolate.run( + () => const Utf8Decoder().fuse(const JsonDecoder()).convert(json) + as Map, + ); + } } diff --git a/mobile-v2/pubspec.yaml b/mobile-v2/pubspec.yaml index a0838a454d..775a298e44 100644 --- a/mobile-v2/pubspec.yaml +++ b/mobile-v2/pubspec.yaml @@ -36,6 +36,7 @@ dependencies: logging: ^1.3.0 # Collection Utils collection: ^1.18.0 + async: ^2.12.0 # service_locator get_it: ^8.0.0 # Photo Manager