Files
immich/server/src/utils/preferences.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

93 lines
2.4 KiB
TypeScript

import _ from 'lodash';
import { UserPreferencesUpdateDto } from 'src/dtos/user-preferences.dto';
import { AssetOrder, UserMetadataKey } from 'src/enum';
import { DeepPartial, UserMetadataItem, UserPreferences } from 'src/types';
import { HumanReadableSize } from 'src/utils/bytes';
import { getKeysDeep } from 'src/utils/misc';
const getDefaultPreferences = (): UserPreferences => {
return {
albums: {
defaultAssetOrder: AssetOrder.Desc,
},
folders: {
enabled: false,
sidebarWeb: false,
},
memories: {
enabled: true,
duration: 5,
},
people: {
enabled: true,
sidebarWeb: false,
minimumFaces: 3,
},
sharedLinks: {
enabled: true,
sidebarWeb: false,
},
ratings: {
enabled: false,
},
tags: {
enabled: false,
sidebarWeb: false,
},
emailNotifications: {
enabled: true,
albumInvite: true,
albumUpdate: true,
},
download: {
archiveSize: HumanReadableSize.GiB * 4,
includeEmbeddedVideos: false,
},
purchase: {
showSupportBadge: true,
hideBuyButtonUntil: new Date(2022, 1, 12).toISOString(),
},
cast: {
gCastEnabled: false,
},
};
};
export const getPreferences = (metadata: UserMetadataItem[]): UserPreferences => {
const preferences = getDefaultPreferences();
const item = metadata.find(({ key }) => key === UserMetadataKey.Preferences);
const partial = item?.value || {};
for (const property of getKeysDeep(partial)) {
_.set(preferences, property, _.get(partial, property));
}
return preferences;
};
export const getPreferencesPartial = (newPreferences: UserPreferences) => {
const defaultPreferences = getDefaultPreferences();
const partial: DeepPartial<UserPreferences> = {};
for (const property of getKeysDeep(defaultPreferences)) {
const newValue = _.get(newPreferences, property);
const isEmpty = newValue === undefined || newValue === null || newValue === '';
const defaultValue = _.get(defaultPreferences, property);
const isEqual = newValue === defaultValue || _.isEqual(newValue, defaultValue);
if (isEmpty || isEqual) {
continue;
}
_.set(partial, property, newValue);
}
return partial;
};
export const mergePreferences = (preferences: UserPreferences, dto: UserPreferencesUpdateDto) => {
for (const key of getKeysDeep(dto)) {
_.set(preferences, key, _.get(dto, key));
}
return preferences;
};