1
0
Fork 0
mirror of https://github.com/immich-app/immich.git synced 2025-04-21 15:36:26 +02:00

fix(server): stack info in asset response for mobile ()

* fix(server): stack info in asset response for mobile

* fix(server): getAllAssets - do not filter by stack ID

* tet(server): GET /assets stack e2e

* chore(server): fix checks

* stack asset height

---------

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
This commit is contained in:
Alex 2024-03-05 23:44:56 -06:00 committed by GitHub
parent 4c0bb2308c
commit 52dfe5fc92
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 37 additions and 24 deletions
mobile
ios
lib/modules/asset_viewer/views
server
e2e/api/specs
src

View file

@ -180,4 +180,4 @@ SPEC CHECKSUMS:
PODFILE CHECKSUM: 64c9b5291666c0ca3caabdfe9865c141ac40321d
COCOAPODS: 1.12.1
COCOAPODS: 1.11.3

View file

@ -218,18 +218,19 @@ class GalleryViewerPage extends HookConsumerWidget {
scrollDirection: Axis.horizontal,
itemCount: stackElements.length,
padding: const EdgeInsets.only(
left: 10,
right: 10,
left: 5,
right: 5,
bottom: 30,
),
itemBuilder: (context, index) {
final assetId = stackElements.elementAt(index).remoteId;
return Padding(
padding: const EdgeInsets.only(right: 10),
padding: const EdgeInsets.only(right: 5),
child: GestureDetector(
onTap: () => stackIndex.value = index,
child: Container(
width: 40,
width: 60,
height: 60,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(6),
@ -391,7 +392,7 @@ class GalleryViewerPage extends HookConsumerWidget {
Visibility(
visible: stack.isNotEmpty,
child: SizedBox(
height: 40,
height: 80,
child: buildStackedChildren(),
),
),

View file

@ -14,6 +14,7 @@ import { AssetEntity, AssetStackEntity, AssetType, SharedLinkType } from '@app/i
import { AssetRepository } from '@app/infra/repositories';
import { INestApplication } from '@nestjs/common';
import { errorStub, userDto, uuidStub } from '@test/fixtures';
import { assetApi } from 'e2e/client/asset-api';
import { randomBytes } from 'node:crypto';
import request from 'supertest';
import { api } from '../../client';
@ -532,6 +533,23 @@ describe(`${AssetController.name} (e2e)`, () => {
}
});
}
it('should return stack data', async () => {
const parentId = asset1.id;
const childIds = [asset2.id, asset3.id];
await request(server)
.put('/asset')
.set('Authorization', `Bearer ${user1.accessToken}`)
.send({ stackParentId: parentId, ids: childIds });
const body = await assetApi.getAllAssets(server, user1.accessToken);
// Response includes parent with stack children count
const parentDto = body.find((a) => a.id == parentId);
expect(parentDto?.stackCount).toEqual(3);
// Response includes children at the root level
expect.arrayContaining([expect.objectContaining({ id: asset1.id }), expect.objectContaining({ id: asset2.id })]);
});
});
describe('POST /asset/upload', () => {

View file

@ -92,12 +92,12 @@ export interface SearchStatusOptions {
export interface SearchOneToOneRelationOptions {
withExif?: boolean;
withSmartInfo?: boolean;
withStacked?: boolean;
}
export interface SearchRelationOptions extends SearchOneToOneRelationOptions {
withFaces?: boolean;
withPeople?: boolean;
withStacked?: boolean;
}
export interface SearchDateOptions {

View file

@ -116,9 +116,17 @@ export class AssetService {
await this.access.requirePermission(auth, Permission.TIMELINE_READ, userId);
const assets = await this.assetRepository.getAllByFileCreationDate(
{ take: dto.take ?? 1000, skip: dto.skip },
{ ...dto, userIds: [userId], withDeleted: true, orderDirection: 'DESC', withExif: true, isVisible: true },
{
...dto,
userIds: [userId],
withDeleted: true,
orderDirection: 'DESC',
withExif: true,
isVisible: true,
withStacked: true,
},
);
return assets.items.map((asset) => mapAsset(asset));
return assets.items.map((asset) => mapAsset(asset, { withStack: true }));
}
async serveThumbnail(auth: AuthDto, assetId: string, dto: GetAssetThumbnailDto): Promise<ImmichFileResponse> {

View file

@ -2,7 +2,6 @@ import { AssetSearchBuilderOptions, Paginated, PaginationOptions } from '@app/do
import _ from 'lodash';
import {
Between,
Brackets,
FindManyOptions,
IsNull,
LessThanOrEqual,
@ -229,12 +228,7 @@ export function searchAssetBuilder(
}
if (withStacked) {
builder
.leftJoinAndSelect(`${builder.alias}.stack`, 'stack')
.leftJoinAndSelect('stack.assets', 'stackedAssets')
.andWhere(
new Brackets((qb) => qb.where(`stack.primaryAssetId = ${builder.alias}.id`).orWhere('asset.stackId IS NULL')),
);
builder.leftJoinAndSelect(`${builder.alias}.stack`, 'stack').leftJoinAndSelect('stack.assets', 'stackedAssets');
}
const withDeleted = options.withDeleted ?? (trashedAfter !== undefined || trashedBefore !== undefined);

View file

@ -83,10 +83,6 @@ FROM
"asset"."isFavorite" = $3
AND "asset"."isArchived" = $4
)
AND (
"stack"."primaryAssetId" = "asset"."id"
OR "asset"."stackId" IS NULL
)
)
AND ("asset"."deletedAt" IS NULL)
) "distinctAlias"
@ -184,10 +180,6 @@ WHERE
"asset"."isFavorite" = $3
AND "asset"."isArchived" = $4
)
AND (
"stack"."primaryAssetId" = "asset"."id"
OR "asset"."stackId" IS NULL
)
AND "asset"."ownerId" IN ($5)
)
AND ("asset"."deletedAt" IS NULL)