mirror of
https://github.com/immich-app/immich
synced 2025-11-14 17:36:12 +00:00
handle live photos
This commit is contained in:
parent
a3d10ff46a
commit
883eb15ecb
8 changed files with 34 additions and 11 deletions
4
mobile/openapi/lib/api/upload_api.dart
generated
4
mobile/openapi/lib/api/upload_api.dart
generated
|
|
@ -293,7 +293,7 @@ class UploadApi {
|
|||
/// Indicates the version of the RUFH protocol supported by the client.
|
||||
///
|
||||
/// * [String] xImmichAssetData (required):
|
||||
/// RFC 9651 structured dictionary containing asset metadata with the following keys: - device-asset-id (string, required): Unique device asset identifier - device-id (string, required): Device identifier - file-created-at (string/date, required): ISO 8601 date string or Unix timestamp - file-modified-at (string/date, required): ISO 8601 date string or Unix timestamp - filename (string, required): Original filename - is-favorite (boolean, optional): Favorite status - icloud-id (string, optional): iCloud identifier for assets from iOS devices
|
||||
/// RFC 9651 structured dictionary containing asset metadata with the following keys: - device-asset-id (string, required): Unique device asset identifier - device-id (string, required): Device identifier - file-created-at (string/date, required): ISO 8601 date string or Unix timestamp - file-modified-at (string/date, required): ISO 8601 date string or Unix timestamp - filename (string, required): Original filename - is-favorite (boolean, optional): Favorite status - live-photo-video-id (string, optional): Live photo ID for assets from iOS devices - icloud-id (string, optional): iCloud identifier for assets from iOS devices
|
||||
///
|
||||
/// * [String] key:
|
||||
///
|
||||
|
|
@ -353,7 +353,7 @@ class UploadApi {
|
|||
/// Indicates the version of the RUFH protocol supported by the client.
|
||||
///
|
||||
/// * [String] xImmichAssetData (required):
|
||||
/// RFC 9651 structured dictionary containing asset metadata with the following keys: - device-asset-id (string, required): Unique device asset identifier - device-id (string, required): Device identifier - file-created-at (string/date, required): ISO 8601 date string or Unix timestamp - file-modified-at (string/date, required): ISO 8601 date string or Unix timestamp - filename (string, required): Original filename - is-favorite (boolean, optional): Favorite status - icloud-id (string, optional): iCloud identifier for assets from iOS devices
|
||||
/// RFC 9651 structured dictionary containing asset metadata with the following keys: - device-asset-id (string, required): Unique device asset identifier - device-id (string, required): Device identifier - file-created-at (string/date, required): ISO 8601 date string or Unix timestamp - file-modified-at (string/date, required): ISO 8601 date string or Unix timestamp - filename (string, required): Original filename - is-favorite (boolean, optional): Favorite status - live-photo-video-id (string, optional): Live photo ID for assets from iOS devices - icloud-id (string, optional): iCloud identifier for assets from iOS devices
|
||||
///
|
||||
/// * [String] key:
|
||||
///
|
||||
|
|
|
|||
|
|
@ -9296,7 +9296,7 @@
|
|||
{
|
||||
"name": "x-immich-asset-data",
|
||||
"in": "header",
|
||||
"description": "RFC 9651 structured dictionary containing asset metadata with the following keys:\n- device-asset-id (string, required): Unique device asset identifier\n- device-id (string, required): Device identifier\n- file-created-at (string/date, required): ISO 8601 date string or Unix timestamp\n- file-modified-at (string/date, required): ISO 8601 date string or Unix timestamp\n- filename (string, required): Original filename\n- is-favorite (boolean, optional): Favorite status\n- icloud-id (string, optional): iCloud identifier for assets from iOS devices",
|
||||
"description": "RFC 9651 structured dictionary containing asset metadata with the following keys:\n- device-asset-id (string, required): Unique device asset identifier\n- device-id (string, required): Device identifier\n- file-created-at (string/date, required): ISO 8601 date string or Unix timestamp\n- file-modified-at (string/date, required): ISO 8601 date string or Unix timestamp\n- filename (string, required): Original filename\n- is-favorite (boolean, optional): Favorite status\n- live-photo-video-id (string, optional): Live photo ID for assets from iOS devices\n- icloud-id (string, optional): iCloud identifier for assets from iOS devices",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
|
|
|
|||
|
|
@ -14,7 +14,13 @@ import {
|
|||
} from '@nestjs/common';
|
||||
import { ApiHeader, ApiOkResponse, ApiTags } from '@nestjs/swagger';
|
||||
import { Request, Response } from 'express';
|
||||
import { GetUploadStatusDto, ResumeUploadDto, StartUploadDto, UploadHeader, UploadOkDto } from 'src/dtos/asset-upload';
|
||||
import {
|
||||
GetUploadStatusDto,
|
||||
ResumeUploadDto,
|
||||
StartUploadDto,
|
||||
UploadHeader,
|
||||
UploadOkDto,
|
||||
} from 'src/dtos/asset-upload.dto';
|
||||
import { AuthDto } from 'src/dtos/auth.dto';
|
||||
import { ImmichHeader, Permission } from 'src/enum';
|
||||
import { Auth, Authenticated } from 'src/middleware/auth.guard';
|
||||
|
|
@ -60,6 +66,7 @@ export class AssetUploadController {
|
|||
- file-modified-at (string/date, required): ISO 8601 date string or Unix timestamp
|
||||
- filename (string, required): Original filename
|
||||
- is-favorite (boolean, optional): Favorite status
|
||||
- live-photo-video-id (string, optional): Live photo ID for assets from iOS devices
|
||||
- icloud-id (string, optional): iCloud identifier for assets from iOS devices`,
|
||||
required: true,
|
||||
example:
|
||||
|
|
|
|||
|
|
@ -28,6 +28,11 @@ export class UploadAssetDataDto {
|
|||
@ValidateBoolean({ optional: true })
|
||||
isFavorite?: boolean;
|
||||
|
||||
@Optional()
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
livePhotoVideoId?: string;
|
||||
|
||||
@Optional()
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
|
|
@ -101,6 +106,7 @@ export class StartUploadDto extends BaseUploadHeadersDto {
|
|||
fileCreatedAt: dict.get('file-created-at')?.[0],
|
||||
fileModifiedAt: dict.get('file-modified-at')?.[0],
|
||||
isFavorite: dict.get('is-favorite')?.[0],
|
||||
livePhotoVideoId: dict.get('live-photo-video-id')?.[0],
|
||||
iCloudId: dict.get('icloud-id')?.[0],
|
||||
});
|
||||
} catch {
|
||||
|
|
@ -126,7 +132,7 @@ export class StartUploadDto extends BaseUploadHeadersDto {
|
|||
@Expose({ name: UploadHeader.UploadLength })
|
||||
@Min(0)
|
||||
@IsInt()
|
||||
@Type(() => Number)
|
||||
@Transform(({ obj, value }) => Number(value === undefined ? obj['x-upload-length'] : value))
|
||||
uploadLength!: number;
|
||||
|
||||
@Expose({ name: UploadHeader.UploadOffset })
|
||||
|
|
@ -64,10 +64,16 @@ where
|
|||
-- AssetRepository.setComplete
|
||||
update "asset"
|
||||
set
|
||||
"status" = $1,
|
||||
"visibility" = $2
|
||||
"status" = 'active',
|
||||
"visibility" = (
|
||||
case
|
||||
when type = 'VIDEO'
|
||||
and "livePhotoVideoId" is not null then 'hidden'
|
||||
else 'timeline'
|
||||
end
|
||||
)::asset_visibility_enum
|
||||
where
|
||||
"id" = $3
|
||||
"id" = $1
|
||||
and "status" = 'partial'
|
||||
|
||||
-- AssetRepository.removeAndDecrementQuota
|
||||
|
|
|
|||
|
|
@ -292,7 +292,10 @@ export class AssetRepository {
|
|||
async setComplete(assetId: string) {
|
||||
await this.db
|
||||
.updateTable('asset')
|
||||
.set({ status: AssetStatus.Active, visibility: AssetVisibility.Timeline })
|
||||
.set({
|
||||
status: sql.lit(AssetStatus.Active),
|
||||
visibility: sql`(case when type = 'VIDEO' and "livePhotoVideoId" is not null then 'hidden' else 'timeline' end)::asset_visibility_enum`,
|
||||
})
|
||||
.where('id', '=', assetId)
|
||||
.where('status', '=', sql.lit(AssetStatus.Partial))
|
||||
.execute();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { BadRequestException, InternalServerErrorException } from '@nestjs/common';
|
||||
import { StructuredBoolean } from 'src/dtos/asset-upload';
|
||||
import { StructuredBoolean } from 'src/dtos/asset-upload.dto';
|
||||
import { AssetMetadataKey, AssetStatus, AssetType, AssetVisibility, JobName, JobStatus } from 'src/enum';
|
||||
import { AssetUploadService } from 'src/services/asset-upload.service';
|
||||
import { ASSET_CHECKSUM_CONSTRAINT } from 'src/utils/database';
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import { Readable } from 'node:stream';
|
|||
import { JOBS_ASSET_PAGINATION_SIZE } from 'src/constants';
|
||||
import { StorageCore } from 'src/cores/storage.core';
|
||||
import { OnEvent, OnJob } from 'src/decorators';
|
||||
import { GetUploadStatusDto, ResumeUploadDto, StartUploadDto } from 'src/dtos/asset-upload';
|
||||
import { GetUploadStatusDto, ResumeUploadDto, StartUploadDto } from 'src/dtos/asset-upload.dto';
|
||||
import { AuthDto } from 'src/dtos/auth.dto';
|
||||
import {
|
||||
AssetMetadataKey,
|
||||
|
|
@ -269,6 +269,7 @@ export class AssetUploadService extends BaseService {
|
|||
localDateTime: assetData.fileCreatedAt,
|
||||
type,
|
||||
isFavorite: assetData.isFavorite,
|
||||
livePhotoVideoId: assetData.livePhotoVideoId,
|
||||
visibility: AssetVisibility.Hidden,
|
||||
originalFileName: assetData.filename,
|
||||
status: AssetStatus.Partial,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue