mirror of
https://github.com/immich-app/immich.git
synced 2026-07-16 13:44:28 +03:00
Compare commits
1 Commits
refactor/s
...
refactor/c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a855852ae7 |
@@ -1,10 +1,7 @@
|
||||
import 'package:immich_mobile/domain/models/user.model.dart';
|
||||
|
||||
/// Key for each possible value in the `Store`.
|
||||
/// Defines the data type for each value
|
||||
enum StoreKey<T> {
|
||||
version<int>._(0),
|
||||
currentUser<UserDto>._(2),
|
||||
deviceId<String>._(4),
|
||||
advancedTroubleshooting<bool>._(114),
|
||||
enableHapticFeedback<bool>._(126),
|
||||
|
||||
@@ -2,13 +2,12 @@ import 'dart:async';
|
||||
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/domain/models/album/local_album.model.dart';
|
||||
import 'package:immich_mobile/domain/models/store.model.dart';
|
||||
import 'package:immich_mobile/domain/services/store.service.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/local_album.repository.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/remote_album.repository.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/user.repository.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/album.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/cancel.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/store.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/user.provider.dart';
|
||||
import 'package:immich_mobile/repositories/drift_album_api_repository.dart';
|
||||
import 'package:immich_mobile/utils/debug_print.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
@@ -18,7 +17,7 @@ final syncLinkedAlbumServiceProvider = Provider(
|
||||
ref.watch(localAlbumRepository),
|
||||
ref.watch(remoteAlbumRepository),
|
||||
ref.watch(driftAlbumApiRepositoryProvider),
|
||||
ref.watch(storeServiceProvider),
|
||||
ref.watch(authUserRepositoryProvider),
|
||||
cancellation: ref.watch(cancellationProvider),
|
||||
),
|
||||
);
|
||||
@@ -27,14 +26,14 @@ class SyncLinkedAlbumService {
|
||||
final DriftLocalAlbumRepository _localAlbumRepository;
|
||||
final DriftRemoteAlbumRepository _remoteAlbumRepository;
|
||||
final DriftAlbumApiRepository _albumApiRepository;
|
||||
final StoreService _storeService;
|
||||
final DriftAuthUserRepository _authUserRepository;
|
||||
final Completer<void>? _cancellation;
|
||||
|
||||
SyncLinkedAlbumService(
|
||||
this._localAlbumRepository,
|
||||
this._remoteAlbumRepository,
|
||||
this._albumApiRepository,
|
||||
this._storeService, {
|
||||
this._authUserRepository, {
|
||||
this._cancellation,
|
||||
});
|
||||
|
||||
@@ -123,11 +122,12 @@ class SyncLinkedAlbumService {
|
||||
/// Creates a new remote album and links it to the local album
|
||||
Future<void> _createAndLinkNewRemoteAlbum(LocalAlbum localAlbum) async {
|
||||
dPrint(() => "Creating new remote album for local album: ${localAlbum.name}");
|
||||
final newRemoteAlbum = await _albumApiRepository.createDriftAlbum(
|
||||
localAlbum.name,
|
||||
_storeService.get(StoreKey.currentUser),
|
||||
assetIds: [],
|
||||
);
|
||||
final currentUser = await _authUserRepository.get();
|
||||
if (currentUser == null) {
|
||||
_log.warning("No user logged in, skipping remote album creation for local album: ${localAlbum.name}");
|
||||
return;
|
||||
}
|
||||
final newRemoteAlbum = await _albumApiRepository.createDriftAlbum(localAlbum.name, currentUser, assetIds: []);
|
||||
await _remoteAlbumRepository.create(newRemoteAlbum, []);
|
||||
return _localAlbumRepository.linkRemoteAlbum(localAlbum.id, newRemoteAlbum.id);
|
||||
}
|
||||
|
||||
@@ -1,29 +1,24 @@
|
||||
import 'dart:async';
|
||||
import 'dart:typed_data';
|
||||
|
||||
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';
|
||||
import 'package:immich_mobile/infrastructure/repositories/user.repository.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/user_api.repository.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
|
||||
class UserService {
|
||||
final Logger _log = Logger("UserService");
|
||||
final UserApiRepository _userApiRepository;
|
||||
final StoreService _storeService;
|
||||
final DriftAuthUserRepository _authUserRepository;
|
||||
|
||||
UserService({required this._userApiRepository, required this._storeService});
|
||||
UserService({required this._userApiRepository, required this._authUserRepository});
|
||||
|
||||
UserDto getMyUser() {
|
||||
return _storeService.get(StoreKey.currentUser);
|
||||
}
|
||||
|
||||
UserDto? tryGetMyUser() {
|
||||
return _storeService.tryGet(StoreKey.currentUser);
|
||||
Future<UserDto?> tryGetMyUser() {
|
||||
return _authUserRepository.get();
|
||||
}
|
||||
|
||||
Stream<UserDto?> watchMyUser() {
|
||||
return _storeService.watch(StoreKey.currentUser);
|
||||
return _authUserRepository.watch();
|
||||
}
|
||||
|
||||
Future<UserDto?> refreshMyUser() async {
|
||||
@@ -31,15 +26,17 @@ class UserService {
|
||||
if (user == null) {
|
||||
return null;
|
||||
}
|
||||
await _storeService.put(StoreKey.currentUser, user);
|
||||
await _authUserRepository.upsert(user);
|
||||
return user;
|
||||
}
|
||||
|
||||
Future<String?> createProfileImage(String name, Uint8List image) async {
|
||||
try {
|
||||
final path = await _userApiRepository.createProfileImage(name: name, data: image);
|
||||
final updatedUser = getMyUser();
|
||||
await _storeService.put(StoreKey.currentUser, updatedUser);
|
||||
final updatedUser = await tryGetMyUser();
|
||||
if (updatedUser != null) {
|
||||
await _authUserRepository.upsert(updatedUser);
|
||||
}
|
||||
return path;
|
||||
} catch (e) {
|
||||
_log.warning("Failed to upload profile image", e);
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/domain/models/store.model.dart';
|
||||
import 'package:immich_mobile/domain/services/sync_linked_album.service.dart';
|
||||
import 'package:immich_mobile/entities/store.entity.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/user.provider.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
|
||||
Future<void> syncLinkedAlbumsIsolated(ProviderContainer ref) {
|
||||
final user = Store.tryGet(StoreKey.currentUser);
|
||||
Future<void> syncLinkedAlbumsIsolated(ProviderContainer ref) async {
|
||||
final user = await ref.read(authUserRepositoryProvider).get();
|
||||
if (user == null) {
|
||||
Logger("SyncLinkedAlbum").warning("No user logged in, skipping linked album sync");
|
||||
return Future.value();
|
||||
return;
|
||||
}
|
||||
return ref.read(syncLinkedAlbumServiceProvider).syncLinkedAlbums(user.id);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:immich_mobile/domain/models/store.model.dart';
|
||||
import 'package:immich_mobile/domain/models/user.model.dart';
|
||||
import 'package:immich_mobile/infrastructure/entities/store.entity.drift.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/user.repository.dart';
|
||||
|
||||
class DriftStoreRepository extends DriftDatabaseRepository {
|
||||
final Drift _db;
|
||||
@@ -63,8 +61,6 @@ class DriftStoreRepository extends DriftDatabaseRepository {
|
||||
const (String) => entity.stringValue,
|
||||
const (bool) => entity.intValue == 1,
|
||||
const (DateTime) => entity.intValue == null ? null : DateTime.fromMillisecondsSinceEpoch(entity.intValue!),
|
||||
const (UserDto) =>
|
||||
entity.stringValue == null ? null : await DriftAuthUserRepository(_db).get(entity.stringValue!),
|
||||
_ => null,
|
||||
}
|
||||
as T?;
|
||||
@@ -75,7 +71,6 @@ class DriftStoreRepository extends DriftDatabaseRepository {
|
||||
const (String) => (null, value as String),
|
||||
const (bool) => ((value as bool) ? 1 : 0, null),
|
||||
const (DateTime) => ((value as DateTime).millisecondsSinceEpoch, null),
|
||||
const (UserDto) => (null, (await DriftAuthUserRepository(_db).upsert(value as UserDto)).id),
|
||||
_ => throw UnsupportedError("Unsupported primitive type: ${key.type} for key: ${key.name}"),
|
||||
};
|
||||
return StoreEntityCompanion(id: Value(key.id), intValue: Value(intValue), stringValue: Value(strValue));
|
||||
|
||||
@@ -17,16 +17,15 @@ class DriftAuthUserRepository extends DriftDatabaseRepository {
|
||||
final Drift _db;
|
||||
const DriftAuthUserRepository(super.db) : _db = db;
|
||||
|
||||
Future<UserDto?> get(String id) async {
|
||||
final user = await _db.managers.authUserEntity.filter((user) => user.id.equals(id)).getSingleOrNull();
|
||||
Selectable<UserDto?> get _authUserQuery => (_db.authUserEntity.select()..limit(1)).asyncMap(_toDto);
|
||||
|
||||
if (user == null) {
|
||||
return null;
|
||||
}
|
||||
Future<UserDto?> get() => _authUserQuery.getSingleOrNull();
|
||||
|
||||
final query = _db.userMetadataEntity.select()..where((e) => e.userId.equals(id));
|
||||
Stream<UserDto?> watch() => _authUserQuery.watchSingleOrNull();
|
||||
|
||||
Future<UserDto> _toDto(AuthUserEntityData user) async {
|
||||
final query = _db.userMetadataEntity.select()..where((e) => e.userId.equals(user.id));
|
||||
final metadata = await query.map((row) => row.toDto()).get();
|
||||
|
||||
return user.toDto(metadata);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,8 +5,6 @@ import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/domain/models/album/local_album.model.dart';
|
||||
import 'package:immich_mobile/domain/models/store.model.dart';
|
||||
import 'package:immich_mobile/entities/store.entity.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/extensions/platform_extensions.dart';
|
||||
import 'package:immich_mobile/extensions/theme_extensions.dart';
|
||||
@@ -85,7 +83,7 @@ class _DriftBackupPageState extends ConsumerState<DriftBackupPage> {
|
||||
final backupSyncManager = ref.read(backgroundSyncProvider);
|
||||
|
||||
Future<void> startBackup() async {
|
||||
final currentUser = Store.tryGet(StoreKey.currentUser);
|
||||
final currentUser = ref.read(currentUserProvider);
|
||||
if (currentUser == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -8,15 +8,15 @@ import 'package:flutter/services.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/constants/locales.dart';
|
||||
import 'package:immich_mobile/domain/models/config/app_config.dart';
|
||||
import 'package:immich_mobile/domain/models/store.model.dart';
|
||||
import 'package:immich_mobile/entities/store.entity.dart';
|
||||
import 'package:immich_mobile/generated/codegen_loader.g.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/settings.repository.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/user.repository.dart';
|
||||
import 'package:immich_mobile/providers/auth.provider.dart';
|
||||
import 'package:immich_mobile/providers/background_sync.provider.dart';
|
||||
import 'package:immich_mobile/providers/backup/drift_backup.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/session.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/user.provider.dart';
|
||||
import 'package:immich_mobile/providers/server_info.provider.dart';
|
||||
import 'package:immich_mobile/providers/view_intent/view_intent_handler.provider.dart';
|
||||
import 'package:immich_mobile/providers/websocket.provider.dart';
|
||||
@@ -318,6 +318,7 @@ class SplashScreenPageState extends ConsumerState<SplashScreenPage> {
|
||||
final backgroundManager = ref.read(backgroundSyncProvider);
|
||||
final backupProvider = ref.read(driftBackupProvider.notifier);
|
||||
final viewIntentHandler = ref.read(viewIntentHandlerProvider);
|
||||
final authUserRepository = ref.read(authUserRepositoryProvider);
|
||||
|
||||
unawaited(
|
||||
ref.read(authProvider.notifier).saveAuthInfo(accessToken: accessToken).then(
|
||||
@@ -337,9 +338,9 @@ class SplashScreenPageState extends ConsumerState<SplashScreenPage> {
|
||||
if (syncSuccess) {
|
||||
await Future.wait([
|
||||
backgroundManager.hashAssets().then((_) {
|
||||
_resumeBackup(backupProvider);
|
||||
_resumeBackup(backupProvider, authUserRepository);
|
||||
}),
|
||||
_resumeBackup(backupProvider),
|
||||
_resumeBackup(backupProvider, authUserRepository),
|
||||
// TODO: Bring back when the soft freeze issue is addressed
|
||||
// backgroundManager.syncCloudIds(),
|
||||
]);
|
||||
@@ -375,11 +376,11 @@ class SplashScreenPageState extends ConsumerState<SplashScreenPage> {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _resumeBackup(DriftBackupNotifier notifier) async {
|
||||
Future<void> _resumeBackup(DriftBackupNotifier notifier, DriftAuthUserRepository authUserRepository) async {
|
||||
final isEnableBackup = SettingsRepository.instance.appConfig.backup.enabled;
|
||||
|
||||
if (isEnableBackup) {
|
||||
final currentUser = Store.tryGet(StoreKey.currentUser);
|
||||
final currentUser = await authUserRepository.get();
|
||||
if (currentUser != null) {
|
||||
unawaited(notifier.startForegroundBackup(currentUser.id));
|
||||
}
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/domain/models/store.model.dart';
|
||||
import 'package:immich_mobile/domain/services/log.service.dart';
|
||||
import 'package:immich_mobile/entities/store.entity.dart';
|
||||
import 'package:immich_mobile/extensions/platform_extensions.dart';
|
||||
import 'package:immich_mobile/providers/auth.provider.dart';
|
||||
import 'package:immich_mobile/providers/background_sync.provider.dart';
|
||||
@@ -13,6 +11,7 @@ import 'package:immich_mobile/providers/infrastructure/platform.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/settings.provider.dart';
|
||||
import 'package:immich_mobile/providers/permission.provider.dart';
|
||||
import 'package:immich_mobile/providers/server_info.provider.dart';
|
||||
import 'package:immich_mobile/providers/user.provider.dart';
|
||||
import 'package:immich_mobile/providers/websocket.provider.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
|
||||
@@ -140,7 +139,7 @@ class AppLifeCycleNotifier extends StateNotifier<AppLifeCycleEnum> {
|
||||
final isEnableBackup = _ref.read(appConfigProvider).backup.enabled;
|
||||
|
||||
if (isEnableBackup) {
|
||||
final currentUser = Store.tryGet(StoreKey.currentUser);
|
||||
final currentUser = _ref.read(currentUserProvider);
|
||||
if (currentUser != null) {
|
||||
await _safeRun(
|
||||
_ref.read(driftBackupProvider.notifier).startForegroundBackup(currentUser.id),
|
||||
|
||||
@@ -138,7 +138,7 @@ class AuthNotifier extends StateNotifier<AuthState> {
|
||||
// Get the deviceid from the store if it exists, otherwise generate a new one
|
||||
String deviceId = Store.tryGet(StoreKey.deviceId) ?? await FlutterUdid.consistentUdid;
|
||||
|
||||
UserDto? user = _userService.tryGetMyUser();
|
||||
UserDto? user = await _userService.tryGetMyUser();
|
||||
|
||||
try {
|
||||
final serverUser = await _userService.refreshMyUser().timeout(_timeoutDuration);
|
||||
|
||||
@@ -6,17 +6,18 @@ import 'package:immich_mobile/infrastructure/repositories/user.repository.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/user_api.repository.dart';
|
||||
import 'package:immich_mobile/providers/api.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/db.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/store.provider.dart';
|
||||
import 'package:immich_mobile/repositories/partner_api.repository.dart';
|
||||
|
||||
final userRepositoryProvider = Provider((ref) => UserRepository(ref.watch(driftProvider)));
|
||||
|
||||
final authUserRepositoryProvider = Provider((ref) => DriftAuthUserRepository(ref.watch(driftProvider)));
|
||||
|
||||
final userApiRepositoryProvider = Provider((ref) => UserApiRepository(ref.watch(apiServiceProvider).usersApi));
|
||||
|
||||
final userServiceProvider = Provider(
|
||||
(ref) => UserService(
|
||||
userApiRepository: ref.watch(userApiRepositoryProvider),
|
||||
storeService: ref.watch(storeServiceProvider),
|
||||
authUserRepository: ref.watch(authUserRepositoryProvider),
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import 'package:immich_mobile/providers/infrastructure/user.provider.dart';
|
||||
|
||||
class CurrentUserProvider extends StateNotifier<UserDto?> {
|
||||
CurrentUserProvider(this._userService) : super(null) {
|
||||
state = _userService.tryGetMyUser();
|
||||
_userService.tryGetMyUser().then((user) => state = user ?? state);
|
||||
streamSub = _userService.watchMyUser().listen((user) => state = user ?? state);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,9 +3,7 @@ import 'dart:async';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/domain/models/session.model.dart';
|
||||
import 'package:immich_mobile/domain/models/settings_key.dart';
|
||||
import 'package:immich_mobile/domain/models/store.model.dart';
|
||||
import 'package:immich_mobile/domain/utils/background_sync.dart';
|
||||
import 'package:immich_mobile/entities/store.entity.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/network.repository.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/session.repository.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/settings.repository.dart';
|
||||
@@ -120,7 +118,6 @@ class AuthService {
|
||||
await _backgroundSyncManager.cancel();
|
||||
await Future.wait([
|
||||
_authRepository.clearLocalData(),
|
||||
Store.delete(StoreKey.currentUser),
|
||||
SessionRepository.instance.clear([SessionKey.accessToken]),
|
||||
SettingsRepository.instance.clear(const [
|
||||
.networkAutoEndpointSwitching,
|
||||
|
||||
@@ -49,7 +49,7 @@ void main() {
|
||||
expect(sut.tryGet(StoreKey.advancedTroubleshooting), _kAdvancedTroubleshooting);
|
||||
expect(sut.tryGet(StoreKey.version), _kVersion);
|
||||
// Other keys should be null
|
||||
expect(sut.tryGet(StoreKey.currentUser), isNull);
|
||||
expect(sut.tryGet(StoreKey.deviceId), isNull);
|
||||
});
|
||||
|
||||
test('Listens to stream of store updates', () async {
|
||||
@@ -69,11 +69,11 @@ void main() {
|
||||
});
|
||||
|
||||
test('Throws StoreKeyNotFoundException for nonexistent keys', () {
|
||||
expect(() => sut.get(StoreKey.currentUser), throwsA(isA<StoreKeyNotFoundException>()));
|
||||
expect(() => sut.get(StoreKey.deviceId), throwsA(isA<StoreKeyNotFoundException>()));
|
||||
});
|
||||
|
||||
test('Returns the stored value for the given key or the defaultValue', () {
|
||||
expect(sut.get(StoreKey.currentUser, 5), 5);
|
||||
expect(sut.get(StoreKey.legacyBackupTriggerDelay, 5), 5);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -1,78 +1,62 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:immich_mobile/domain/models/store.model.dart';
|
||||
import 'package:immich_mobile/domain/services/store.service.dart';
|
||||
import 'package:immich_mobile/domain/services/user.service.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/user.repository.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/user_api.repository.dart';
|
||||
import 'package:mocktail/mocktail.dart';
|
||||
|
||||
import '../../fixtures/user.stub.dart';
|
||||
import '../../infrastructure/repository.mock.dart';
|
||||
import '../service.mock.dart';
|
||||
|
||||
void main() {
|
||||
late UserService sut;
|
||||
late UserApiRepository mockUserApiRepo;
|
||||
late StoreService mockStoreService;
|
||||
late DriftAuthUserRepository mockAuthUserRepo;
|
||||
|
||||
setUp(() {
|
||||
mockUserApiRepo = MockUserApiRepository();
|
||||
mockStoreService = MockStoreService();
|
||||
sut = UserService(userApiRepository: mockUserApiRepo, storeService: mockStoreService);
|
||||
mockAuthUserRepo = MockDriftAuthUserRepository();
|
||||
sut = UserService(userApiRepository: mockUserApiRepo, authUserRepository: mockAuthUserRepo);
|
||||
|
||||
registerFallbackValue(UserStub.admin);
|
||||
when(() => mockStoreService.get(StoreKey.currentUser)).thenReturn(UserStub.admin);
|
||||
when(() => mockStoreService.tryGet(StoreKey.currentUser)).thenReturn(UserStub.admin);
|
||||
});
|
||||
|
||||
group('getMyUser', () {
|
||||
test('should return user from store', () {
|
||||
final result = sut.getMyUser();
|
||||
expect(result, UserStub.admin);
|
||||
});
|
||||
|
||||
test('should handle user not found scenario', () {
|
||||
when(() => mockStoreService.get(StoreKey.currentUser)).thenThrow(Exception('User not found'));
|
||||
|
||||
expect(() => sut.getMyUser(), throwsA(isA<Exception>()));
|
||||
});
|
||||
when(() => mockAuthUserRepo.get()).thenAnswer((_) async => UserStub.admin);
|
||||
when(() => mockAuthUserRepo.upsert(any())).thenAnswer((_) async => UserStub.admin);
|
||||
});
|
||||
|
||||
group('tryGetMyUser', () {
|
||||
test('should return user from store', () {
|
||||
final result = sut.tryGetMyUser();
|
||||
test('should return the current user from the auth user repository', () async {
|
||||
final result = await sut.tryGetMyUser();
|
||||
expect(result, UserStub.admin);
|
||||
});
|
||||
|
||||
test('should return null if user not found', () {
|
||||
when(() => mockStoreService.tryGet(StoreKey.currentUser)).thenReturn(null);
|
||||
final result = sut.tryGetMyUser();
|
||||
test('should return null if no user is logged in', () async {
|
||||
when(() => mockAuthUserRepo.get()).thenAnswer((_) async => null);
|
||||
final result = await sut.tryGetMyUser();
|
||||
expect(result, isNull);
|
||||
});
|
||||
});
|
||||
|
||||
group('watchMyUser', () {
|
||||
test('should return user stream from store', () {
|
||||
when(() => mockStoreService.watch(StoreKey.currentUser)).thenAnswer((_) => Stream.value(UserStub.admin));
|
||||
test('should return the current user stream from the auth user repository', () {
|
||||
when(() => mockAuthUserRepo.watch()).thenAnswer((_) => Stream.value(UserStub.admin));
|
||||
final result = sut.watchMyUser();
|
||||
expect(result, emits(UserStub.admin));
|
||||
});
|
||||
|
||||
test('should return an empty stream if user not found', () {
|
||||
when(() => mockStoreService.watch(StoreKey.currentUser)).thenAnswer((_) => const Stream.empty());
|
||||
test('should return an empty stream if no user is logged in', () {
|
||||
when(() => mockAuthUserRepo.watch()).thenAnswer((_) => const Stream.empty());
|
||||
final result = sut.watchMyUser();
|
||||
expect(result, emitsInOrder([]));
|
||||
});
|
||||
});
|
||||
|
||||
group('refreshMyUser', () {
|
||||
test('should return user from api and store it', () async {
|
||||
test('should return user from api and persist it', () async {
|
||||
when(() => mockUserApiRepo.getMyUser()).thenAnswer((_) async => UserStub.admin);
|
||||
when(() => mockStoreService.put(StoreKey.currentUser, UserStub.admin)).thenAnswer((_) async => true);
|
||||
|
||||
final result = await sut.refreshMyUser();
|
||||
verify(() => mockStoreService.put(StoreKey.currentUser, UserStub.admin)).called(1);
|
||||
verify(() => mockAuthUserRepo.upsert(UserStub.admin)).called(1);
|
||||
expect(result, UserStub.admin);
|
||||
});
|
||||
|
||||
@@ -80,7 +64,7 @@ void main() {
|
||||
when(() => mockUserApiRepo.getMyUser()).thenAnswer((_) async => null);
|
||||
|
||||
final result = await sut.refreshMyUser();
|
||||
verifyNever(() => mockStoreService.put(StoreKey.currentUser, UserStub.admin));
|
||||
verifyNever(() => mockAuthUserRepo.upsert(any()));
|
||||
expect(result, isNull);
|
||||
});
|
||||
});
|
||||
@@ -88,29 +72,26 @@ void main() {
|
||||
group('createProfileImage', () {
|
||||
test('should return profile image path', () async {
|
||||
const profileImagePath = 'profile.jpg';
|
||||
final updatedUser = UserStub.admin;
|
||||
|
||||
when(
|
||||
() => mockUserApiRepo.createProfileImage(name: profileImagePath, data: Uint8List(0)),
|
||||
).thenAnswer((_) async => profileImagePath);
|
||||
when(() => mockStoreService.put(StoreKey.currentUser, updatedUser)).thenAnswer((_) async => true);
|
||||
|
||||
final result = await sut.createProfileImage(profileImagePath, Uint8List(0));
|
||||
|
||||
verify(() => mockStoreService.put(StoreKey.currentUser, updatedUser)).called(1);
|
||||
verify(() => mockAuthUserRepo.upsert(UserStub.admin)).called(1);
|
||||
expect(result, profileImagePath);
|
||||
});
|
||||
|
||||
test('should return null if profile image creation fails', () async {
|
||||
const profileImagePath = 'profile.jpg';
|
||||
final updatedUser = UserStub.admin;
|
||||
|
||||
when(
|
||||
() => mockUserApiRepo.createProfileImage(name: profileImagePath, data: Uint8List(0)),
|
||||
).thenThrow(Exception('Failed to create profile image'));
|
||||
|
||||
final result = await sut.createProfileImage(profileImagePath, Uint8List(0));
|
||||
verifyNever(() => mockStoreService.put(StoreKey.currentUser, updatedUser));
|
||||
verifyNever(() => mockAuthUserRepo.upsert(any()));
|
||||
expect(result, isNull);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,17 +4,13 @@ import 'package:drift/drift.dart' hide isNull;
|
||||
import 'package:drift/native.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:immich_mobile/domain/models/store.model.dart';
|
||||
import 'package:immich_mobile/domain/models/user.model.dart';
|
||||
import 'package:immich_mobile/infrastructure/entities/store.entity.drift.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/store.repository.dart';
|
||||
|
||||
import '../../fixtures/user.stub.dart';
|
||||
|
||||
const _kTestAccessToken = "#TestToken";
|
||||
const _kTestVersion = 10;
|
||||
const _kTestAdvancedTroubleshooting = false;
|
||||
final _kTestUser = UserStub.admin;
|
||||
|
||||
Future<void> _populateStore(Drift db) async {
|
||||
await db.batch((batch) async {
|
||||
@@ -82,14 +78,6 @@ void main() {
|
||||
advancedTroubleshooting = await sut.tryGet(StoreKey.advancedTroubleshooting);
|
||||
expect(advancedTroubleshooting, _kTestAdvancedTroubleshooting);
|
||||
});
|
||||
|
||||
test('converts user', () async {
|
||||
UserDto? user = await sut.tryGet(StoreKey.currentUser);
|
||||
expect(user, isNull);
|
||||
await sut.upsert(StoreKey.currentUser, _kTestUser);
|
||||
user = await sut.tryGet(StoreKey.currentUser);
|
||||
expect(user, _kTestUser);
|
||||
});
|
||||
});
|
||||
|
||||
group('Store Repository Deletes:', () {
|
||||
|
||||
@@ -48,6 +48,8 @@ class MockSyncMigrationRepository extends Mock implements SyncMigrationRepositor
|
||||
|
||||
class MockUserRepository extends Mock implements UserRepository {}
|
||||
|
||||
class MockDriftAuthUserRepository extends Mock implements DriftAuthUserRepository {}
|
||||
|
||||
class MockPartnerRepository extends Mock implements PartnerRepository {}
|
||||
|
||||
// API Repos
|
||||
|
||||
@@ -60,7 +60,7 @@ void main() {
|
||||
when(() => actionService.editDateTime(any(), any())).thenAnswer((_) async => true);
|
||||
when(() => assetService.watchAsset(any())).thenAnswer((_) => const Stream.empty());
|
||||
when(() => assetService.getExif(any())).thenAnswer((_) async => null);
|
||||
when(() => userService.tryGetMyUser()).thenReturn(_user);
|
||||
when(() => userService.tryGetMyUser()).thenAnswer((_) async => _user);
|
||||
when(() => userService.watchMyUser()).thenAnswer((_) => const Stream.empty());
|
||||
|
||||
container = ProviderContainer(
|
||||
|
||||
Reference in New Issue
Block a user