Files
immich/server/src/dtos/user-preferences.dto.ts
T
Tim Jones 368cb7a4ad feat: minimum face count per user (#27452)
* add user metadata table and use to filter persons in person.getAllForUser query

* update PersonRepository.getAllForUser query

* remove minFaces from PersonSearchOptions interface

* fix person.getAllForUser query

* update types and openapi specs

* add minFaces field to user settings page

* remove old arg from tests

* add e2e test to verify minimumFace user preference

* add i18n label and description for english

* update default min faces

* fetch minFaces ML default and use as per-user default in frontend

* update e2e tests

* fix bugs in people getAllForUser query

* update person getNumberOfPeople query to reflect correct number of people according to minFaces threshold

* updated mobile openapi specs?

* use subquery in coalesce instead of join

* remove out of scope query update
2026-06-02 18:05:55 +02:00

216 lines
7.0 KiB
TypeScript

import { createZodDto } from 'nestjs-zod';
import { AssetOrderSchema, UserAvatarColorSchema } from 'src/enum';
import { UserPreferences } from 'src/types';
import z from 'zod';
const AlbumsUpdateSchema = z
.object({
defaultAssetOrder: AssetOrderSchema.optional(),
})
.optional()
.describe('Album preferences')
.meta({ id: 'AlbumsUpdate' });
const AvatarUpdateSchema = z
.object({
color: UserAvatarColorSchema.optional(),
})
.optional()
.meta({ id: 'AvatarUpdate' });
const MemoriesUpdateSchema = z
.object({
enabled: z.boolean().optional().describe('Whether memories are enabled'),
duration: z.int().min(1).optional().describe('Memory duration in seconds'),
})
.optional()
.meta({ id: 'MemoriesUpdate' });
const RatingsUpdateSchema = z
.object({
enabled: z.boolean().optional().describe('Whether ratings are enabled'),
})
.optional()
.meta({ id: 'RatingsUpdate' });
const FoldersUpdateSchema = z
.object({
enabled: z.boolean().optional().describe('Whether folders are enabled'),
sidebarWeb: z.boolean().optional().describe('Whether folders appear in web sidebar'),
})
.optional()
.meta({ id: 'FoldersUpdate' });
const PeopleUpdateSchema = z
.object({
enabled: z.boolean().optional().describe('Whether people are enabled'),
sidebarWeb: z.boolean().optional().describe('Whether people appear in web sidebar'),
minimumFaces: z.int().min(1).optional().describe('People face threshold'),
})
.optional()
.meta({ id: 'PeopleUpdate' });
const SharedLinksUpdateSchema = z
.object({
enabled: z.boolean().optional().describe('Whether shared links are enabled'),
sidebarWeb: z.boolean().optional().describe('Whether shared links appear in web sidebar'),
})
.optional()
.meta({ id: 'SharedLinksUpdate' });
const TagsUpdateSchema = z
.object({
enabled: z.boolean().optional().describe('Whether tags are enabled'),
sidebarWeb: z.boolean().optional().describe('Whether tags appear in web sidebar'),
})
.optional()
.meta({ id: 'TagsUpdate' });
const EmailNotificationsUpdateSchema = z
.object({
enabled: z.boolean().optional().describe('Whether email notifications are enabled'),
albumInvite: z.boolean().optional().describe('Whether to receive email notifications for album invites'),
albumUpdate: z.boolean().optional().describe('Whether to receive email notifications for album updates'),
})
.optional()
.meta({ id: 'EmailNotificationsUpdate' });
const DownloadUpdateSchema = z
.object({
archiveSize: z.int().min(1).optional().describe('Maximum archive size in bytes'),
includeEmbeddedVideos: z.boolean().optional().describe('Whether to include embedded videos in downloads'),
})
.optional()
.meta({ id: 'DownloadUpdate' });
const PurchaseUpdateSchema = z
.object({
showSupportBadge: z.boolean().optional().describe('Whether to show support badge'),
hideBuyButtonUntil: z.string().optional().describe('Date until which to hide buy button'),
})
.optional()
.meta({ id: 'PurchaseUpdate' });
const CastUpdateSchema = z
.object({
gCastEnabled: z.boolean().optional().describe('Whether Google Cast is enabled'),
})
.optional()
.meta({ id: 'CastUpdate' });
const UserPreferencesUpdateSchema = z
.object({
albums: AlbumsUpdateSchema,
avatar: AvatarUpdateSchema,
cast: CastUpdateSchema,
download: DownloadUpdateSchema,
emailNotifications: EmailNotificationsUpdateSchema,
folders: FoldersUpdateSchema,
memories: MemoriesUpdateSchema,
people: PeopleUpdateSchema,
purchase: PurchaseUpdateSchema,
ratings: RatingsUpdateSchema,
sharedLinks: SharedLinksUpdateSchema,
tags: TagsUpdateSchema,
})
.meta({ id: 'UserPreferencesUpdateDto' });
const AlbumsResponseSchema = z
.object({
defaultAssetOrder: AssetOrderSchema,
})
.meta({ id: 'AlbumsResponse' });
const FoldersResponseSchema = z
.object({
enabled: z.boolean().describe('Whether folders are enabled'),
sidebarWeb: z.boolean().describe('Whether folders appear in web sidebar'),
})
.meta({ id: 'FoldersResponse' });
const MemoriesResponseSchema = z
.object({
enabled: z.boolean().describe('Whether memories are enabled'),
duration: z.int().describe('Memory duration in seconds'),
})
.meta({ id: 'MemoriesResponse' });
const PeopleResponseSchema = z
.object({
enabled: z.boolean().describe('Whether people are enabled'),
sidebarWeb: z.boolean().describe('Whether people appear in web sidebar'),
minimumFaces: z.int().min(1).optional().describe('People face threshold'),
})
.meta({ id: 'PeopleResponse' });
const RatingsResponseSchema = z
.object({
enabled: z.boolean().describe('Whether ratings are enabled'),
})
.meta({ id: 'RatingsResponse' });
const SharedLinksResponseSchema = z
.object({
enabled: z.boolean().describe('Whether shared links are enabled'),
sidebarWeb: z.boolean().describe('Whether shared links appear in web sidebar'),
})
.meta({ id: 'SharedLinksResponse' });
const TagsResponseSchema = z
.object({
enabled: z.boolean().describe('Whether tags are enabled'),
sidebarWeb: z.boolean().describe('Whether tags appear in web sidebar'),
})
.meta({ id: 'TagsResponse' });
const EmailNotificationsResponseSchema = z
.object({
enabled: z.boolean().describe('Whether email notifications are enabled'),
albumInvite: z.boolean().describe('Whether to receive email notifications for album invites'),
albumUpdate: z.boolean().describe('Whether to receive email notifications for album updates'),
})
.meta({ id: 'EmailNotificationsResponse' });
const DownloadResponseSchema = z
.object({
archiveSize: z.int().describe('Maximum archive size in bytes'),
includeEmbeddedVideos: z.boolean().describe('Whether to include embedded videos in downloads'),
})
.meta({ id: 'DownloadResponse' });
const PurchaseResponseSchema = z
.object({
showSupportBadge: z.boolean().describe('Whether to show support badge'),
hideBuyButtonUntil: z.string().describe('Date until which to hide buy button'),
})
.meta({ id: 'PurchaseResponse' });
const CastResponseSchema = z
.object({
gCastEnabled: z.boolean().describe('Whether Google Cast is enabled'),
})
.meta({ id: 'CastResponse' });
const UserPreferencesResponseSchema = z
.object({
albums: AlbumsResponseSchema,
folders: FoldersResponseSchema,
memories: MemoriesResponseSchema,
people: PeopleResponseSchema,
ratings: RatingsResponseSchema,
sharedLinks: SharedLinksResponseSchema,
tags: TagsResponseSchema,
emailNotifications: EmailNotificationsResponseSchema,
download: DownloadResponseSchema,
purchase: PurchaseResponseSchema,
cast: CastResponseSchema,
})
.meta({ id: 'UserPreferencesResponseDto' });
export class UserPreferencesUpdateDto extends createZodDto(UserPreferencesUpdateSchema) {}
export class UserPreferencesResponseDto extends createZodDto(UserPreferencesResponseSchema) {}
export const mapPreferences = (preferences: UserPreferences): UserPreferencesResponseDto => {
return preferences;
};