mirror of
https://github.com/immich-app/immich.git
synced 2025-04-21 07:26:25 +02:00
refactor(mobile): render list (#16239)
* refactor(mobile): trash provider * refactor(mobile): trash provider * pr feedback * archive timeline * favorite * album * trash timeline * all videos timeline * refactor * refactor: home timeline and partner timeline * update analysis option
This commit is contained in:
parent
616905211d
commit
5acf6868b7
24 changed files with 284 additions and 196 deletions
mobile
analysis_options.yaml
lib
interfaces
pages
album
library
photos
search
providers
album
archive.provider.dartasset.provider.dartfavorite.provider.dartsearch
timeline.provider.darttrash.provider.dartrepositories
services
|
@ -65,7 +65,7 @@ custom_lint:
|
|||
allowed:
|
||||
# required / wanted
|
||||
- lib/entities/*.entity.dart
|
||||
- lib/repositories/{album,asset,backup,database,etag,exif_info,user}.repository.dart
|
||||
- lib/repositories/{album,asset,backup,database,etag,exif_info,user,timeline}.repository.dart
|
||||
- lib/infrastructure/entities/*.entity.dart
|
||||
- lib/infrastructure/repositories/{store,db}.repository.dart
|
||||
- lib/providers/infrastructure/db.provider.dart
|
||||
|
@ -79,7 +79,7 @@ custom_lint:
|
|||
- lib/widgets/asset_grid/asset_grid_data_structure.dart
|
||||
- test/**.dart
|
||||
# refactor the remaining providers
|
||||
- lib/providers/{archive,asset,authentication,db,favorite,partner,user}.provider.dart
|
||||
- lib/providers/{asset,authentication,db,partner,user}.provider.dart
|
||||
- lib/providers/{asset_viewer/render_list,backup/backup,search/all_motion_photos,search/recently_added_asset}.provider.dart
|
||||
|
||||
- import_rule_openapi:
|
||||
|
|
|
@ -3,7 +3,6 @@ import 'package:immich_mobile/entities/asset.entity.dart';
|
|||
import 'package:immich_mobile/entities/user.entity.dart';
|
||||
import 'package:immich_mobile/interfaces/database.interface.dart';
|
||||
import 'package:immich_mobile/models/albums/album_search.model.dart';
|
||||
import 'package:immich_mobile/widgets/asset_grid/asset_grid_data_structure.dart';
|
||||
|
||||
abstract interface class IAlbumRepository implements IDatabaseRepository {
|
||||
Future<Album> create(Album album);
|
||||
|
@ -50,8 +49,6 @@ abstract interface class IAlbumRepository implements IDatabaseRepository {
|
|||
|
||||
Stream<Album?> watchAlbum(int id);
|
||||
|
||||
Stream<RenderList> getRenderListStream(Album album);
|
||||
|
||||
Future<void> clearTable();
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@ import 'package:immich_mobile/entities/album.entity.dart';
|
|||
import 'package:immich_mobile/entities/asset.entity.dart';
|
||||
import 'package:immich_mobile/entities/device_asset.entity.dart';
|
||||
import 'package:immich_mobile/interfaces/database.interface.dart';
|
||||
import 'package:immich_mobile/widgets/asset_grid/asset_grid_data_structure.dart';
|
||||
|
||||
abstract interface class IAssetRepository implements IDatabaseRepository {
|
||||
Future<Asset?> getByRemoteId(String id);
|
||||
|
@ -66,8 +65,6 @@ abstract interface class IAssetRepository implements IDatabaseRepository {
|
|||
Stream<Asset?> watchAsset(int id, {bool fireImmediately = false});
|
||||
|
||||
Future<List<Asset>> getTrashAssets(int userId);
|
||||
|
||||
Stream<RenderList> getTrashRenderListStream(int userId);
|
||||
}
|
||||
|
||||
enum AssetSort { checksum, ownerIdChecksum }
|
||||
|
|
16
mobile/lib/interfaces/timeline.interface.dart
Normal file
16
mobile/lib/interfaces/timeline.interface.dart
Normal file
|
@ -0,0 +1,16 @@
|
|||
import 'package:immich_mobile/entities/album.entity.dart';
|
||||
import 'package:immich_mobile/widgets/asset_grid/asset_grid_data_structure.dart';
|
||||
|
||||
abstract class ITimelineRepository {
|
||||
Stream<RenderList> watchArchiveTimeline(int userId);
|
||||
Stream<RenderList> watchFavoriteTimeline(int userId);
|
||||
Stream<RenderList> watchTrashTimeline(int userId);
|
||||
Stream<RenderList> watchAlbumTimeline(Album album);
|
||||
Stream<RenderList> watchAllVideosTimeline();
|
||||
|
||||
Stream<RenderList> watchHomeTimeline(int userId, GroupAssetsBy groupAssetsBy);
|
||||
Stream<RenderList> watchMultiUsersTimeline(
|
||||
List<int> userIds,
|
||||
GroupAssetsBy groupAssetsBy,
|
||||
);
|
||||
}
|
|
@ -14,6 +14,7 @@ import 'package:immich_mobile/pages/album/album_shared_user_icons.dart';
|
|||
import 'package:immich_mobile/pages/album/album_title.dart';
|
||||
import 'package:immich_mobile/providers/album/album.provider.dart';
|
||||
import 'package:immich_mobile/providers/album/current_album.provider.dart';
|
||||
import 'package:immich_mobile/providers/timeline.provider.dart';
|
||||
import 'package:immich_mobile/utils/immich_loading_overlay.dart';
|
||||
import 'package:immich_mobile/providers/multiselect.provider.dart';
|
||||
import 'package:immich_mobile/providers/auth.provider.dart';
|
||||
|
@ -104,7 +105,7 @@ class AlbumViewer extends HookConsumerWidget {
|
|||
children: [
|
||||
MultiselectGrid(
|
||||
key: const ValueKey("albumViewerMultiselectGrid"),
|
||||
renderListProvider: albumRenderlistProvider(album.id),
|
||||
renderListProvider: albumTimelineProvider(album.id),
|
||||
topWidget: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
|
|
|
@ -2,8 +2,8 @@ import 'package:auto_route/auto_route.dart';
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/providers/archive.provider.dart';
|
||||
import 'package:immich_mobile/providers/multiselect.provider.dart';
|
||||
import 'package:immich_mobile/providers/timeline.provider.dart';
|
||||
import 'package:immich_mobile/widgets/asset_grid/multiselect_grid.dart';
|
||||
|
||||
@RoutePage()
|
||||
|
@ -13,8 +13,8 @@ class ArchivePage extends HookConsumerWidget {
|
|||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
AppBar buildAppBar() {
|
||||
final archivedAssets = ref.watch(archiveProvider);
|
||||
final count = archivedAssets.value?.totalAssets.toString() ?? "?";
|
||||
final archiveRenderList = ref.watch(archiveTimelineProvider);
|
||||
final count = archiveRenderList.value?.totalAssets.toString() ?? "?";
|
||||
return AppBar(
|
||||
leading: IconButton(
|
||||
onPressed: () => context.maybePop(),
|
||||
|
@ -31,7 +31,7 @@ class ArchivePage extends HookConsumerWidget {
|
|||
return Scaffold(
|
||||
appBar: ref.watch(multiselectProvider) ? null : buildAppBar(),
|
||||
body: MultiselectGrid(
|
||||
renderListProvider: archiveProvider,
|
||||
renderListProvider: archiveTimelineProvider,
|
||||
unarchive: true,
|
||||
archiveEnabled: true,
|
||||
deleteEnabled: true,
|
||||
|
|
|
@ -2,8 +2,8 @@ import 'package:auto_route/auto_route.dart';
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/providers/favorite.provider.dart';
|
||||
import 'package:immich_mobile/providers/multiselect.provider.dart';
|
||||
import 'package:immich_mobile/providers/timeline.provider.dart';
|
||||
import 'package:immich_mobile/widgets/asset_grid/multiselect_grid.dart';
|
||||
|
||||
@RoutePage()
|
||||
|
@ -29,7 +29,7 @@ class FavoritesPage extends HookConsumerWidget {
|
|||
return Scaffold(
|
||||
appBar: ref.watch(multiselectProvider) ? null : buildAppBar(),
|
||||
body: MultiselectGrid(
|
||||
renderListProvider: favoriteAssetsProvider,
|
||||
renderListProvider: favoriteTimelineProvider,
|
||||
favoriteEnabled: true,
|
||||
editEnabled: true,
|
||||
unfavorite: true,
|
||||
|
|
|
@ -7,6 +7,7 @@ import 'package:immich_mobile/providers/multiselect.provider.dart';
|
|||
import 'package:immich_mobile/providers/partner.provider.dart';
|
||||
import 'package:immich_mobile/entities/user.entity.dart';
|
||||
import 'package:immich_mobile/providers/asset.provider.dart';
|
||||
import 'package:immich_mobile/providers/timeline.provider.dart';
|
||||
import 'package:immich_mobile/widgets/asset_grid/multiselect_grid.dart';
|
||||
import 'package:immich_mobile/widgets/common/immich_toast.dart';
|
||||
|
||||
|
@ -110,7 +111,7 @@ class PartnerDetailPage extends HookConsumerWidget {
|
|||
),
|
||||
),
|
||||
),
|
||||
renderListProvider: assetsProvider(partner.isarId),
|
||||
renderListProvider: singleUserTimelineProvider(partner.isarId),
|
||||
onRefresh: () => ref.read(assetProvider.notifier).getAllAsset(),
|
||||
deleteEnabled: false,
|
||||
favoriteEnabled: false,
|
||||
|
|
|
@ -7,6 +7,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|||
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/providers/asset.provider.dart';
|
||||
import 'package:immich_mobile/providers/timeline.provider.dart';
|
||||
import 'package:immich_mobile/widgets/asset_grid/immich_asset_grid.dart';
|
||||
import 'package:immich_mobile/widgets/asset_grid/delete_dialog.dart';
|
||||
import 'package:immich_mobile/providers/trash.provider.dart';
|
||||
|
@ -22,7 +23,7 @@ class TrashPage extends HookConsumerWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final trashedAssets = ref.watch(trashedAssetsProvider);
|
||||
final trashRenderList = ref.watch(trashTimelineProvider);
|
||||
final trashDays =
|
||||
ref.watch(serverInfoProvider.select((v) => v.serverConfig.trashDays));
|
||||
final selectionEnabledHook = useState(false);
|
||||
|
@ -234,11 +235,11 @@ class TrashPage extends HookConsumerWidget {
|
|||
}
|
||||
|
||||
return Scaffold(
|
||||
appBar: trashedAssets.maybeWhen(
|
||||
appBar: trashRenderList.maybeWhen(
|
||||
orElse: () => buildAppBar("?"),
|
||||
data: (data) => buildAppBar(data.totalAssets.toString()),
|
||||
),
|
||||
body: trashedAssets.widgetWhen(
|
||||
body: trashRenderList.widgetWhen(
|
||||
onData: (data) => data.isEmpty
|
||||
? Center(
|
||||
child: Text('trash_page_no_assets'.tr()),
|
||||
|
|
|
@ -8,6 +8,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/providers/album/album.provider.dart';
|
||||
import 'package:immich_mobile/providers/multiselect.provider.dart';
|
||||
import 'package:immich_mobile/providers/timeline.provider.dart';
|
||||
import 'package:immich_mobile/widgets/memories/memory_lane.dart';
|
||||
import 'package:immich_mobile/providers/asset.provider.dart';
|
||||
import 'package:immich_mobile/providers/server_info.provider.dart';
|
||||
|
@ -108,8 +109,8 @@ class PhotosPage extends HookConsumerWidget {
|
|||
? const MemoryLane()
|
||||
: const SizedBox(),
|
||||
renderListProvider: timelineUsers.length > 1
|
||||
? multiUserAssetsProvider(timelineUsers)
|
||||
: assetsProvider(currentUser?.isarId),
|
||||
? multiUsersTimelineProvider(timelineUsers)
|
||||
: singleUserTimelineProvider(currentUser!.isarId),
|
||||
buildLoadingIndicator: buildLoadingIndicator,
|
||||
onRefresh: refreshAssets,
|
||||
stackEnabled: true,
|
||||
|
|
|
@ -2,7 +2,7 @@ import 'package:auto_route/auto_route.dart';
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/providers/search/all_video_assets.provider.dart';
|
||||
import 'package:immich_mobile/providers/timeline.provider.dart';
|
||||
import 'package:immich_mobile/widgets/asset_grid/multiselect_grid.dart';
|
||||
|
||||
@RoutePage()
|
||||
|
@ -19,7 +19,7 @@ class AllVideosPage extends HookConsumerWidget {
|
|||
icon: const Icon(Icons.arrow_back_ios_rounded),
|
||||
),
|
||||
),
|
||||
body: MultiselectGrid(renderListProvider: allVideoAssetsProvider),
|
||||
body: MultiselectGrid(renderListProvider: allVideosTimelineProvider),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ import 'package:immich_mobile/constants/enums.dart';
|
|||
import 'package:immich_mobile/entities/user.entity.dart';
|
||||
import 'package:immich_mobile/models/albums/album_search.model.dart';
|
||||
import 'package:immich_mobile/services/album.service.dart';
|
||||
import 'package:immich_mobile/widgets/asset_grid/asset_grid_data_structure.dart';
|
||||
import 'package:immich_mobile/entities/asset.entity.dart';
|
||||
import 'package:immich_mobile/entities/album.entity.dart';
|
||||
|
||||
|
@ -152,17 +151,6 @@ final albumWatcher =
|
|||
}
|
||||
});
|
||||
|
||||
final albumRenderlistProvider =
|
||||
StreamProvider.autoDispose.family<RenderList, int>((ref, id) {
|
||||
final album = ref.watch(albumWatcher(id)).value;
|
||||
|
||||
if (album != null) {
|
||||
return ref.watch(albumServiceProvider).getRenderListGenerator(album);
|
||||
}
|
||||
|
||||
return const Stream.empty();
|
||||
});
|
||||
|
||||
class LocalAlbumsNotifier extends StateNotifier<List<Album>> {
|
||||
LocalAlbumsNotifier(this.albumService) : super([]) {
|
||||
albumService.getAllLocalAlbums().then((value) {
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/widgets/asset_grid/asset_grid_data_structure.dart';
|
||||
import 'package:immich_mobile/entities/asset.entity.dart';
|
||||
import 'package:immich_mobile/providers/db.provider.dart';
|
||||
import 'package:immich_mobile/providers/user.provider.dart';
|
||||
import 'package:immich_mobile/utils/renderlist_generator.dart';
|
||||
import 'package:isar/isar.dart';
|
||||
|
||||
final archiveProvider = StreamProvider<RenderList>((ref) {
|
||||
final user = ref.watch(currentUserProvider);
|
||||
if (user == null) return const Stream.empty();
|
||||
final query = ref
|
||||
.watch(dbProvider)
|
||||
.assets
|
||||
.where()
|
||||
.ownerIdEqualToAnyChecksum(user.isarId)
|
||||
.filter()
|
||||
.isArchivedEqualTo(true)
|
||||
.isTrashedEqualTo(false)
|
||||
.sortByFileCreatedAtDesc();
|
||||
return renderListGenerator(query, ref);
|
||||
});
|
|
@ -4,7 +4,6 @@ import 'package:immich_mobile/domain/models/store.model.dart';
|
|||
import 'package:immich_mobile/entities/asset.entity.dart';
|
||||
import 'package:immich_mobile/entities/store.entity.dart';
|
||||
import 'package:immich_mobile/providers/db.provider.dart';
|
||||
import 'package:immich_mobile/providers/locale_provider.dart';
|
||||
import 'package:immich_mobile/providers/memory.provider.dart';
|
||||
import 'package:immich_mobile/providers/user.provider.dart';
|
||||
import 'package:immich_mobile/services/album.service.dart';
|
||||
|
@ -13,8 +12,6 @@ import 'package:immich_mobile/services/etag.service.dart';
|
|||
import 'package:immich_mobile/services/exif.service.dart';
|
||||
import 'package:immich_mobile/services/sync.service.dart';
|
||||
import 'package:immich_mobile/services/user.service.dart';
|
||||
import 'package:immich_mobile/utils/renderlist_generator.dart';
|
||||
import 'package:immich_mobile/widgets/asset_grid/asset_grid_data_structure.dart';
|
||||
import 'package:isar/isar.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
|
||||
|
@ -188,47 +185,6 @@ final assetWatcher =
|
|||
return assetService.watchAsset(asset.id, fireImmediately: true);
|
||||
});
|
||||
|
||||
final assetsProvider = StreamProvider.family<RenderList, int?>(
|
||||
(ref, userId) {
|
||||
if (userId == null) return const Stream.empty();
|
||||
ref.watch(localeProvider);
|
||||
|
||||
final query = ref
|
||||
.watch(dbProvider)
|
||||
.assets
|
||||
.where()
|
||||
.ownerIdEqualToAnyChecksum(userId)
|
||||
.filter()
|
||||
.isArchivedEqualTo(false)
|
||||
.isTrashedEqualTo(false)
|
||||
.stackPrimaryAssetIdIsNull()
|
||||
.sortByFileCreatedAtDesc();
|
||||
|
||||
return renderListGenerator(query, ref);
|
||||
},
|
||||
dependencies: [localeProvider],
|
||||
);
|
||||
|
||||
final multiUserAssetsProvider = StreamProvider.family<RenderList, List<int>>(
|
||||
(ref, userIds) {
|
||||
if (userIds.isEmpty) return const Stream.empty();
|
||||
ref.watch(localeProvider);
|
||||
final query = ref
|
||||
.watch(dbProvider)
|
||||
.assets
|
||||
.where()
|
||||
.anyOf(userIds, (q, u) => q.ownerIdEqualToAnyChecksum(u))
|
||||
.filter()
|
||||
.isArchivedEqualTo(false)
|
||||
.isTrashedEqualTo(false)
|
||||
.stackPrimaryAssetIdIsNull()
|
||||
.sortByFileCreatedAtDesc();
|
||||
|
||||
return renderListGenerator(query, ref);
|
||||
},
|
||||
dependencies: [localeProvider],
|
||||
);
|
||||
|
||||
QueryBuilder<Asset, Asset, QAfterSortBy>? getRemoteAssetQuery(WidgetRef ref) {
|
||||
final userId = ref.watch(currentUserProvider)?.isarId;
|
||||
if (userId == null) {
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/widgets/asset_grid/asset_grid_data_structure.dart';
|
||||
import 'package:immich_mobile/entities/asset.entity.dart';
|
||||
import 'package:immich_mobile/providers/db.provider.dart';
|
||||
import 'package:immich_mobile/providers/user.provider.dart';
|
||||
import 'package:immich_mobile/utils/renderlist_generator.dart';
|
||||
import 'package:isar/isar.dart';
|
||||
|
||||
final favoriteAssetsProvider = StreamProvider<RenderList>((ref) {
|
||||
final user = ref.watch(currentUserProvider);
|
||||
if (user == null) return const Stream.empty();
|
||||
final query = ref
|
||||
.watch(dbProvider)
|
||||
.assets
|
||||
.where()
|
||||
.ownerIdEqualToAnyChecksum(user.isarId)
|
||||
.filter()
|
||||
.isFavoriteEqualTo(true)
|
||||
.isTrashedEqualTo(false)
|
||||
.sortByFileCreatedAtDesc();
|
||||
return renderListGenerator(query, ref);
|
||||
});
|
|
@ -1,17 +0,0 @@
|
|||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/widgets/asset_grid/asset_grid_data_structure.dart';
|
||||
import 'package:immich_mobile/entities/asset.entity.dart';
|
||||
import 'package:immich_mobile/providers/db.provider.dart';
|
||||
import 'package:immich_mobile/utils/renderlist_generator.dart';
|
||||
|
||||
final allVideoAssetsProvider = StreamProvider<RenderList>((ref) {
|
||||
final query = ref
|
||||
.watch(dbProvider)
|
||||
.assets
|
||||
.filter()
|
||||
.isArchivedEqualTo(false)
|
||||
.isTrashedEqualTo(false)
|
||||
.typeEqualTo(AssetType.video)
|
||||
.sortByFileCreatedAtDesc();
|
||||
return renderListGenerator(query, ref);
|
||||
});
|
55
mobile/lib/providers/timeline.provider.dart
Normal file
55
mobile/lib/providers/timeline.provider.dart
Normal file
|
@ -0,0 +1,55 @@
|
|||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/providers/album/album.provider.dart';
|
||||
import 'package:immich_mobile/providers/locale_provider.dart';
|
||||
import 'package:immich_mobile/services/timeline.service.dart';
|
||||
import 'package:immich_mobile/widgets/asset_grid/asset_grid_data_structure.dart';
|
||||
|
||||
final singleUserTimelineProvider = StreamProvider.family<RenderList, int>(
|
||||
(ref, userId) {
|
||||
ref.watch(localeProvider);
|
||||
final timelineService = ref.watch(timelineServiceProvider);
|
||||
return timelineService.watchHomeTimeline(userId);
|
||||
},
|
||||
dependencies: [localeProvider],
|
||||
);
|
||||
|
||||
final multiUsersTimelineProvider = StreamProvider.family<RenderList, List<int>>(
|
||||
(ref, userIds) {
|
||||
ref.watch(localeProvider);
|
||||
final timelineService = ref.watch(timelineServiceProvider);
|
||||
return timelineService.watchMultiUsersTimeline(userIds);
|
||||
},
|
||||
dependencies: [localeProvider],
|
||||
);
|
||||
|
||||
final albumTimelineProvider =
|
||||
StreamProvider.autoDispose.family<RenderList, int>((ref, id) {
|
||||
final album = ref.watch(albumWatcher(id)).value;
|
||||
final timelineService = ref.watch(timelineServiceProvider);
|
||||
|
||||
if (album != null) {
|
||||
return timelineService.watchAlbumTimeline(album);
|
||||
}
|
||||
|
||||
return const Stream.empty();
|
||||
});
|
||||
|
||||
final archiveTimelineProvider = StreamProvider<RenderList>((ref) {
|
||||
final timelineService = ref.watch(timelineServiceProvider);
|
||||
return timelineService.watchArchiveTimeline();
|
||||
});
|
||||
|
||||
final favoriteTimelineProvider = StreamProvider<RenderList>((ref) {
|
||||
final timelineService = ref.watch(timelineServiceProvider);
|
||||
return timelineService.watchFavoriteTimeline();
|
||||
});
|
||||
|
||||
final trashTimelineProvider = StreamProvider<RenderList>((ref) {
|
||||
final timelineService = ref.watch(timelineServiceProvider);
|
||||
return timelineService.watchTrashTimeline();
|
||||
});
|
||||
|
||||
final allVideosTimelineProvider = StreamProvider<RenderList>((ref) {
|
||||
final timelineService = ref.watch(timelineServiceProvider);
|
||||
return timelineService.watchAllVideosTimeline();
|
||||
});
|
|
@ -1,8 +1,6 @@
|
|||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/widgets/asset_grid/asset_grid_data_structure.dart';
|
||||
import 'package:immich_mobile/services/trash.service.dart';
|
||||
import 'package:immich_mobile/entities/asset.entity.dart';
|
||||
import 'package:immich_mobile/providers/user.provider.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
|
||||
class TrashNotifier extends StateNotifier<bool> {
|
||||
|
@ -49,12 +47,3 @@ final trashProvider = StateNotifierProvider<TrashNotifier, bool>((ref) {
|
|||
ref.watch(trashServiceProvider),
|
||||
);
|
||||
});
|
||||
|
||||
final trashedAssetsProvider = StreamProvider<RenderList>((ref) {
|
||||
final user = ref.read(currentUserProvider);
|
||||
if (user == null) {
|
||||
return const Stream.empty();
|
||||
}
|
||||
|
||||
return ref.watch(trashServiceProvider).getRenderListGenerator(user.isarId);
|
||||
});
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/constants/enums.dart';
|
||||
import 'package:immich_mobile/domain/models/store.model.dart';
|
||||
import 'package:immich_mobile/entities/album.entity.dart';
|
||||
import 'package:immich_mobile/entities/asset.entity.dart';
|
||||
|
@ -9,7 +8,6 @@ import 'package:immich_mobile/interfaces/album.interface.dart';
|
|||
import 'package:immich_mobile/models/albums/album_search.model.dart';
|
||||
import 'package:immich_mobile/providers/db.provider.dart';
|
||||
import 'package:immich_mobile/repositories/database.repository.dart';
|
||||
import 'package:immich_mobile/widgets/asset_grid/asset_grid_data_structure.dart';
|
||||
import 'package:isar/isar.dart';
|
||||
|
||||
final albumRepositoryProvider =
|
||||
|
@ -177,22 +175,4 @@ class AlbumRepository extends DatabaseRepository implements IAlbumRepository {
|
|||
Stream<Album?> watchAlbum(int id) {
|
||||
return db.albums.watchObject(id, fireImmediately: true);
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<RenderList> getRenderListStream(Album album) async* {
|
||||
final query = album.assets.filter().isTrashedEqualTo(false);
|
||||
final withSortedOption = switch (album.sortOrder) {
|
||||
SortOrder.asc => query.sortByFileCreatedAt(),
|
||||
SortOrder.desc => query.sortByFileCreatedAtDesc(),
|
||||
};
|
||||
|
||||
yield await RenderList.fromQuery(
|
||||
withSortedOption,
|
||||
GroupAssetsBy.none,
|
||||
);
|
||||
|
||||
await for (final _ in query.watchLazy()) {
|
||||
yield await RenderList.fromQuery(withSortedOption, GroupAssetsBy.none);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ import 'package:immich_mobile/entities/ios_device_asset.entity.dart';
|
|||
import 'package:immich_mobile/interfaces/asset.interface.dart';
|
||||
import 'package:immich_mobile/providers/db.provider.dart';
|
||||
import 'package:immich_mobile/repositories/database.repository.dart';
|
||||
import 'package:immich_mobile/widgets/asset_grid/asset_grid_data_structure.dart';
|
||||
import 'package:isar/isar.dart';
|
||||
|
||||
final assetRepositoryProvider =
|
||||
|
@ -234,20 +233,6 @@ class AssetRepository extends DatabaseRepository implements IAssetRepository {
|
|||
.isTrashedEqualTo(true)
|
||||
.findAll();
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<RenderList> getTrashRenderListStream(int userId) async* {
|
||||
final query = db.assets
|
||||
.filter()
|
||||
.ownerIdEqualTo(userId)
|
||||
.isTrashedEqualTo(true)
|
||||
.sortByFileCreatedAtDesc();
|
||||
|
||||
yield await RenderList.fromQuery(query, GroupAssetsBy.none);
|
||||
await for (final _ in query.watchLazy()) {
|
||||
yield await RenderList.fromQuery(query, GroupAssetsBy.none);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<Asset>> _getMatchesImpl(
|
||||
|
|
120
mobile/lib/repositories/timeline.repository.dart
Normal file
120
mobile/lib/repositories/timeline.repository.dart
Normal file
|
@ -0,0 +1,120 @@
|
|||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/constants/enums.dart';
|
||||
import 'package:immich_mobile/entities/album.entity.dart';
|
||||
import 'package:immich_mobile/entities/asset.entity.dart';
|
||||
import 'package:immich_mobile/interfaces/timeline.interface.dart';
|
||||
import 'package:immich_mobile/providers/db.provider.dart';
|
||||
import 'package:immich_mobile/repositories/database.repository.dart';
|
||||
import 'package:immich_mobile/widgets/asset_grid/asset_grid_data_structure.dart';
|
||||
import 'package:isar/isar.dart';
|
||||
|
||||
final timelineRepositoryProvider =
|
||||
Provider((ref) => TimelineRepository(ref.watch(dbProvider)));
|
||||
|
||||
class TimelineRepository extends DatabaseRepository
|
||||
implements ITimelineRepository {
|
||||
TimelineRepository(super.db);
|
||||
|
||||
@override
|
||||
Stream<RenderList> watchArchiveTimeline(int userId) {
|
||||
final query = db.assets
|
||||
.where()
|
||||
.ownerIdEqualToAnyChecksum(userId)
|
||||
.filter()
|
||||
.isArchivedEqualTo(true)
|
||||
.isTrashedEqualTo(false)
|
||||
.sortByFileCreatedAtDesc();
|
||||
|
||||
return _watchRenderList(query, GroupAssetsBy.none);
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<RenderList> watchFavoriteTimeline(int userId) {
|
||||
final query = db.assets
|
||||
.where()
|
||||
.ownerIdEqualToAnyChecksum(userId)
|
||||
.filter()
|
||||
.isFavoriteEqualTo(true)
|
||||
.isTrashedEqualTo(false)
|
||||
.sortByFileCreatedAtDesc();
|
||||
|
||||
return _watchRenderList(query, GroupAssetsBy.none);
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<RenderList> watchAlbumTimeline(Album album) {
|
||||
final query = album.assets.filter().isTrashedEqualTo(false);
|
||||
final withSortedOption = switch (album.sortOrder) {
|
||||
SortOrder.asc => query.sortByFileCreatedAt(),
|
||||
SortOrder.desc => query.sortByFileCreatedAtDesc(),
|
||||
};
|
||||
|
||||
return _watchRenderList(withSortedOption, GroupAssetsBy.none);
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<RenderList> watchTrashTimeline(int userId) {
|
||||
final query = db.assets
|
||||
.filter()
|
||||
.ownerIdEqualTo(userId)
|
||||
.isTrashedEqualTo(true)
|
||||
.sortByFileCreatedAtDesc();
|
||||
|
||||
return _watchRenderList(query, GroupAssetsBy.none);
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<RenderList> watchAllVideosTimeline() {
|
||||
final query = db.assets
|
||||
.filter()
|
||||
.isArchivedEqualTo(false)
|
||||
.isTrashedEqualTo(false)
|
||||
.typeEqualTo(AssetType.video)
|
||||
.sortByFileCreatedAtDesc();
|
||||
|
||||
return _watchRenderList(query, GroupAssetsBy.none);
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<RenderList> watchHomeTimeline(
|
||||
int userId,
|
||||
GroupAssetsBy groupAssetByOption,
|
||||
) {
|
||||
final query = db.assets
|
||||
.where()
|
||||
.ownerIdEqualToAnyChecksum(userId)
|
||||
.filter()
|
||||
.isArchivedEqualTo(false)
|
||||
.isTrashedEqualTo(false)
|
||||
.stackPrimaryAssetIdIsNull()
|
||||
.sortByFileCreatedAtDesc();
|
||||
|
||||
return _watchRenderList(query, groupAssetByOption);
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<RenderList> watchMultiUsersTimeline(
|
||||
List<int> userIds,
|
||||
GroupAssetsBy groupAssetByOption,
|
||||
) {
|
||||
final query = db.assets
|
||||
.where()
|
||||
.anyOf(userIds, (qb, userId) => qb.ownerIdEqualToAnyChecksum(userId))
|
||||
.filter()
|
||||
.isArchivedEqualTo(false)
|
||||
.isTrashedEqualTo(false)
|
||||
.stackPrimaryAssetIdIsNull()
|
||||
.sortByFileCreatedAtDesc();
|
||||
return _watchRenderList(query, groupAssetByOption);
|
||||
}
|
||||
|
||||
Stream<RenderList> _watchRenderList(
|
||||
QueryBuilder<Asset, Asset, QAfterSortBy> query,
|
||||
GroupAssetsBy groupAssetsBy,
|
||||
) async* {
|
||||
yield await RenderList.fromQuery(query, groupAssetsBy);
|
||||
await for (final _ in query.watchLazy()) {
|
||||
yield await RenderList.fromQuery(query, groupAssetsBy);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -27,7 +27,6 @@ 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:immich_mobile/widgets/asset_grid/asset_grid_data_structure.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
|
||||
final albumServiceProvider = Provider(
|
||||
|
@ -469,10 +468,6 @@ class AlbumService {
|
|||
return _albumRepository.watchAlbum(id);
|
||||
}
|
||||
|
||||
Stream<RenderList> getRenderListGenerator(Album album) {
|
||||
return _albumRepository.getRenderListStream(album);
|
||||
}
|
||||
|
||||
Future<List<Album>> search(
|
||||
String searchTerm,
|
||||
QuickFilterMode filterMode,
|
||||
|
|
70
mobile/lib/services/timeline.service.dart
Normal file
70
mobile/lib/services/timeline.service.dart
Normal file
|
@ -0,0 +1,70 @@
|
|||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/entities/album.entity.dart';
|
||||
import 'package:immich_mobile/interfaces/timeline.interface.dart';
|
||||
import 'package:immich_mobile/interfaces/user.interface.dart';
|
||||
import 'package:immich_mobile/providers/app_settings.provider.dart';
|
||||
import 'package:immich_mobile/repositories/timeline.repository.dart';
|
||||
import 'package:immich_mobile/repositories/user.repository.dart';
|
||||
import 'package:immich_mobile/services/app_settings.service.dart';
|
||||
import 'package:immich_mobile/widgets/asset_grid/asset_grid_data_structure.dart';
|
||||
|
||||
final timelineServiceProvider = Provider<TimelineService>((ref) {
|
||||
return TimelineService(
|
||||
ref.watch(timelineRepositoryProvider),
|
||||
ref.watch(userRepositoryProvider),
|
||||
ref.watch(appSettingsServiceProvider),
|
||||
);
|
||||
});
|
||||
|
||||
class TimelineService {
|
||||
final ITimelineRepository _timelineRepository;
|
||||
final IUserRepository _userRepository;
|
||||
final AppSettingsService _appSettingsService;
|
||||
TimelineService(
|
||||
this._timelineRepository,
|
||||
this._userRepository,
|
||||
this._appSettingsService,
|
||||
);
|
||||
|
||||
Stream<RenderList> watchHomeTimeline(int userId) {
|
||||
return _timelineRepository.watchHomeTimeline(userId, _getGroupByOption());
|
||||
}
|
||||
|
||||
Stream<RenderList> watchMultiUsersTimeline(List<int> userIds) {
|
||||
return _timelineRepository.watchMultiUsersTimeline(
|
||||
userIds,
|
||||
_getGroupByOption(),
|
||||
);
|
||||
}
|
||||
|
||||
Stream<RenderList> watchArchiveTimeline() async* {
|
||||
final user = await _userRepository.me();
|
||||
|
||||
yield* _timelineRepository.watchArchiveTimeline(user.isarId);
|
||||
}
|
||||
|
||||
Stream<RenderList> watchFavoriteTimeline() async* {
|
||||
final user = await _userRepository.me();
|
||||
|
||||
yield* _timelineRepository.watchFavoriteTimeline(user.isarId);
|
||||
}
|
||||
|
||||
Stream<RenderList> watchAlbumTimeline(Album album) async* {
|
||||
yield* _timelineRepository.watchAlbumTimeline(album);
|
||||
}
|
||||
|
||||
Stream<RenderList> watchTrashTimeline() async* {
|
||||
final user = await _userRepository.me();
|
||||
|
||||
yield* _timelineRepository.watchTrashTimeline(user.isarId);
|
||||
}
|
||||
|
||||
Stream<RenderList> watchAllVideosTimeline() {
|
||||
return _timelineRepository.watchAllVideosTimeline();
|
||||
}
|
||||
|
||||
GroupAssetsBy _getGroupByOption() {
|
||||
return GroupAssetsBy
|
||||
.values[_appSettingsService.getSetting(AppSettingsEnum.groupAssetsBy)];
|
||||
}
|
||||
}
|
|
@ -2,11 +2,12 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|||
import 'package:immich_mobile/entities/asset.entity.dart';
|
||||
import 'package:immich_mobile/interfaces/asset.interface.dart';
|
||||
import 'package:immich_mobile/interfaces/user.interface.dart';
|
||||
|
||||
import 'package:immich_mobile/providers/api.provider.dart';
|
||||
import 'package:immich_mobile/repositories/asset.repository.dart';
|
||||
import 'package:immich_mobile/repositories/user.repository.dart';
|
||||
|
||||
import 'package:immich_mobile/services/api.service.dart';
|
||||
import 'package:immich_mobile/widgets/asset_grid/asset_grid_data_structure.dart';
|
||||
import 'package:openapi/api.dart';
|
||||
|
||||
final trashServiceProvider = Provider<TrashService>((ref) {
|
||||
|
@ -82,8 +83,4 @@ class TrashService {
|
|||
|
||||
await _assetRepository.updateAll(updatedAssets);
|
||||
}
|
||||
|
||||
Stream<RenderList> getRenderListGenerator(int userId) {
|
||||
return _assetRepository.getTrashRenderListStream(userId);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue