From 44b099303587475667ab2c0136453ae1cd2e479c Mon Sep 17 00:00:00 2001 From: ExceptionsOccur Date: Tue, 14 Jan 2025 10:03:59 +0800 Subject: [PATCH 1/2] according to photo grid setting, let photos group by date in album page view on android --- .../lib/providers/album/album.provider.dart | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/mobile/lib/providers/album/album.provider.dart b/mobile/lib/providers/album/album.provider.dart index b3d619a81579a5..976158a5798d97 100644 --- a/mobile/lib/providers/album/album.provider.dart +++ b/mobile/lib/providers/album/album.provider.dart @@ -11,6 +11,8 @@ import 'package:immich_mobile/entities/album.entity.dart'; import 'package:immich_mobile/providers/db.provider.dart'; import 'package:immich_mobile/utils/renderlist_generator.dart'; import 'package:isar/isar.dart'; +import '../../services/app_settings.service.dart'; +import '../app_settings.provider.dart'; final isRefreshingRemoteAlbumProvider = StateProvider((ref) => false); @@ -140,6 +142,17 @@ final albumWatcher = } }); +Stream renderListGeneratorWithGroupByDate( + QueryBuilder query, + StreamProviderRef ref, + GroupAssetsBy groupBy, + ) { + final settings = ref.watch(appSettingsServiceProvider); + final groupBy = + GroupAssetsBy.values[settings.getSetting(AppSettingsEnum.groupAssetsBy)]; + return renderListGeneratorWithGroupBy(query, groupBy); +} + final albumRenderlistProvider = StreamProvider.autoDispose.family((ref, albumId) { final album = ref.watch(albumWatcher(albumId)).value; @@ -147,13 +160,15 @@ final albumRenderlistProvider = if (album != null) { final query = album.assets.filter().isTrashedEqualTo(false); if (album.sortOrder == SortOrder.asc) { - return renderListGeneratorWithGroupBy( + return renderListGeneratorWithGroupByDate( query.sortByFileCreatedAt(), + ref, GroupAssetsBy.none, ); } else if (album.sortOrder == SortOrder.desc) { - return renderListGeneratorWithGroupBy( + return renderListGeneratorWithGroupByDate( query.sortByFileCreatedAtDesc(), + ref, GroupAssetsBy.none, ); } From 9876c0c5a639398ab3cfe7620003907a69ded13b Mon Sep 17 00:00:00 2001 From: ExceptionsOccur Date: Thu, 16 Jan 2025 20:27:07 +0800 Subject: [PATCH 2/2] memory includes assets in shared albums --- server/src/interfaces/asset.interface.ts | 2 +- server/src/repositories/asset.repository.ts | 21 +++++++++++++++++++-- server/src/services/asset.service.ts | 3 ++- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/server/src/interfaces/asset.interface.ts b/server/src/interfaces/asset.interface.ts index 5abaf9af26607a..bfe22c4c4cd169 100644 --- a/server/src/interfaces/asset.interface.ts +++ b/server/src/interfaces/asset.interface.ts @@ -135,7 +135,7 @@ export interface IAssetRepository { create(asset: Insertable): Promise; getByIds(ids: string[], relations?: GetByIdsRelations): Promise; getByIdsWithAllRelations(ids: string[]): Promise; - getByDayOfYear(ownerIds: string[], monthDay: MonthDay): Promise; + getByDayOfYear(ownerIds: string[], albumIds: string[], monthDay: MonthDay): Promise; getByChecksum(options: AssetGetByChecksumOptions): Promise; getByChecksums(userId: string, checksums: Buffer[]): Promise; getUploadAssetIdByChecksum(ownerId: string, checksum: Buffer): Promise; diff --git a/server/src/repositories/asset.repository.ts b/server/src/repositories/asset.repository.ts index ef581d47669cb2..70bad74c798e9e 100644 --- a/server/src/repositories/asset.repository.ts +++ b/server/src/repositories/asset.repository.ts @@ -85,7 +85,7 @@ export class AssetRepository implements IAssetRepository { } @GenerateSql({ params: [DummyValue.UUID, { day: 1, month: 1 }] }) - getByDayOfYear(ownerIds: string[], { day, month }: MonthDay): Promise { + getByDayOfYear(ownerIds: string[], albumIds: string[], { day, month }: MonthDay): Promise { return this.db .with('res', (qb) => qb @@ -110,7 +110,20 @@ export class AssetRepository implements IAssetRepository { .innerJoin('asset_job_status', 'assets.id', 'asset_job_status.assetId') .where('asset_job_status.previewAt', 'is not', null) .where(sql`(assets."localDateTime" at time zone 'UTC')::date`, '=', sql`today.date`) - .where('assets.ownerId', '=', anyUuid(ownerIds)) + .where(({eb, and, or}) => or([ + // assets in share albums and not ownerIds own + and([ + eb.exists((qb)=> + qb + .selectFrom('albums_assets_assets') + .whereRef('albums_assets_assets.assetsId', '=', 'assets.id') + .where('albums_assets_assets.albumsId', '=', anyUuid(albumIds)) + ), + eb('assets.ownerId', '!=', anyUuid(ownerIds)) + ]), + // ownerIds own + eb('assets.ownerId', '=', anyUuid(ownerIds)) + ])) .where('assets.isVisible', '=', true) .where('assets.isArchived', '=', false) .where((eb) => @@ -122,6 +135,10 @@ export class AssetRepository implements IAssetRepository { ), ) .where('assets.deletedAt', 'is', null) + // TODO optimize the query to avoid performance issues caused by a large amount of data + // If the same photo is uploaded twice by user A and user B respectively, + // when the photo appears in the sharing, the result will show duplicates + .distinctOn('assets.checksum') .limit(10) .as('a'), (join) => join.onTrue(), diff --git a/server/src/services/asset.service.ts b/server/src/services/asset.service.ts index de4c0fe0f1a000..1425bb1abc6b8b 100644 --- a/server/src/services/asset.service.ts +++ b/server/src/services/asset.service.ts @@ -42,8 +42,9 @@ export class AssetService extends BaseService { timelineEnabled: true, }); const userIds = [auth.user.id, ...partnerIds]; + const shareAlbums = await this.albumRepository.getShared(auth.user.id); - const groups = await this.assetRepository.getByDayOfYear(userIds, dto); + const groups = await this.assetRepository.getByDayOfYear(userIds, shareAlbums.length > 0 ? shareAlbums.map(el=>el.id) : [], dto); return groups.map(({ yearsAgo, assets }) => ({ yearsAgo, // TODO move this to clients