1
0
mirror of https://github.com/immich-app/immich.git synced 2025-02-06 18:45:04 +02: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-06 01:35:58 +01:00
commit 73871a6caa
8 changed files with 13 additions and 55 deletions

24
server/src/db.d.ts vendored
View File

@ -214,20 +214,6 @@ export interface GeodataPlaces {
name: string;
}
export interface GeodataPlacesTmp {
admin1Code: string | null;
admin1Name: string | null;
admin2Code: string | null;
admin2Name: string | null;
alternateNames: string | null;
countryCode: string;
id: number;
latitude: number;
longitude: number;
modificationDate: Timestamp;
name: string;
}
export interface Libraries {
createdAt: Generated<Timestamp>;
deletedAt: Timestamp | null;
@ -280,14 +266,6 @@ export interface NaturalearthCountries {
type: string;
}
export interface NaturalearthCountriesTmp {
admin: string;
admin_a3: string;
coordinates: string;
id: Generated<number>;
type: string;
}
export interface Partners {
createdAt: Generated<Timestamp>;
inTimeline: Generated<boolean>;
@ -445,14 +423,12 @@ export interface DB {
exif: Exif;
face_search: FaceSearch;
geodata_places: GeodataPlaces;
geodata_places_tmp: GeodataPlacesTmp;
libraries: Libraries;
memories: Memories;
memories_assets_assets: MemoriesAssetsAssets;
migrations: Migrations;
move_history: MoveHistory;
naturalearth_countries: NaturalearthCountries;
naturalearth_countries_tmp: NaturalearthCountriesTmp;
partners: Partners;
person: Person;
sessions: Sessions;

View File

@ -164,8 +164,8 @@ export const mapAlbum = (entity: AlbumEntity, withAssets: boolean, auth?: AuthDt
const hasSharedLink = entity.sharedLinks?.length > 0;
const hasSharedUser = sharedUsers.length > 0;
let startDate = assets.at(0)?.localDateTime || undefined;
let endDate = assets.at(-1)?.localDateTime || undefined;
let startDate = assets.at(0)?.localDateTime;
let endDate = assets.at(-1)?.localDateTime;
// Swap dates if start date is greater than end date.
if (startDate && endDate && startDate > endDate) {
[startDate, endDate] = [endDate, startDate];

View File

@ -126,15 +126,6 @@ export class AssetStatsResponseDto {
total!: number;
}
export class AssetDatesDto {
dateTimeOriginal!: Date;
timeZone!: string | null;
localDateTime!: Date;
modifyDate!: Date;
fileCreatedAt!: Date;
fileModifiedAt!: Date;
}
export const mapStats = (stats: AssetStats): AssetStatsResponseDto => {
return {
images: stats[AssetType.IMAGE],

View File

@ -621,6 +621,9 @@ export class AssetRepository implements IAssetRepository {
.$if(!!options.isTrashed, (qb) => qb.where('assets.status', '!=', AssetStatus.DELETED))
.where('assets.deletedAt', options.isTrashed ? 'is not' : 'is', null)
.where('assets.isVisible', '=', true)
.where('assets.fileCreatedAt', 'is not', null)
.where('assets.fileModifiedAt', 'is not', null)
.where('assets.localDateTime', 'is not', null)
.$if(!!options.albumId, (qb) =>
qb
.innerJoin('albums_assets_assets', 'assets.id', 'albums_assets_assets.assetsId')

View File

@ -543,10 +543,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]));
if (!assetStub.image.fileCreatedAt) {
throw new Error('fileCreatedAt is missing');
}
assetMock.getById.mockResolvedValue({
...assetStub.image,
files: [
@ -568,10 +564,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]));
if (!assetStub.image.fileCreatedAt) {
throw new Error('fileCreatedAt is missing');
}
assetMock.getById.mockResolvedValue({
...assetStub.image,
files: [

View File

@ -339,6 +339,7 @@ describe(MetadataService.name, () => {
id: assetStub.image.id,
duration: null,
fileCreatedAt: assetStub.image.fileCreatedAt,
fileModifiedAt: assetStub.image.fileModifiedAt,
localDateTime: assetStub.image.fileCreatedAt,
});
});

View File

@ -10,7 +10,6 @@ import { SystemConfig } from 'src/config';
import { StorageCore } from 'src/cores/storage.core';
import { Exif } from 'src/db';
import { OnEvent, OnJob } from 'src/decorators';
import { AssetDatesDto } from 'src/dtos/asset.dto';
import { AssetFaceEntity } from 'src/entities/asset-face.entity';
import { AssetEntity } from 'src/entities/asset.entity';
import { PersonEntity } from 'src/entities/person.entity';
@ -38,6 +37,13 @@ const EXIF_DATE_TAGS: Array<keyof Tags> = [
'DateTimeCreated',
];
class AssetDatesDto {
dateTimeOriginal!: Date;
timeZone!: string | null;
localDateTime!: Date;
modifyDate!: Date;
}
const validate = <T>(value: T): NonNullable<T> | null => {
// handle lists of numbers
if (Array.isArray(value)) {
@ -464,7 +470,6 @@ export class MetadataService extends BaseService {
}
} else {
const motionAssetId = this.cryptoRepository.randomUUID();
const dates = this.getDates(asset, tags);
motionAsset = await this.assetRepository.create({
id: motionAssetId,
@ -641,8 +646,6 @@ export class MetadataService extends BaseService {
timeZone,
localDateTime,
modifyDate,
fileCreatedAt,
fileModifiedAt,
};
}

View File

@ -179,10 +179,6 @@ describe(StorageTemplateService.name, () => {
expect(await sut.handleMigrationSingle({ id: asset.id })).toBe(JobStatus.SUCCESS);
if (asset.fileCreatedAt == null) {
throw new Error('fileCreatedAt must be set');
}
expect(moveMock.create).toHaveBeenCalledWith({
entityId: asset.id,
newPath: `upload/library/${user.id}/${asset.fileCreatedAt.getFullYear()}/${album.albumName}/${asset.originalFileName}`,
@ -203,10 +199,6 @@ describe(StorageTemplateService.name, () => {
expect(await sut.handleMigrationSingle({ id: asset.id })).toBe(JobStatus.SUCCESS);
if (asset.fileCreatedAt == null) {
throw new Error('fileCreatedAt must be set');
}
const month = (asset.fileCreatedAt.getMonth() + 1).toString().padStart(2, '0');
expect(moveMock.create).toHaveBeenCalledWith({
entityId: asset.id,