mirror of
https://github.com/immich-app/immich.git
synced 2025-12-29 17:25:00 +03:00
refactor(mobile): move user service to domain (#16782)
* refactor: user entity * chore: rebase fixes * refactor(mobile): move user service to domain * fix: timeline not visible on album selection page --------- Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
This commit is contained in:
@@ -28,12 +28,10 @@ import 'package:immich_mobile/repositories/asset.repository.dart';
|
||||
import 'package:immich_mobile/repositories/backup.repository.dart';
|
||||
import 'package:immich_mobile/services/entity.service.dart';
|
||||
import 'package:immich_mobile/services/sync.service.dart';
|
||||
import 'package:immich_mobile/services/user.service.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
|
||||
final albumServiceProvider = Provider(
|
||||
(ref) => AlbumService(
|
||||
ref.watch(userServiceProvider),
|
||||
ref.watch(syncServiceProvider),
|
||||
ref.watch(entityServiceProvider),
|
||||
ref.watch(albumRepositoryProvider),
|
||||
@@ -45,7 +43,6 @@ final albumServiceProvider = Provider(
|
||||
);
|
||||
|
||||
class AlbumService {
|
||||
final UserService _userService;
|
||||
final SyncService _syncService;
|
||||
final EntityService _entityService;
|
||||
final IAlbumRepository _albumRepository;
|
||||
@@ -58,7 +55,6 @@ class AlbumService {
|
||||
Completer<bool> _remoteCompleter = Completer()..complete(false);
|
||||
|
||||
AlbumService(
|
||||
this._userService,
|
||||
this._syncService,
|
||||
this._entityService,
|
||||
this._albumRepository,
|
||||
@@ -171,7 +167,7 @@ class AlbumService {
|
||||
final Stopwatch sw = Stopwatch()..start();
|
||||
bool changes = false;
|
||||
try {
|
||||
final users = await _userService.getUsersFromServer();
|
||||
final users = await _syncService.getUsersFromServer();
|
||||
if (users != null) {
|
||||
await _syncService.syncUsersFromServer(users);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,8 @@ import 'package:immich_mobile/models/backup/backup_candidate.model.dart';
|
||||
import 'package:immich_mobile/providers/api.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/exif.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/store.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/user.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/user.provider.dart'
|
||||
hide userServiceProvider;
|
||||
import 'package:immich_mobile/repositories/asset.repository.dart';
|
||||
import 'package:immich_mobile/repositories/asset_api.repository.dart';
|
||||
import 'package:immich_mobile/repositories/asset_media.repository.dart';
|
||||
@@ -30,7 +31,6 @@ import 'package:immich_mobile/services/album.service.dart';
|
||||
import 'package:immich_mobile/services/api.service.dart';
|
||||
import 'package:immich_mobile/services/backup.service.dart';
|
||||
import 'package:immich_mobile/services/sync.service.dart';
|
||||
import 'package:immich_mobile/services/user.service.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:maplibre_gl/maplibre_gl.dart';
|
||||
import 'package:openapi/api.dart';
|
||||
@@ -45,7 +45,6 @@ final assetServiceProvider = Provider(
|
||||
ref.watch(backupAlbumRepositoryProvider),
|
||||
ref.watch(apiServiceProvider),
|
||||
ref.watch(syncServiceProvider),
|
||||
ref.watch(userServiceProvider),
|
||||
ref.watch(backupServiceProvider),
|
||||
ref.watch(albumServiceProvider),
|
||||
ref.watch(storeServiceProvider),
|
||||
@@ -62,7 +61,6 @@ class AssetService {
|
||||
final IBackupAlbumRepository _backupRepository;
|
||||
final ApiService _apiService;
|
||||
final SyncService _syncService;
|
||||
final UserService _userService;
|
||||
final BackupService _backupService;
|
||||
final AlbumService _albumService;
|
||||
final StoreService _storeService;
|
||||
@@ -78,7 +76,6 @@ class AssetService {
|
||||
this._backupRepository,
|
||||
this._apiService,
|
||||
this._syncService,
|
||||
this._userService,
|
||||
this._backupService,
|
||||
this._albumService,
|
||||
this._storeService,
|
||||
@@ -97,7 +94,6 @@ class AssetService {
|
||||
users: syncedUsers,
|
||||
getChangedAssets: _getRemoteAssetChanges,
|
||||
loadAssets: _getRemoteAssets,
|
||||
refreshUsers: _userService.getUsersFromServer,
|
||||
);
|
||||
debugPrint("refreshRemoteAssets full took ${sw.elapsedMilliseconds}ms");
|
||||
return changes;
|
||||
|
||||
@@ -13,12 +13,14 @@ import 'package:flutter/widgets.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/domain/interfaces/exif.interface.dart';
|
||||
import 'package:immich_mobile/domain/interfaces/user.interface.dart';
|
||||
import 'package:immich_mobile/domain/interfaces/user_api.repository.dart';
|
||||
import 'package:immich_mobile/domain/models/store.model.dart';
|
||||
import 'package:immich_mobile/domain/services/store.service.dart';
|
||||
import 'package:immich_mobile/entities/backup_album.entity.dart';
|
||||
import 'package:immich_mobile/entities/store.entity.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/exif.repository.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/user.repository.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/user_api.repository.dart';
|
||||
import 'package:immich_mobile/interfaces/backup_album.interface.dart';
|
||||
import 'package:immich_mobile/interfaces/partner.interface.dart';
|
||||
import 'package:immich_mobile/models/backup/backup_candidate.model.dart';
|
||||
@@ -39,7 +41,6 @@ import 'package:immich_mobile/repositories/network.repository.dart';
|
||||
import 'package:immich_mobile/repositories/partner.repository.dart';
|
||||
import 'package:immich_mobile/repositories/partner_api.repository.dart';
|
||||
import 'package:immich_mobile/repositories/permission.repository.dart';
|
||||
import 'package:immich_mobile/repositories/user_api.repository.dart';
|
||||
import 'package:immich_mobile/services/album.service.dart';
|
||||
import 'package:immich_mobile/services/api.service.dart';
|
||||
import 'package:immich_mobile/services/app_settings.service.dart';
|
||||
@@ -50,7 +51,6 @@ import 'package:immich_mobile/services/hash.service.dart';
|
||||
import 'package:immich_mobile/services/localization.service.dart';
|
||||
import 'package:immich_mobile/services/network.service.dart';
|
||||
import 'package:immich_mobile/services/sync.service.dart';
|
||||
import 'package:immich_mobile/services/user.service.dart';
|
||||
import 'package:immich_mobile/utils/backup_progress.dart';
|
||||
import 'package:immich_mobile/utils/bootstrap.dart';
|
||||
import 'package:immich_mobile/utils/diff.dart';
|
||||
@@ -390,7 +390,7 @@ class BackgroundService {
|
||||
FileMediaRepository fileMediaRepository = FileMediaRepository();
|
||||
AssetMediaRepository assetMediaRepository = AssetMediaRepository();
|
||||
IUserRepository userRepository = IsarUserRepository(db);
|
||||
UserApiRepository userApiRepository =
|
||||
IUserApiRepository userApiRepository =
|
||||
UserApiRepository(apiService.usersApi);
|
||||
AlbumApiRepository albumApiRepository =
|
||||
AlbumApiRepository(apiService.albumsApi);
|
||||
@@ -413,14 +413,10 @@ class BackgroundService {
|
||||
userRepository,
|
||||
StoreService.I,
|
||||
eTagRepository,
|
||||
);
|
||||
UserService userService = UserService(
|
||||
partnerApiRepository,
|
||||
userApiRepository,
|
||||
userRepository,
|
||||
);
|
||||
AlbumService albumService = AlbumService(
|
||||
userService,
|
||||
syncSerive,
|
||||
entityService,
|
||||
albumRepository,
|
||||
|
||||
@@ -4,6 +4,7 @@ import 'package:collection/collection.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/domain/interfaces/exif.interface.dart';
|
||||
import 'package:immich_mobile/domain/interfaces/user.interface.dart';
|
||||
import 'package:immich_mobile/domain/interfaces/user_api.repository.dart';
|
||||
import 'package:immich_mobile/domain/models/store.model.dart';
|
||||
import 'package:immich_mobile/domain/models/user.model.dart';
|
||||
import 'package:immich_mobile/domain/services/store.service.dart';
|
||||
@@ -17,6 +18,7 @@ import 'package:immich_mobile/interfaces/album_media.interface.dart';
|
||||
import 'package:immich_mobile/interfaces/asset.interface.dart';
|
||||
import 'package:immich_mobile/interfaces/etag.interface.dart';
|
||||
import 'package:immich_mobile/interfaces/partner.interface.dart';
|
||||
import 'package:immich_mobile/interfaces/partner_api.interface.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/exif.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/store.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/user.provider.dart';
|
||||
@@ -26,6 +28,7 @@ import 'package:immich_mobile/repositories/album_media.repository.dart';
|
||||
import 'package:immich_mobile/repositories/asset.repository.dart';
|
||||
import 'package:immich_mobile/repositories/etag.repository.dart';
|
||||
import 'package:immich_mobile/repositories/partner.repository.dart';
|
||||
import 'package:immich_mobile/repositories/partner_api.repository.dart';
|
||||
import 'package:immich_mobile/services/entity.service.dart';
|
||||
import 'package:immich_mobile/services/hash.service.dart';
|
||||
import 'package:immich_mobile/utils/async_mutex.dart';
|
||||
@@ -46,6 +49,8 @@ final syncServiceProvider = Provider(
|
||||
ref.watch(userRepositoryProvider),
|
||||
ref.watch(storeServiceProvider),
|
||||
ref.watch(etagRepositoryProvider),
|
||||
ref.watch(partnerApiRepositoryProvider),
|
||||
ref.watch(userApiRepositoryProvider),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -61,6 +66,8 @@ class SyncService {
|
||||
final IPartnerRepository _partnerRepository;
|
||||
final StoreService _storeService;
|
||||
final IETagRepository _eTagRepository;
|
||||
final IPartnerApiRepository _partnerApiRepository;
|
||||
final IUserApiRepository _userApiRepository;
|
||||
final AsyncMutex _lock = AsyncMutex();
|
||||
final Logger _log = Logger('SyncService');
|
||||
|
||||
@@ -76,6 +83,8 @@ class SyncService {
|
||||
this._userRepository,
|
||||
this._storeService,
|
||||
this._eTagRepository,
|
||||
this._partnerApiRepository,
|
||||
this._userApiRepository,
|
||||
);
|
||||
|
||||
// public methods:
|
||||
@@ -95,12 +104,11 @@ class SyncService {
|
||||
) getChangedAssets,
|
||||
required FutureOr<List<Asset>?> Function(UserDto user, DateTime until)
|
||||
loadAssets,
|
||||
required FutureOr<List<UserDto>?> Function() refreshUsers,
|
||||
}) =>
|
||||
_lock.run(
|
||||
() async =>
|
||||
await _syncRemoteAssetChanges(users, getChangedAssets) ??
|
||||
await _syncRemoteAssetsFull(refreshUsers, loadAssets),
|
||||
await _syncRemoteAssetsFull(getUsersFromServer, loadAssets),
|
||||
);
|
||||
|
||||
/// Syncs remote albums to the database
|
||||
@@ -853,6 +861,61 @@ class SyncService {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<UserDto>?> getUsersFromServer() async {
|
||||
List<UserDto>? users;
|
||||
try {
|
||||
users = await _userApiRepository.getAll();
|
||||
} catch (e) {
|
||||
_log.warning("Failed to fetch users", e);
|
||||
users = null;
|
||||
}
|
||||
final List<UserDto> sharedBy =
|
||||
await _partnerApiRepository.getAll(Direction.sharedByMe);
|
||||
final List<UserDto> sharedWith =
|
||||
await _partnerApiRepository.getAll(Direction.sharedWithMe);
|
||||
|
||||
if (users == null) {
|
||||
_log.warning("Failed to refresh users");
|
||||
return null;
|
||||
}
|
||||
|
||||
users.sortBy((u) => u.uid);
|
||||
sharedBy.sortBy((u) => u.uid);
|
||||
sharedWith.sortBy((u) => u.uid);
|
||||
|
||||
final updatedSharedBy = <UserDto>[];
|
||||
|
||||
diffSortedListsSync(
|
||||
users,
|
||||
sharedBy,
|
||||
compare: (UserDto a, UserDto b) => a.uid.compareTo(b.uid),
|
||||
both: (UserDto a, UserDto b) {
|
||||
updatedSharedBy.add(a.copyWith(isPartnerSharedBy: true));
|
||||
return true;
|
||||
},
|
||||
onlyFirst: (UserDto a) => updatedSharedBy.add(a),
|
||||
onlySecond: (UserDto b) => updatedSharedBy.add(b),
|
||||
);
|
||||
|
||||
final updatedSharedWith = <UserDto>[];
|
||||
|
||||
diffSortedListsSync(
|
||||
updatedSharedBy,
|
||||
sharedWith,
|
||||
compare: (UserDto a, UserDto b) => a.uid.compareTo(b.uid),
|
||||
both: (UserDto a, UserDto b) {
|
||||
updatedSharedWith.add(
|
||||
a.copyWith(inTimeline: b.inTimeline, isPartnerSharedWith: true),
|
||||
);
|
||||
return true;
|
||||
},
|
||||
onlyFirst: (UserDto a) => updatedSharedWith.add(a),
|
||||
onlySecond: (UserDto b) => updatedSharedWith.add(b),
|
||||
);
|
||||
|
||||
return updatedSharedWith;
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a triple(toAdd, toUpdate, toRemove)
|
||||
|
||||
@@ -1,108 +0,0 @@
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
import 'package:immich_mobile/domain/interfaces/user.interface.dart';
|
||||
import 'package:immich_mobile/domain/models/user.model.dart';
|
||||
import 'package:immich_mobile/interfaces/partner_api.interface.dart';
|
||||
import 'package:immich_mobile/interfaces/user_api.interface.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/user.provider.dart';
|
||||
import 'package:immich_mobile/repositories/partner_api.repository.dart';
|
||||
import 'package:immich_mobile/repositories/user_api.repository.dart';
|
||||
import 'package:immich_mobile/utils/diff.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
|
||||
final userServiceProvider = Provider(
|
||||
(ref) => UserService(
|
||||
ref.watch(partnerApiRepositoryProvider),
|
||||
ref.watch(userApiRepositoryProvider),
|
||||
ref.watch(userRepositoryProvider),
|
||||
),
|
||||
);
|
||||
|
||||
class UserService {
|
||||
final IPartnerApiRepository _partnerApiRepository;
|
||||
final IUserApiRepository _userApiRepository;
|
||||
final IUserRepository _userRepository;
|
||||
final Logger _log = Logger("UserService");
|
||||
|
||||
UserService(
|
||||
this._partnerApiRepository,
|
||||
this._userApiRepository,
|
||||
this._userRepository,
|
||||
);
|
||||
|
||||
Future<({String profileImagePath})?> uploadProfileImage(XFile image) async {
|
||||
try {
|
||||
return await _userApiRepository.createProfileImage(
|
||||
name: image.name,
|
||||
data: await image.readAsBytes(),
|
||||
);
|
||||
} catch (e) {
|
||||
_log.warning("Failed to upload profile image", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<UserDto>> getAll() async {
|
||||
return await _userRepository.getAll();
|
||||
}
|
||||
|
||||
Future<List<UserDto>?> getUsersFromServer() async {
|
||||
List<UserDto>? users;
|
||||
try {
|
||||
users = await _userApiRepository.getAll();
|
||||
} catch (e) {
|
||||
_log.warning("Failed to fetch users", e);
|
||||
users = null;
|
||||
}
|
||||
final List<UserDto> sharedBy =
|
||||
await _partnerApiRepository.getAll(Direction.sharedByMe);
|
||||
final List<UserDto> sharedWith =
|
||||
await _partnerApiRepository.getAll(Direction.sharedWithMe);
|
||||
|
||||
if (users == null) {
|
||||
_log.warning("Failed to refresh users");
|
||||
return null;
|
||||
}
|
||||
|
||||
users.sortBy((u) => u.uid);
|
||||
sharedBy.sortBy((u) => u.uid);
|
||||
sharedWith.sortBy((u) => u.uid);
|
||||
|
||||
final updatedSharedBy = <UserDto>[];
|
||||
|
||||
diffSortedListsSync(
|
||||
users,
|
||||
sharedBy,
|
||||
compare: (UserDto a, UserDto b) => a.uid.compareTo(b.uid),
|
||||
both: (UserDto a, UserDto b) {
|
||||
updatedSharedBy.add(a.copyWith(isPartnerSharedBy: true));
|
||||
return true;
|
||||
},
|
||||
onlyFirst: (UserDto a) => updatedSharedBy.add(a),
|
||||
onlySecond: (UserDto b) => updatedSharedBy.add(b),
|
||||
);
|
||||
|
||||
final updatedSharedWith = <UserDto>[];
|
||||
|
||||
diffSortedListsSync(
|
||||
updatedSharedBy,
|
||||
sharedWith,
|
||||
compare: (UserDto a, UserDto b) => a.uid.compareTo(b.uid),
|
||||
both: (UserDto a, UserDto b) {
|
||||
updatedSharedWith.add(
|
||||
a.copyWith(inTimeline: b.inTimeline, isPartnerSharedWith: true),
|
||||
);
|
||||
return true;
|
||||
},
|
||||
onlyFirst: (UserDto a) => updatedSharedWith.add(a),
|
||||
onlySecond: (UserDto b) => updatedSharedWith.add(b),
|
||||
);
|
||||
|
||||
return updatedSharedWith;
|
||||
}
|
||||
|
||||
Future<void> clearTable() {
|
||||
return _userRepository.deleteAll();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user