mirror of
https://github.com/immich-app/immich.git
synced 2025-05-24 01:12:58 -04:00
refactor(mobile): move timeline methods to timeline repo (#16526)
* refactor: move timeline calls to timeline repo * refactor: review changes --------- Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
This commit is contained in:
parent
3d6a6f77a8
commit
4db8f0c666
@ -3,6 +3,10 @@ import 'package:immich_mobile/entities/asset.entity.dart';
|
|||||||
import 'package:immich_mobile/widgets/asset_grid/asset_grid_data_structure.dart';
|
import 'package:immich_mobile/widgets/asset_grid/asset_grid_data_structure.dart';
|
||||||
|
|
||||||
abstract class ITimelineRepository {
|
abstract class ITimelineRepository {
|
||||||
|
Future<List<int>> getTimelineUserIds(int id);
|
||||||
|
|
||||||
|
Stream<List<int>> watchTimelineUsers(int id);
|
||||||
|
|
||||||
Stream<RenderList> watchArchiveTimeline(int userId);
|
Stream<RenderList> watchArchiveTimeline(int userId);
|
||||||
Stream<RenderList> watchFavoriteTimeline(int userId);
|
Stream<RenderList> watchFavoriteTimeline(int userId);
|
||||||
Stream<RenderList> watchTrashTimeline(int userId);
|
Stream<RenderList> watchTrashTimeline(int userId);
|
||||||
|
@ -22,10 +22,6 @@ abstract interface class IUserRepository implements IDatabaseRepository {
|
|||||||
Future<User> me();
|
Future<User> me();
|
||||||
|
|
||||||
Future<void> clearTable();
|
Future<void> clearTable();
|
||||||
|
|
||||||
Future<List<int>> getTimelineUserIds(int id);
|
|
||||||
|
|
||||||
Stream<List<int>> watchTimelineUsers(int id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum UserSort { id }
|
enum UserSort { id }
|
||||||
|
@ -59,7 +59,11 @@ class AssetNotifier extends StateNotifier<bool> {
|
|||||||
await clearAllAssets();
|
await clearAllAssets();
|
||||||
log.info("Manual refresh requested, cleared assets and albums from db");
|
log.info("Manual refresh requested, cleared assets and albums from db");
|
||||||
}
|
}
|
||||||
final bool changedUsers = await _userService.refreshUsers();
|
final users = await _userService.getUsersFromServer();
|
||||||
|
bool changedUsers = false;
|
||||||
|
if (users != null) {
|
||||||
|
changedUsers = await _syncService.syncUsersFromServer(users);
|
||||||
|
}
|
||||||
final bool newRemote = await _assetService.refreshRemoteAssets();
|
final bool newRemote = await _assetService.refreshRemoteAssets();
|
||||||
final bool newLocal = await _albumService.refreshDeviceAlbums();
|
final bool newLocal = await _albumService.refreshDeviceAlbums();
|
||||||
debugPrint(
|
debugPrint(
|
||||||
|
@ -6,7 +6,7 @@ import 'package:immich_mobile/entities/store.entity.dart';
|
|||||||
import 'package:immich_mobile/entities/user.entity.dart';
|
import 'package:immich_mobile/entities/user.entity.dart';
|
||||||
import 'package:immich_mobile/providers/api.provider.dart';
|
import 'package:immich_mobile/providers/api.provider.dart';
|
||||||
import 'package:immich_mobile/services/api.service.dart';
|
import 'package:immich_mobile/services/api.service.dart';
|
||||||
import 'package:immich_mobile/services/user.service.dart';
|
import 'package:immich_mobile/services/timeline.service.dart';
|
||||||
|
|
||||||
class CurrentUserProvider extends StateNotifier<User?> {
|
class CurrentUserProvider extends StateNotifier<User?> {
|
||||||
CurrentUserProvider(this._apiService) : super(null) {
|
CurrentUserProvider(this._apiService) : super(null) {
|
||||||
@ -46,14 +46,15 @@ final currentUserProvider =
|
|||||||
});
|
});
|
||||||
|
|
||||||
class TimelineUserIdsProvider extends StateNotifier<List<int>> {
|
class TimelineUserIdsProvider extends StateNotifier<List<int>> {
|
||||||
TimelineUserIdsProvider(this._userService) : super([]) {
|
TimelineUserIdsProvider(this._timelineService) : super([]) {
|
||||||
_userService.getTimelineUserIds().then((users) => state = users);
|
_timelineService.getTimelineUserIds().then((users) => state = users);
|
||||||
streamSub =
|
streamSub = _timelineService
|
||||||
_userService.watchTimelineUserIds().listen((users) => state = users);
|
.watchTimelineUserIds()
|
||||||
|
.listen((users) => state = users);
|
||||||
}
|
}
|
||||||
|
|
||||||
late final StreamSubscription<List<int>> streamSub;
|
late final StreamSubscription<List<int>> streamSub;
|
||||||
final UserService _userService;
|
final TimelineService _timelineService;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
@ -64,5 +65,5 @@ class TimelineUserIdsProvider extends StateNotifier<List<int>> {
|
|||||||
|
|
||||||
final timelineUsersIdsProvider =
|
final timelineUsersIdsProvider =
|
||||||
StateNotifierProvider<TimelineUserIdsProvider, List<int>>((ref) {
|
StateNotifierProvider<TimelineUserIdsProvider, List<int>>((ref) {
|
||||||
return TimelineUserIdsProvider(ref.watch(userServiceProvider));
|
return TimelineUserIdsProvider(ref.watch(timelineServiceProvider));
|
||||||
});
|
});
|
||||||
|
@ -2,6 +2,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|||||||
import 'package:immich_mobile/constants/enums.dart';
|
import 'package:immich_mobile/constants/enums.dart';
|
||||||
import 'package:immich_mobile/entities/album.entity.dart';
|
import 'package:immich_mobile/entities/album.entity.dart';
|
||||||
import 'package:immich_mobile/entities/asset.entity.dart';
|
import 'package:immich_mobile/entities/asset.entity.dart';
|
||||||
|
import 'package:immich_mobile/entities/user.entity.dart';
|
||||||
import 'package:immich_mobile/interfaces/timeline.interface.dart';
|
import 'package:immich_mobile/interfaces/timeline.interface.dart';
|
||||||
import 'package:immich_mobile/providers/db.provider.dart';
|
import 'package:immich_mobile/providers/db.provider.dart';
|
||||||
import 'package:immich_mobile/repositories/database.repository.dart';
|
import 'package:immich_mobile/repositories/database.repository.dart';
|
||||||
@ -15,6 +16,28 @@ class TimelineRepository extends DatabaseRepository
|
|||||||
implements ITimelineRepository {
|
implements ITimelineRepository {
|
||||||
TimelineRepository(super.db);
|
TimelineRepository(super.db);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<List<int>> getTimelineUserIds(int id) {
|
||||||
|
return db.users
|
||||||
|
.filter()
|
||||||
|
.inTimelineEqualTo(true)
|
||||||
|
.or()
|
||||||
|
.isarIdEqualTo(id)
|
||||||
|
.isarIdProperty()
|
||||||
|
.findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Stream<List<int>> watchTimelineUsers(int id) {
|
||||||
|
return db.users
|
||||||
|
.filter()
|
||||||
|
.inTimelineEqualTo(true)
|
||||||
|
.or()
|
||||||
|
.isarIdEqualTo(id)
|
||||||
|
.isarIdProperty()
|
||||||
|
.watch();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Stream<RenderList> watchArchiveTimeline(int userId) {
|
Stream<RenderList> watchArchiveTimeline(int userId) {
|
||||||
final query = db.assets
|
final query = db.assets
|
||||||
|
@ -70,26 +70,4 @@ class UserRepository extends DatabaseRepository implements IUserRepository {
|
|||||||
await db.users.clear();
|
await db.users.clear();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<List<int>> getTimelineUserIds(int id) {
|
|
||||||
return db.users
|
|
||||||
.filter()
|
|
||||||
.inTimelineEqualTo(true)
|
|
||||||
.or()
|
|
||||||
.isarIdEqualTo(id)
|
|
||||||
.isarIdProperty()
|
|
||||||
.findAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Stream<List<int>> watchTimelineUsers(int id) {
|
|
||||||
return db.users
|
|
||||||
.filter()
|
|
||||||
.inTimelineEqualTo(true)
|
|
||||||
.or()
|
|
||||||
.isarIdEqualTo(id)
|
|
||||||
.isarIdProperty()
|
|
||||||
.watch();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -169,7 +169,10 @@ class AlbumService {
|
|||||||
final Stopwatch sw = Stopwatch()..start();
|
final Stopwatch sw = Stopwatch()..start();
|
||||||
bool changes = false;
|
bool changes = false;
|
||||||
try {
|
try {
|
||||||
await _userService.refreshUsers();
|
final users = await _userService.getUsersFromServer();
|
||||||
|
if (users != null) {
|
||||||
|
await _syncService.syncUsersFromServer(users);
|
||||||
|
}
|
||||||
final (sharedAlbum, ownedAlbum) = await (
|
final (sharedAlbum, ownedAlbum) = await (
|
||||||
// Note: `shared: true` is required to get albums that don't belong to
|
// Note: `shared: true` is required to get albums that don't belong to
|
||||||
// us due to unusual behaviour on the API but this will also return our
|
// us due to unusual behaviour on the API but this will also return our
|
||||||
|
@ -410,7 +410,6 @@ class BackgroundService {
|
|||||||
partnerApiRepository,
|
partnerApiRepository,
|
||||||
userApiRepository,
|
userApiRepository,
|
||||||
userRepository,
|
userRepository,
|
||||||
syncSerive,
|
|
||||||
);
|
);
|
||||||
AlbumService albumService = AlbumService(
|
AlbumService albumService = AlbumService(
|
||||||
userService,
|
userService,
|
||||||
|
@ -6,6 +6,7 @@ import 'package:immich_mobile/entities/album.entity.dart';
|
|||||||
import 'package:immich_mobile/entities/asset.entity.dart';
|
import 'package:immich_mobile/entities/asset.entity.dart';
|
||||||
import 'package:immich_mobile/entities/etag.entity.dart';
|
import 'package:immich_mobile/entities/etag.entity.dart';
|
||||||
import 'package:immich_mobile/entities/user.entity.dart';
|
import 'package:immich_mobile/entities/user.entity.dart';
|
||||||
|
import 'package:immich_mobile/extensions/collection_extensions.dart';
|
||||||
import 'package:immich_mobile/interfaces/album.interface.dart';
|
import 'package:immich_mobile/interfaces/album.interface.dart';
|
||||||
import 'package:immich_mobile/interfaces/album_api.interface.dart';
|
import 'package:immich_mobile/interfaces/album_api.interface.dart';
|
||||||
import 'package:immich_mobile/interfaces/album_media.interface.dart';
|
import 'package:immich_mobile/interfaces/album_media.interface.dart';
|
||||||
@ -23,7 +24,6 @@ import 'package:immich_mobile/repositories/user.repository.dart';
|
|||||||
import 'package:immich_mobile/services/entity.service.dart';
|
import 'package:immich_mobile/services/entity.service.dart';
|
||||||
import 'package:immich_mobile/services/hash.service.dart';
|
import 'package:immich_mobile/services/hash.service.dart';
|
||||||
import 'package:immich_mobile/utils/async_mutex.dart';
|
import 'package:immich_mobile/utils/async_mutex.dart';
|
||||||
import 'package:immich_mobile/extensions/collection_extensions.dart';
|
|
||||||
import 'package:immich_mobile/utils/datetime_comparison.dart';
|
import 'package:immich_mobile/utils/datetime_comparison.dart';
|
||||||
import 'package:immich_mobile/utils/diff.dart';
|
import 'package:immich_mobile/utils/diff.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
|
@ -21,12 +21,23 @@ class TimelineService {
|
|||||||
final ITimelineRepository _timelineRepository;
|
final ITimelineRepository _timelineRepository;
|
||||||
final IUserRepository _userRepository;
|
final IUserRepository _userRepository;
|
||||||
final AppSettingsService _appSettingsService;
|
final AppSettingsService _appSettingsService;
|
||||||
TimelineService(
|
|
||||||
|
const TimelineService(
|
||||||
this._timelineRepository,
|
this._timelineRepository,
|
||||||
this._userRepository,
|
this._userRepository,
|
||||||
this._appSettingsService,
|
this._appSettingsService,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Future<List<int>> getTimelineUserIds() async {
|
||||||
|
final me = await _userRepository.me();
|
||||||
|
return _timelineRepository.getTimelineUserIds(me.isarId);
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream<List<int>> watchTimelineUserIds() async* {
|
||||||
|
final me = await _userRepository.me();
|
||||||
|
yield* _timelineRepository.watchTimelineUsers(me.isarId);
|
||||||
|
}
|
||||||
|
|
||||||
Stream<RenderList> watchHomeTimeline(int userId) {
|
Stream<RenderList> watchHomeTimeline(int userId) {
|
||||||
return _timelineRepository.watchHomeTimeline(userId, _getGroupByOption());
|
return _timelineRepository.watchHomeTimeline(userId, _getGroupByOption());
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:image_picker/image_picker.dart';
|
import 'package:image_picker/image_picker.dart';
|
||||||
|
import 'package:immich_mobile/entities/user.entity.dart';
|
||||||
import 'package:immich_mobile/interfaces/partner_api.interface.dart';
|
import 'package:immich_mobile/interfaces/partner_api.interface.dart';
|
||||||
import 'package:immich_mobile/interfaces/user.interface.dart';
|
import 'package:immich_mobile/interfaces/user.interface.dart';
|
||||||
import 'package:immich_mobile/interfaces/user_api.interface.dart';
|
import 'package:immich_mobile/interfaces/user_api.interface.dart';
|
||||||
import 'package:immich_mobile/repositories/partner_api.repository.dart';
|
import 'package:immich_mobile/repositories/partner_api.repository.dart';
|
||||||
import 'package:immich_mobile/repositories/user.repository.dart';
|
import 'package:immich_mobile/repositories/user.repository.dart';
|
||||||
import 'package:immich_mobile/repositories/user_api.repository.dart';
|
import 'package:immich_mobile/repositories/user_api.repository.dart';
|
||||||
import 'package:immich_mobile/entities/user.entity.dart';
|
|
||||||
import 'package:immich_mobile/services/sync.service.dart';
|
|
||||||
import 'package:immich_mobile/utils/diff.dart';
|
import 'package:immich_mobile/utils/diff.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
|
|
||||||
@ -17,7 +16,6 @@ final userServiceProvider = Provider(
|
|||||||
ref.watch(partnerApiRepositoryProvider),
|
ref.watch(partnerApiRepositoryProvider),
|
||||||
ref.watch(userApiRepositoryProvider),
|
ref.watch(userApiRepositoryProvider),
|
||||||
ref.watch(userRepositoryProvider),
|
ref.watch(userRepositoryProvider),
|
||||||
ref.watch(syncServiceProvider),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -25,14 +23,12 @@ class UserService {
|
|||||||
final IPartnerApiRepository _partnerApiRepository;
|
final IPartnerApiRepository _partnerApiRepository;
|
||||||
final IUserApiRepository _userApiRepository;
|
final IUserApiRepository _userApiRepository;
|
||||||
final IUserRepository _userRepository;
|
final IUserRepository _userRepository;
|
||||||
final SyncService _syncService;
|
|
||||||
final Logger _log = Logger("UserService");
|
final Logger _log = Logger("UserService");
|
||||||
|
|
||||||
UserService(
|
UserService(
|
||||||
this._partnerApiRepository,
|
this._partnerApiRepository,
|
||||||
this._userApiRepository,
|
this._userApiRepository,
|
||||||
this._userRepository,
|
this._userRepository,
|
||||||
this._syncService,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Future<List<User>> getUsers({bool self = false}) {
|
Future<List<User>> getUsers({bool self = false}) {
|
||||||
@ -98,23 +94,7 @@ class UserService {
|
|||||||
return users;
|
return users;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> refreshUsers() async {
|
|
||||||
final users = await getUsersFromServer();
|
|
||||||
if (users == null) return false;
|
|
||||||
return _syncService.syncUsersFromServer(users);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> clearTable() {
|
Future<void> clearTable() {
|
||||||
return _userRepository.clearTable();
|
return _userRepository.clearTable();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<int>> getTimelineUserIds() async {
|
|
||||||
final me = await _userRepository.me();
|
|
||||||
return _userRepository.getTimelineUserIds(me.isarId);
|
|
||||||
}
|
|
||||||
|
|
||||||
Stream<List<int>> watchTimelineUserIds() async* {
|
|
||||||
final me = await _userRepository.me();
|
|
||||||
yield* _userRepository.watchTimelineUsers(me.isarId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ import 'package:flutter_test/flutter_test.dart';
|
|||||||
import 'package:immich_mobile/entities/backup_album.entity.dart';
|
import 'package:immich_mobile/entities/backup_album.entity.dart';
|
||||||
import 'package:immich_mobile/services/album.service.dart';
|
import 'package:immich_mobile/services/album.service.dart';
|
||||||
import 'package:mocktail/mocktail.dart';
|
import 'package:mocktail/mocktail.dart';
|
||||||
|
|
||||||
import '../fixtures/album.stub.dart';
|
import '../fixtures/album.stub.dart';
|
||||||
import '../fixtures/asset.stub.dart';
|
import '../fixtures/asset.stub.dart';
|
||||||
import '../fixtures/user.stub.dart';
|
import '../fixtures/user.stub.dart';
|
||||||
@ -83,7 +84,9 @@ void main() {
|
|||||||
|
|
||||||
group('refreshRemoteAlbums', () {
|
group('refreshRemoteAlbums', () {
|
||||||
test('is working', () async {
|
test('is working', () async {
|
||||||
when(() => userService.refreshUsers()).thenAnswer((_) async => true);
|
when(() => userService.getUsersFromServer()).thenAnswer((_) async => []);
|
||||||
|
when(() => syncService.syncUsersFromServer(any()))
|
||||||
|
.thenAnswer((_) async => true);
|
||||||
when(() => albumApiRepository.getAll(shared: true))
|
when(() => albumApiRepository.getAll(shared: true))
|
||||||
.thenAnswer((_) async => [AlbumStub.sharedWithUser]);
|
.thenAnswer((_) async => [AlbumStub.sharedWithUser]);
|
||||||
|
|
||||||
@ -99,7 +102,8 @@ void main() {
|
|||||||
).thenAnswer((_) async => true);
|
).thenAnswer((_) async => true);
|
||||||
final result = await sut.refreshRemoteAlbums();
|
final result = await sut.refreshRemoteAlbums();
|
||||||
expect(result, true);
|
expect(result, true);
|
||||||
verify(() => userService.refreshUsers()).called(1);
|
verify(() => userService.getUsersFromServer()).called(1);
|
||||||
|
verify(() => syncService.syncUsersFromServer([])).called(1);
|
||||||
verify(() => albumApiRepository.getAll(shared: true)).called(1);
|
verify(() => albumApiRepository.getAll(shared: true)).called(1);
|
||||||
verify(() => albumApiRepository.getAll(shared: null)).called(1);
|
verify(() => albumApiRepository.getAll(shared: null)).called(1);
|
||||||
verify(
|
verify(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user