mirror of
https://github.com/immich-app/immich.git
synced 2026-05-18 03:10:24 +03:00
feat(server): lighter buckets
This commit is contained in:
@@ -1,30 +1,105 @@
|
||||
import { BadRequestException, Injectable } from '@nestjs/common';
|
||||
import { AssetResponseDto, SanitizedAssetResponseDto, mapAsset } from 'src/dtos/asset-response.dto';
|
||||
import { round } from 'lodash';
|
||||
import { Stack } from 'src/database';
|
||||
import { AuthDto } from 'src/dtos/auth.dto';
|
||||
import { TimeBucketAssetDto, TimeBucketDto, TimeBucketResponseDto } from 'src/dtos/time-bucket.dto';
|
||||
import { Permission } from 'src/enum';
|
||||
import {
|
||||
TimeBucketAssetDto,
|
||||
TimeBucketDto,
|
||||
TimeBucketResponseDto,
|
||||
TimeBucketsResponseDto,
|
||||
} from 'src/dtos/time-bucket.dto';
|
||||
import { AssetType, Permission } from 'src/enum';
|
||||
import { TimeBucketOptions } from 'src/repositories/asset.repository';
|
||||
import { BaseService } from 'src/services/base.service';
|
||||
import { getMyPartnerIds } from 'src/utils/asset.util';
|
||||
import { TimeBucketAssets } from 'src/services/timeline.service.types';
|
||||
import { getMyPartnerIds, isFlipped } from 'src/utils/asset.util';
|
||||
import { hexOrBufferToBase64 } from 'src/utils/bytes';
|
||||
|
||||
@Injectable()
|
||||
export class TimelineService extends BaseService {
|
||||
async getTimeBuckets(auth: AuthDto, dto: TimeBucketDto): Promise<TimeBucketResponseDto[]> {
|
||||
async getTimeBuckets(auth: AuthDto, dto: TimeBucketDto): Promise<TimeBucketsResponseDto[]> {
|
||||
await this.timeBucketChecks(auth, dto);
|
||||
const timeBucketOptions = await this.buildTimeBucketOptions(auth, dto);
|
||||
return this.assetRepository.getTimeBuckets(timeBucketOptions);
|
||||
}
|
||||
|
||||
async getTimeBucket(
|
||||
auth: AuthDto,
|
||||
dto: TimeBucketAssetDto,
|
||||
): Promise<AssetResponseDto[] | SanitizedAssetResponseDto[]> {
|
||||
async getTimeBucket(auth: AuthDto, dto: TimeBucketAssetDto): Promise<TimeBucketResponseDto> {
|
||||
await this.timeBucketChecks(auth, dto);
|
||||
const timeBucketOptions = await this.buildTimeBucketOptions(auth, dto);
|
||||
const assets = await this.assetRepository.getTimeBucket(dto.timeBucket, timeBucketOptions);
|
||||
return !auth.sharedLink || auth.sharedLink?.showExif
|
||||
? assets.map((asset) => mapAsset(asset, { withStack: true, auth }))
|
||||
: assets.map((asset) => mapAsset(asset, { stripMetadata: true, auth }));
|
||||
const timeBucketOptions = await this.buildTimeBucketOptions(auth, { ...dto });
|
||||
|
||||
const page = dto.page || 1;
|
||||
const size = dto.pageSize || -1;
|
||||
if (dto.pageSize === 0) {
|
||||
throw new BadRequestException('pageSize must not be 0');
|
||||
}
|
||||
const paginate = page >= 1 && size >= 1;
|
||||
const items = await this.assetRepository.getTimeBucket(dto.timeBucket, timeBucketOptions, {
|
||||
skip: page,
|
||||
take: size,
|
||||
});
|
||||
|
||||
const hasNextPage = paginate && items.length > size;
|
||||
if (paginate) {
|
||||
items.splice(size);
|
||||
}
|
||||
|
||||
const bucketAssets: TimeBucketAssets = {
|
||||
id: [],
|
||||
ownerId: [],
|
||||
ratio: [],
|
||||
isFavorite: [],
|
||||
isArchived: [],
|
||||
isTrashed: [],
|
||||
isVideo: [],
|
||||
isImage: [],
|
||||
thumbhash: [],
|
||||
localDateTime: [],
|
||||
stack: [],
|
||||
duration: [],
|
||||
projectionType: [],
|
||||
livePhotoVideoId: [],
|
||||
};
|
||||
for (const item of items) {
|
||||
let width = item.width!;
|
||||
let height = item.height!;
|
||||
if (isFlipped(item.orientation)) {
|
||||
const w = item.width!;
|
||||
const h = item.height!;
|
||||
height = w;
|
||||
width = h;
|
||||
}
|
||||
bucketAssets.id.push(item.id);
|
||||
bucketAssets.ownerId.push(item.ownerId);
|
||||
bucketAssets.ratio.push(round(width / height, 2));
|
||||
bucketAssets.isArchived.push(item.isArchived ? 1 : 0);
|
||||
bucketAssets.isFavorite.push(item.isFavorite ? 1 : 0);
|
||||
bucketAssets.isTrashed.push(item.deletedAt === null ? 0 : 1);
|
||||
bucketAssets.thumbhash.push(item.thumbhash ? hexOrBufferToBase64(item.thumbhash) : 0);
|
||||
bucketAssets.localDateTime.push(item.localDateTime);
|
||||
bucketAssets.stack.push(this.mapStack(item.stack) || 0);
|
||||
bucketAssets.duration.push(item.duration || 0);
|
||||
bucketAssets.projectionType.push(item.projectionType || 0);
|
||||
bucketAssets.livePhotoVideoId.push(item.livePhotoVideoId || 0);
|
||||
bucketAssets.isImage.push(item.type === AssetType.IMAGE ? 1 : 0);
|
||||
bucketAssets.isVideo.push(item.type === AssetType.VIDEO ? 1 : 0);
|
||||
}
|
||||
|
||||
return {
|
||||
bucketAssets,
|
||||
hasNextPage,
|
||||
};
|
||||
}
|
||||
|
||||
mapStack(entity?: Stack | null) {
|
||||
if (!entity) {
|
||||
return;
|
||||
}
|
||||
|
||||
return {
|
||||
id: entity.id!,
|
||||
primaryAssetId: entity.primaryAssetId!,
|
||||
assetCount: entity.assetCount as number,
|
||||
};
|
||||
}
|
||||
|
||||
private async buildTimeBucketOptions(auth: AuthDto, dto: TimeBucketDto): Promise<TimeBucketOptions> {
|
||||
|
||||
Reference in New Issue
Block a user