mirror of
https://github.com/immich-app/immich.git
synced 2025-12-29 17:25:00 +03:00
merge: remote-tracking branch 'origin/main' into feat/database-restores
This commit is contained in:
@@ -55,7 +55,9 @@ COPY --from=ghcr.io/jdx/mise:2025.11.3@sha256:ac26f5978c0e2783f3e68e58ce75eddb83
|
||||
WORKDIR /usr/src/app
|
||||
COPY ./plugins/mise.toml ./plugins/
|
||||
ENV MISE_TRUSTED_CONFIG_PATHS=/usr/src/app/plugins/mise.toml
|
||||
RUN mise install --cd plugins
|
||||
ENV MISE_DATA_DIR=/buildcache/mise
|
||||
RUN --mount=type=cache,id=mise-tools,target=/buildcache/mise \
|
||||
mise install --cd plugins
|
||||
|
||||
COPY ./plugins ./plugins/
|
||||
# Build plugins
|
||||
@@ -64,6 +66,7 @@ RUN --mount=type=cache,id=pnpm-plugins,target=/buildcache/pnpm-store \
|
||||
--mount=type=bind,source=.pnpmfile.cjs,target=.pnpmfile.cjs \
|
||||
--mount=type=bind,source=pnpm-lock.yaml,target=pnpm-lock.yaml \
|
||||
--mount=type=bind,source=pnpm-workspace.yaml,target=pnpm-workspace.yaml \
|
||||
--mount=type=cache,id=mise-tools,target=/buildcache/mise \
|
||||
cd plugins && mise run build
|
||||
|
||||
FROM ghcr.io/immich-app/base-server-prod:202511041104@sha256:57c0379977fd5521d83cdf661aecd1497c83a9a661ebafe0a5243a09fc1064cb
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "immich",
|
||||
"version": "2.2.3",
|
||||
"version": "2.3.1",
|
||||
"description": "",
|
||||
"author": "",
|
||||
"private": true,
|
||||
|
||||
@@ -121,6 +121,23 @@ export class MediaRepository {
|
||||
}
|
||||
}
|
||||
|
||||
async copyTagGroup(tagGroup: string, source: string, target: string): Promise<boolean> {
|
||||
try {
|
||||
await exiftool.write(
|
||||
target,
|
||||
{},
|
||||
{
|
||||
ignoreMinorErrors: true,
|
||||
writeArgs: ['-TagsFromFile', source, `-${tagGroup}:all>${tagGroup}:all`, '-overwrite_original'],
|
||||
},
|
||||
);
|
||||
return true;
|
||||
} catch (error: any) {
|
||||
this.logger.warn(`Could not copy tag data to image: ${error.message}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
decodeImage(input: string | Buffer, options: DecodeToBufferOptions) {
|
||||
return this.getImageDecodingPipeline(input, options).raw().toBuffer({ resolveWithObject: true });
|
||||
}
|
||||
|
||||
@@ -865,6 +865,7 @@ describe(MediaService.name, () => {
|
||||
mocks.systemMetadata.get.mockResolvedValue({ image: { fullsize: { enabled: false } } });
|
||||
mocks.media.extract.mockResolvedValue({ buffer: extractedBuffer, format: RawExtractedFormat.Jpeg });
|
||||
mocks.media.getImageDimensions.mockResolvedValue({ width: 3840, height: 2160 });
|
||||
mocks.media.copyTagGroup.mockResolvedValue(true);
|
||||
|
||||
mocks.assetJob.getForGenerateThumbnailJob.mockResolvedValue(assetStub.panoramaTif);
|
||||
|
||||
@@ -890,6 +891,13 @@ describe(MediaService.name, () => {
|
||||
},
|
||||
expect.any(String),
|
||||
);
|
||||
|
||||
expect(mocks.media.copyTagGroup).toHaveBeenCalledTimes(2);
|
||||
expect(mocks.media.copyTagGroup).toHaveBeenCalledWith(
|
||||
'XMP-GPano',
|
||||
assetStub.panoramaTif.originalPath,
|
||||
expect.any(String),
|
||||
);
|
||||
});
|
||||
|
||||
it('should respect encoding options when generating full-size preview', async () => {
|
||||
|
||||
@@ -316,6 +316,16 @@ export class MediaService extends BaseService {
|
||||
|
||||
const outputs = await Promise.all(promises);
|
||||
|
||||
if (asset.exifInfo.projectionType === 'EQUIRECTANGULAR') {
|
||||
const promises = [
|
||||
this.mediaRepository.copyTagGroup('XMP-GPano', asset.originalPath, previewPath),
|
||||
fullsizePath
|
||||
? this.mediaRepository.copyTagGroup('XMP-GPano', asset.originalPath, fullsizePath)
|
||||
: Promise.resolve(),
|
||||
];
|
||||
await Promise.all(promises);
|
||||
}
|
||||
|
||||
return { previewPath, thumbnailPath, fullsizePath, thumbhash: outputs[0] as Buffer };
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ export const newMediaRepositoryMock = (): Mocked<RepositoryInterface<MediaReposi
|
||||
return {
|
||||
generateThumbnail: vitest.fn().mockImplementation(() => Promise.resolve()),
|
||||
writeExif: vitest.fn().mockImplementation(() => Promise.resolve()),
|
||||
copyTagGroup: vitest.fn().mockImplementation(() => Promise.resolve()),
|
||||
generateThumbhash: vitest.fn().mockResolvedValue(Buffer.from('')),
|
||||
decodeImage: vitest.fn().mockResolvedValue({ data: Buffer.from(''), info: {} }),
|
||||
extract: vitest.fn().mockResolvedValue(null),
|
||||
|
||||
Reference in New Issue
Block a user