0
Fork 0
mirror of https://github.com/immich-app/immich.git synced 2025-02-11 01:18:24 -05:00

Merge branch 'feat/nullable-dates' of https://github.com/immich-app/immich into feat/inline-offline-check

This commit is contained in:
Jonathan Jogenfors 2025-02-08 01:08:31 +01:00
commit 92177576c1
5 changed files with 21 additions and 62 deletions

View file

@ -542,7 +542,6 @@ describe(AssetMediaService.name, () => {
it('should throw an error if the requested preview file does not exist', async () => {
accessMock.asset.checkOwnerAccess.mockResolvedValue(new Set([assetStub.image.id]));
assetMock.getById.mockResolvedValue({
...assetStub.image,
files: [
@ -563,7 +562,6 @@ describe(AssetMediaService.name, () => {
it('should fall back to preview if the requested thumbnail file does not exist', async () => {
accessMock.asset.checkOwnerAccess.mockResolvedValue(new Set([assetStub.image.id]));
assetMock.getById.mockResolvedValue({
...assetStub.image,
files: [

View file

@ -574,8 +574,7 @@ export class LibraryService extends BaseService {
}
const mtime = stat.mtime;
const isTimeUpdated = asset.fileModifiedAt === null || mtime.toISOString() !== asset.fileModifiedAt.toISOString();
const isTimeUpdated = !asset.fileModifiedAt || mtime.toISOString() !== asset.fileModifiedAt.toISOString();
if (isTimeUpdated) {
this.logger.verbose(

View file

@ -1,4 +1,4 @@
import { BadRequestException, Injectable } from '@nestjs/common';
import { Injectable } from '@nestjs/common';
import { ContainerDirectoryItem, ExifDateTime, Maybe, Tags } from 'exiftool-vendored';
import { firstDateTime } from 'exiftool-vendored/dist/FirstDateTime';
import { Insertable } from 'kysely';
@ -588,17 +588,7 @@ export class MetadataService extends BaseService {
}
}
private getDates(asset: AssetEntity, exifTags: ImmichTags): AssetDatesDto {
// We first assert that fileCreatedAt and fileModifiedAt are not null since that should be set to a non-null value before calling this function
if (asset.fileCreatedAt === null) {
this.logger.warn(`Asset ${asset.id} has no file creation date`);
throw new BadRequestException(`Asset ${asset.id} has no file creation date`);
}
if (asset.fileModifiedAt === null) {
this.logger.warn(`Asset ${asset.id} has no file modification date`);
throw new BadRequestException(`Asset ${asset.id} has no file modification date`);
}
private getDates(asset: AssetEntity, exifTags: ImmichTags) {
const dateTime = firstDateTime(exifTags as Maybe<Tags>, EXIF_DATE_TAGS);
this.logger.verbose(`Asset ${asset.id} date time is ${dateTime}`);
@ -630,11 +620,7 @@ export class MetadataService extends BaseService {
localDateTime = earliestDate;
}
if (localDateTime) {
this.logger.verbose(`Asset ${asset.id} has a local time of ${localDateTime.toISOString()}`);
} else {
this.logger.verbose(`Asset ${asset.id} has no time set`);
}
this.logger.verbose(`Asset ${asset.id} has a local time of ${localDateTime.toISOString()}`);
let modifyDate = asset.fileModifiedAt;
try {

View file

@ -310,12 +310,6 @@ export class StorageTemplateService extends BaseService {
const systemTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
const zone = asset.exifInfo?.timeZone || systemTimeZone;
if (!asset.fileCreatedAt) {
this.logger.log(`Asset ${asset.id} is missing fileCreatedAt, skipping storage template migration`);
throw new Error(`Missing fileCreatedAt for asset ${asset.id}`);
}
const dt = DateTime.fromJSDate(asset.fileCreatedAt, { zone });
for (const token of Object.values(storageTokens).flat()) {

View file

@ -29,8 +29,6 @@ type TimeZoneTest = {
description: string;
serverTimeZone?: string;
exifData: Record<string, any>;
fileCreatedAt: Date;
fileModifiedAt: Date;
expected: {
localDateTime: string;
dateTimeOriginal: string;
@ -60,8 +58,6 @@ describe(MetadataService.name, () => {
const timeZoneTests: TimeZoneTest[] = [
{
description: 'should handle no time zone information',
fileCreatedAt: new Date('2022-01-01T00:00:00.000Z'),
fileModifiedAt: new Date('2022-01-01T00:00:00.000Z'),
exifData: {
DateTimeOriginal: '2022:01:01 00:00:00',
},
@ -73,8 +69,6 @@ describe(MetadataService.name, () => {
},
{
description: 'should handle no time zone information and server behind UTC',
fileCreatedAt: new Date('2022-01-01T00:00:00.000Z'),
fileModifiedAt: new Date('2022-01-01T00:00:00.000Z'),
serverTimeZone: 'America/Los_Angeles',
exifData: {
DateTimeOriginal: '2022:01:01 00:00:00',
@ -87,8 +81,6 @@ describe(MetadataService.name, () => {
},
{
description: 'should handle no time zone information and server ahead of UTC',
fileCreatedAt: new Date('2022-01-01T00:00:00.000Z'),
fileModifiedAt: new Date('2022-01-01T00:00:00.000Z'),
serverTimeZone: 'Europe/Brussels',
exifData: {
DateTimeOriginal: '2022:01:01 00:00:00',
@ -101,8 +93,6 @@ describe(MetadataService.name, () => {
},
{
description: 'should handle no time zone information and server ahead of UTC in the summer',
fileCreatedAt: new Date('2022-01-01T00:00:00.000Z'),
fileModifiedAt: new Date('2022-01-01T00:00:00.000Z'),
serverTimeZone: 'Europe/Brussels',
exifData: {
DateTimeOriginal: '2022:06:01 00:00:00',
@ -115,8 +105,6 @@ describe(MetadataService.name, () => {
},
{
description: 'should handle a +13:00 time zone',
fileCreatedAt: new Date('2022-01-01T00:00:00.000Z'),
fileModifiedAt: new Date('2022-01-01T00:00:00.000Z'),
exifData: {
DateTimeOriginal: '2022:01:01 00:00:00+13:00',
},
@ -128,32 +116,26 @@ describe(MetadataService.name, () => {
},
];
it.each(timeZoneTests)(
'$description',
async ({ exifData, serverTimeZone, expected, fileCreatedAt, fileModifiedAt }) => {
// TODO: the TZ environment variable is no longer used, remove it
process.env.TZ = serverTimeZone ?? undefined;
it.each(timeZoneTests)('$description', async ({ exifData, serverTimeZone, expected }) => {
process.env.TZ = serverTimeZone ?? undefined;
const { filePath } = await createTestFile(exifData);
assetMock.getByIds.mockResolvedValue([
{ id: 'asset-1', originalPath: filePath, fileCreatedAt, fileModifiedAt } as AssetEntity,
]);
const { filePath } = await createTestFile(exifData);
assetMock.getByIds.mockResolvedValue([{ id: 'asset-1', originalPath: filePath } as AssetEntity]);
await sut.handleMetadataExtraction({ id: 'asset-1' });
await sut.handleMetadataExtraction({ id: 'asset-1' });
expect(assetMock.upsertExif).toHaveBeenCalledWith(
expect.objectContaining({
dateTimeOriginal: new Date(expected.dateTimeOriginal),
timeZone: expected.timeZone,
}),
);
expect(assetMock.upsertExif).toHaveBeenCalledWith(
expect.objectContaining({
dateTimeOriginal: new Date(expected.dateTimeOriginal),
timeZone: expected.timeZone,
}),
);
expect(assetMock.update).toHaveBeenCalledWith(
expect.objectContaining({
localDateTime: new Date(expected.localDateTime),
}),
);
},
);
expect(assetMock.update).toHaveBeenCalledWith(
expect.objectContaining({
localDateTime: new Date(expected.localDateTime),
}),
);
});
});
});