chore: single line block comments (#30852)

This commit is contained in:
Daniel Dietzler 2026-08-18 17:55:26 +02:00 committed by GitHub
parent 80a90fabf3
commit 03da1ba108
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
34 changed files with 102 additions and 294 deletions

View file

@ -45,6 +45,7 @@ export default typescriptEslint.config([
'unicorn/prefer-promise-with-resolvers': 'off',
'unicorn/no-declarations-before-early-exit': 'off',
'unicorn/prefer-simple-condition-first': 'off',
'unicorn/single-line-block-comment-style': ['error', 'single-line'],
curly: 2,
'prettier/prettier': 0,
'unicorn/name-replacements': 'off',

View file

@ -29,9 +29,7 @@ describe('/users', () => {
});
describe('PUT /users/me', () => {
/**
@deprecated
*/
/** @deprecated */
it('should allow a user to change their password (deprecated)', async () => {
const user = await getMyUser({ headers: asBearerAuth(nonAdmin.accessToken) });

View file

@ -42,6 +42,7 @@ export default typescriptEslint.config([
'unicorn/import-style': 'off',
'unicorn/consistent-class-member-order': 'off',
'unicorn/prefer-simple-condition-first': 'off',
'unicorn/single-line-block-comment-style': ['error', 'single-line'],
curly: 2,
// prefer the typescript-eslint type-aware version
'unicorn/require-array-sort-compare': 'off',

View file

@ -51,6 +51,7 @@ export default typescriptEslint.config([
'unicorn/max-nested-calls': 'off',
'unicorn/no-declarations-before-early-exit': 'off',
'unicorn/no-unreadable-object-destructuring': 'off',
'unicorn/single-line-block-comment-style': ['error', 'single-line'],
// maybe we do want to enable this later. TBD
'unicorn/prefer-await': 'off',
'unicorn/consistent-class-member-order': 'off',

View file

@ -7,9 +7,7 @@ import request from 'supertest';
import { errorDto } from 'test/medium/responses';
import { ControllerContext, controllerSetup, mockBaseService } from 'test/utils';
/**
Returns a full config that passes Zod validation (required URLs and min lengths).
*/
/** Returns a full config that passes Zod validation (required URLs and min lengths). */
function validConfig() {
const config = _.cloneDeep(defaults) as typeof defaults & {
oauth: { mobileRedirectUri: string };

View file

@ -136,24 +136,16 @@ export interface GenerateSqlQueries {
export const Telemetry = (options: { enabled?: boolean }) =>
SetMetadata(MetadataKey.TelemetryEnabled, options?.enabled ?? true);
/**
Decorator to enable versioning/tracking of generated Sql
*/
/** Decorator to enable versioning/tracking of generated Sql */
export const GenerateSql = (...options: GenerateSqlQueries[]) => SetMetadata(GENERATE_SQL_KEY, options);
export type EventConfig = {
name: EmitEvent;
/**
handle socket.io server events as well
*/
/** handle socket.io server events as well */
server?: boolean;
/**
lower value has higher priority, defaults to 0
*/
/** lower value has higher priority, defaults to 0 */
priority?: number;
/**
register events for these workers, defaults to all workers
*/
/** register events for these workers, defaults to all workers */
workers?: ImmichWorker[];
};
export const OnEvent = (config: EventConfig) => SetMetadata(MetadataKey.EventConfig, config);
@ -191,9 +183,7 @@ type HistoryEntry = {
};
type DeprecatedOptions = {
/**
replacement operationId
*/
/** replacement operationId */
replacementId?: string;
};

View file

@ -1,9 +1,7 @@
import { createZodDto } from 'nestjs-zod';
import z from 'zod';
/**
@deprecated Use `BulkIdResponseDto` instead
*/
/** @deprecated Use `BulkIdResponseDto` instead */
export enum AssetIdErrorReason {
DUPLICATE = 'duplicate',
NO_PERMISSION = 'no_permission',
@ -15,9 +13,7 @@ const AssetIdErrorReasonSchema = z
.describe('Error reason if failed')
.meta({ id: 'AssetIdErrorReason' });
/**
@deprecated Use `BulkIdResponseDto` instead
*/
/** @deprecated Use `BulkIdResponseDto` instead */
const AssetIdsResponseSchema = z
.object({
assetId: z.uuidv4().describe('Asset ID'),
@ -54,9 +50,7 @@ const BulkIdResponseSchema = z
})
.meta({ id: 'BulkIdResponseDto' });
/**
@deprecated Use `BulkIdResponseDto` instead
*/
/** @deprecated Use `BulkIdResponseDto` instead */
export class AssetIdsResponseDto extends createZodDto(AssetIdsResponseSchema) {}
export class BulkIdsDto extends createZodDto(BulkIdsSchema) {}
export class BulkIdResponseDto extends createZodDto(BulkIdResponseSchema) {}

View file

@ -40,9 +40,7 @@ const AssetMediaBaseSchema = z.object({
fileModifiedAt: isoDatetimeToDate.describe('File modification date'),
duration: z.coerce.number().int().min(0).optional().describe('Duration in milliseconds (for videos)'),
filename: z.string().optional().describe('Filename'),
/**
The properties below are added to correctly generate the API docs and client SDKs. Validation should be handled in the controller.
*/
/** The properties below are added to correctly generate the API docs and client SDKs. Validation should be handled in the controller. */
[UploadFieldName.ASSET_DATA]: z.any().describe('Asset file data').meta({ type: 'string', format: 'binary' }),
});

View file

@ -23,9 +23,7 @@ import {
} from 'src/enum';
import z from 'zod';
/**
Coerces 'true'/'false' strings to boolean, but also allows booleans.
*/
/** Coerces 'true'/'false' strings to boolean, but also allows booleans. */
const configBool = z
.preprocess((val) => {
if (val === 'true') {

View file

@ -45,13 +45,9 @@ export enum AssetType {
export const AssetTypeSchema = z.enum(AssetType).describe('Asset type').meta({ id: 'AssetTypeEnum' });
export enum ChecksumAlgorithm {
/**
sha1 checksum of the whole file contents
*/
/** sha1 checksum of the whole file contents */
sha1File = 'sha1',
/**
sha1 checksum of "path:" plus the file path, currently used in external libraries, deprecated
*/
/** sha1 checksum of "path:" plus the file path, currently used in external libraries, deprecated */
sha1Path = 'sha1-path',
}
@ -89,9 +85,7 @@ export enum AssetOrderBy {
export const AssetOrderBySchema = z.enum(AssetOrderBy).describe('Asset sorting property').meta({ id: 'AssetOrderBy' });
export enum MemoryType {
/**
pictures taken on this day X years ago
*/
/** pictures taken on this day X years ago */
OnThisDay = 'on_this_day',
}
@ -101,9 +95,7 @@ export enum AssetOrderWithRandom {
// Include existing values
Asc = AssetOrder.Asc,
Desc = AssetOrder.Desc,
/**
Randomly Ordered
*/
/** Randomly Ordered */
Random = 'random',
}
@ -650,9 +642,7 @@ export enum ExifOrientation {
Rotate270CW = 8,
}
/**
ITU-T H.273 colour primaries codes.
*/
/** ITU-T H.273 colour primaries codes. */
export enum ColorPrimaries {
Reserved = 0,
Bt709 = 1,
@ -669,9 +659,7 @@ export enum ColorPrimaries {
Ebu3213 = 22,
}
/**
ITU-T H.273 transfer characteristics codes.
*/
/** ITU-T H.273 transfer characteristics codes. */
export enum ColorTransfer {
Reserved = 0,
Bt709 = 1,
@ -693,9 +681,7 @@ export enum ColorTransfer {
AribStdB67 = 18,
}
/**
ITU-T H.273 matrix coefficients codes.
*/
/** ITU-T H.273 matrix coefficients codes. */
export enum ColorMatrix {
Gbr = 0,
Bt709 = 1,
@ -714,9 +700,7 @@ export enum ColorMatrix {
Ictcp = 14,
}
/**
H.264 `profile_idc` values.
*/
/** H.264 `profile_idc` values. */
// H.264 has a few profiles that have the same value but different names, included so lookup by name works
export enum H264Profile {
ConstrainedBaseline = 66,
@ -734,9 +718,7 @@ export enum H264Profile {
High444Predictive = 244,
}
/**
HEVC `profile_idc` values.
*/
/** HEVC `profile_idc` values. */
export enum HevcProfile {
Main = 1,
Main10 = 2,
@ -744,18 +726,14 @@ export enum HevcProfile {
Rext = 4,
}
/**
AV1 `seq_profile` values.
*/
/** AV1 `seq_profile` values. */
export enum Av1Profile {
Main = 0,
High = 1,
Professional = 2,
}
/**
MPEG-4 Audio Object Type values for AAC.
*/
/** MPEG-4 Audio Object Type values for AAC. */
export enum AacProfile {
Main = 1,
Lc = 2,
@ -768,9 +746,7 @@ export enum AacProfile {
XheAac = 42,
}
/**
Dolby Vision bitstream profile numbers from the DOVI configuration record.
*/
/** Dolby Vision bitstream profile numbers from the DOVI configuration record. */
export enum DvProfile {
Dvhe03 = 3,
Dvhe04 = 4,
@ -946,21 +922,13 @@ export const JobNameSchema = z.enum(JobName).describe('Job name').meta({ id: 'Jo
export enum QueueCommand {
Start = 'start',
/**
@deprecated Use `updateQueue` instead
*/
/** @deprecated Use `updateQueue` instead */
Pause = 'pause',
/**
@deprecated Use `updateQueue` instead
*/
/** @deprecated Use `updateQueue` instead */
Resume = 'resume',
/**
@deprecated Use `emptyQueue` instead
*/
/** @deprecated Use `emptyQueue` instead */
Empty = 'empty',
/**
@deprecated Use `emptyQueue` instead
*/
/** @deprecated Use `emptyQueue` instead */
ClearFailed = 'clear-failed',
}
@ -1025,15 +993,11 @@ export enum SyncRequestType {
AlbumsV2 = 'AlbumsV2',
AlbumUsersV1 = 'AlbumUsersV1',
AlbumToAssetsV1 = 'AlbumToAssetsV1',
/**
@deprecated
*/
/** @deprecated */
AlbumAssetsV1 = 'AlbumAssetsV1',
AlbumAssetsV2 = 'AlbumAssetsV2',
AlbumAssetExifsV1 = 'AlbumAssetExifsV1',
/**
@deprecated
*/
/** @deprecated */
AssetsV1 = 'AssetsV1',
AssetsV2 = 'AssetsV2',
AssetExifsV1 = 'AssetExifsV1',
@ -1044,9 +1008,7 @@ export enum SyncRequestType {
MemoriesV1 = 'MemoriesV1',
MemoryToAssetsV1 = 'MemoryToAssetsV1',
PartnersV1 = 'PartnersV1',
/**
@deprecated
*/
/** @deprecated */
PartnerAssetsV1 = 'PartnerAssetsV1',
PartnerAssetsV2 = 'PartnerAssetsV2',
PartnerAssetExifsV1 = 'PartnerAssetExifsV1',
@ -1054,9 +1016,7 @@ export enum SyncRequestType {
StacksV1 = 'StacksV1',
UsersV1 = 'UsersV1',
PeopleV1 = 'PeopleV1',
/**
@deprecated
*/
/** @deprecated */
AssetFacesV1 = 'AssetFacesV1',
AssetFacesV2 = 'AssetFacesV2',
UserMetadataV1 = 'UserMetadataV1',
@ -1073,9 +1033,7 @@ export enum SyncEntityType {
UserV1 = 'UserV1',
UserDeleteV1 = 'UserDeleteV1',
/**
@deprecated
*/
/** @deprecated */
AssetV1 = 'AssetV1',
AssetV2 = 'AssetV2',
AssetDeleteV1 = 'AssetDeleteV1',
@ -1090,14 +1048,10 @@ export enum SyncEntityType {
PartnerV1 = 'PartnerV1',
PartnerDeleteV1 = 'PartnerDeleteV1',
/**
@deprecated
*/
/** @deprecated */
PartnerAssetV1 = 'PartnerAssetV1',
PartnerAssetV2 = 'PartnerAssetV2',
/**
@deprecated
*/
/** @deprecated */
PartnerAssetBackfillV1 = 'PartnerAssetBackfillV1',
PartnerAssetBackfillV2 = 'PartnerAssetBackfillV2',
PartnerAssetDeleteV1 = 'PartnerAssetDeleteV1',
@ -1115,19 +1069,13 @@ export enum SyncEntityType {
AlbumUserBackfillV1 = 'AlbumUserBackfillV1',
AlbumUserDeleteV1 = 'AlbumUserDeleteV1',
/**
@deprecated
*/
/** @deprecated */
AlbumAssetCreateV1 = 'AlbumAssetCreateV1',
AlbumAssetCreateV2 = 'AlbumAssetCreateV2',
/**
@deprecated
*/
/** @deprecated */
AlbumAssetUpdateV1 = 'AlbumAssetUpdateV1',
AlbumAssetUpdateV2 = 'AlbumAssetUpdateV2',
/**
@deprecated
*/
/** @deprecated */
AlbumAssetBackfillV1 = 'AlbumAssetBackfillV1',
AlbumAssetBackfillV2 = 'AlbumAssetBackfillV2',
AlbumAssetExifCreateV1 = 'AlbumAssetExifCreateV1',

View file

@ -25,9 +25,7 @@ export type AuthenticatedOptions = AuthorizedRoute | PublicRoute;
type ReflectorTarget = Parameters<Reflector['get']>[1];
/**
Resolves the `@Authenticated()` options of a route handler, with the defaults applied.
*/
/** Resolves the `@Authenticated()` options of a route handler, with the defaults applied. */
export const getAuthenticatedOptions = (reflector: Reflector, target: ReflectorTarget) => {
const options = reflector.getAllAndOverride<AuthenticatedOptions | undefined>(MetadataKey.AuthRoute, [target]);
return options && { sharedLink: false, admin: false, public: false, setup: false, ...options };

View file

@ -56,25 +56,15 @@ type EventMap = {
AssetDeleteAll: [{ assetIds: string[]; userId: string }];
AssetRestoreAll: [{ assetIds: string[]; userId: string }];
/**
a worker receives a job and emits this event to run it
*/
/** a worker receives a job and emits this event to run it */
JobRun: [QueueName, JobItem];
/**
job pre-hook
*/
/** job pre-hook */
JobStart: [QueueName, JobItem];
/**
job post-hook
*/
/** job post-hook */
JobComplete: [QueueName, JobItem];
/**
job finishes without error
*/
/** job finishes without error */
JobSuccess: [JobSuccessEvent];
/**
job finishes with error
*/
/** job finishes with error */
JobError: [JobErrorEvent];
// queue events
@ -94,13 +84,9 @@ type EventMap = {
// user events
UserSignup: [{ notify: boolean; id: string; password?: string }];
UserCreate: [UserEvent];
/**
user is soft deleted
*/
/** user is soft deleted */
UserTrash: [UserEvent];
/**
user is permanently deleted
*/
/** user is permanently deleted */
UserDelete: [UserEvent];
UserRestore: [UserEvent];

View file

@ -287,9 +287,7 @@ export class JobRepository {
return this.moduleRef.get<Queue>(getQueueToken(queue), { strict: false });
}
/**
@deprecated
*/
/** @deprecated */
// todo: remove this when asset notifications no longer need it.
public async removeJob(name: JobName, jobID: string): Promise<void> {
const existingJob = await this.getQueue(this.getQueueName(name)).getJob(jobID);

View file

@ -464,9 +464,7 @@ export class MediaRepository {
return value ? ((enumObj[pascalCase(value)] as Extract<E[keyof E], number> | undefined) ?? null) : null;
}
/**
Parse a rational like "60000/1001" or "1/600" into `{ num, den }`.
*/
/** Parse a rational like "60000/1001" or "1/600" into `{ num, den }`. */
private parseRational(value: string | undefined): { num: number; den: number } | null {
if (value) {
const [num, den = 1] = value.split('/').map(Number);

View file

@ -135,9 +135,7 @@ export type AssetSearchBuilderOptions = Omit<AssetSearchOptions, 'orderDirection
export interface AssetSearchBuilderV3Options {
filter?: SearchFilter;
/**
Server-derived ownership scope. Never client-controlled.
*/
/** Server-derived ownership scope. Never client-controlled. */
userIds?: string[];
withExif?: boolean;
withFaces?: boolean;

View file

@ -45,21 +45,15 @@ export class MemoryTable {
@Column({ type: 'jsonb' })
data!: Record<string, unknown>;
/**
unless set to true, will be automatically deleted in the future
*/
/** unless set to true, will be automatically deleted in the future */
@Column({ type: 'boolean', default: false })
isSaved!: Generated<boolean>;
/**
memories are sorted in ascending order by this value
*/
/** memories are sorted in ascending order by this value */
@Column({ type: 'timestamp with time zone' })
memoryAt!: Timestamp;
/**
when the user last viewed the memory
*/
/** when the user last viewed the memory */
@Column({ type: 'timestamp with time zone', nullable: true })
seenAt!: Timestamp | null;

View file

@ -48,9 +48,7 @@ export type ValidateRequest = {
metadata: {
sharedLinkRoute: boolean;
adminRoute: boolean;
/**
`false` explicitly means no permission is required, which otherwise defaults to `all`
*/
/** `false` explicitly means no permission is required, which otherwise defaults to `all` */
permission?: Permission | false;
uri: string;
};

View file

@ -42,9 +42,7 @@ import { Tasks } from 'src/utils/tasks';
const POSTGRES_INT_MAX = 2_147_483_647;
const POSTGRES_INT_MIN = -2_147_483_648;
/**
look for a date from these tags (in order)
*/
/** look for a date from these tags (in order) */
const EXIF_DATE_TAGS: Array<keyof ImmichTags> = [
'SubSecDateTimeOriginal',
'SubSecCreateDate',

View file

@ -105,33 +105,19 @@ export interface AudioStreamInfo {
bitrate: number;
}
/**
Packet-derived video data needed for accurate HLS playlists.
*/
/** Packet-derived video data needed for accurate HLS playlists. */
export interface VideoPacketInfo {
/**
Sum of source packet duration across all packets (includes discard).
*/
/** Sum of source packet duration across all packets (includes discard). */
totalDuration: number;
/**
Post-discard packet count.
*/
/** Post-discard packet count. */
packetCount: number;
/**
Output CFR frame count at `packetCount / format.duration`.
*/
/** Output CFR frame count at `packetCount / format.duration`. */
outputFrames: number;
/**
All keyframe PTS in source ticks, including pre-roll discard keyframes.
*/
/** All keyframe PTS in source ticks, including pre-roll discard keyframes. */
keyframePts: number[];
/**
Cumulative packet duration through each keyframe, inclusive.
*/
/** Cumulative packet duration through each keyframe, inclusive. */
keyframeAccDuration: number[];
/**
Each keyframe's own packet duration (needed for VFR).
*/
/** Each keyframe's own packet duration (needed for VFR). */
keyframeOwnDuration: number[];
}
@ -224,9 +210,7 @@ export interface IBaseJob {
}
export interface IDelayedJob extends IBaseJob {
/**
The minimum time to wait to execute this job, in milliseconds.
*/
/** The minimum time to wait to execute this job, in milliseconds. */
delay?: number;
}
@ -468,9 +452,7 @@ export interface ExtensionVersion {
export interface ImmichFile extends Express.Multer.File {
uuid: string;
/**
sha1 hash of file
*/
/** sha1 hash of file */
checksum: Buffer;
}
@ -540,9 +522,7 @@ export type SystemFlags = { mountChecks: Record<StorageFolder, boolean> };
export type MaintenanceModeState =
{ isMaintenanceMode: true; secret: string; action?: SetMaintenanceModeDto } | { isMaintenanceMode: false };
export type MemoriesState = {
/**
memories have already been created through this date
*/
/** memories have already been created through this date */
lastOnThisDayDate: string;
};
export type MediaLocation = { location: string };

View file

@ -113,9 +113,7 @@ export const removeAssets = async (
export type PartnerIdOptions = {
userId: string;
repository: PartnerRepository;
/**
only include partners with `inTimeline: true`
*/
/** only include partners with `inTimeline: true` */
timelineEnabled?: boolean;
};
export const getMyPartnerIds = async ({ userId, repository, timelineEnabled }: PartnerIdOptions) => {

View file

@ -391,9 +391,7 @@ export function withEdits(eb: ExpressionBuilder<DB, 'asset'>): AliasedEditAction
}
const joinDeduplicationPlugin = new DeduplicateJoinsPlugin();
/**
TODO: This should only be used for search-related queries, not as a general purpose query builder
*/
/** TODO: This should only be used for search-related queries, not as a general purpose query builder */
export function searchAssetBuilderLegacy(kysely: Kysely<DB>, options: AssetSearchBuilderOptions) {
options.withDeleted ||= !!(options.trashedAfter || options.trashedBefore || options.isOffline);

View file

@ -164,9 +164,7 @@ export const mimeTypes = {
transparentCapableExtensions.has(getFilenameExtension(filename).toLowerCase()),
isRaw: (filename: string) => isType(filename, raw),
lookup,
/**
return an extension (including a leading `.`) for a mime-type
*/
/** return an extension (including a leading `.`) for a mime-type */
toExtension,
assetType: (filename: string) => {
const contentType = lookup(filename);

View file

@ -12,9 +12,7 @@ export const triggerMap: Record<WorkflowTrigger, WorkflowType[]> = {
export const getWorkflowTriggers = () =>
Object.entries(triggerMap).map(([trigger, types]) => ({ trigger: trigger as WorkflowTrigger, types }));
/**
some types extend other types and have implied compatibility
*/
/** some types extend other types and have implied compatibility */
const inferredMap: Record<WorkflowType, WorkflowType[]> = {
[WorkflowType.AssetV1]: [],
// [WorkflowType.AssetPersonV1]: [WorkflowType.AssetV1],

View file

@ -48,9 +48,7 @@ const probeStubDefault: VideoInfo = {
audioStreams: probeStubDefaultAudioStream,
};
/**
Fixtures in the shape `mediaRepository.probe()` returns (arrays of streams, raw ffprobe format).
*/
/** Fixtures in the shape `mediaRepository.probe()` returns (arrays of streams, raw ffprobe format). */
export const videoInfoStub = {
noVideoStreams: Object.freeze<VideoInfo>({ ...probeStubDefault, videoStreams: [] }),
noAudioStreams: Object.freeze<VideoInfo>({ ...probeStubDefault, audioStreams: [] }),

View file

@ -146,6 +146,7 @@ export default typescriptEslint.config(
'unicorn/prefer-minimal-ternary': 'off',
'unicorn/no-empty-file': 'off',
'unicorn/prefer-simple-condition-first': 'off',
'unicorn/single-line-block-comment-style': ['error', 'single-line'],
// prefer the typescript-eslint type-aware version
'unicorn/require-array-sort-compare': 'off',
'@typescript-eslint/require-array-sort-compare': 'error',

View file

@ -1,6 +1,4 @@
/**
Focus the given element when it is mounted.
*/
/** Focus the given element when it is mounted. */
export const initInput = (element: HTMLInputElement) => {
element.focus();
};

View file

@ -55,9 +55,7 @@
}
const groupOptions: AlbumGroupOption = {
/**
No grouping
*/
/** No grouping */
[AlbumGroupBy.None]: (order, albums): AlbumGroup[] => {
return [
{
@ -68,9 +66,7 @@
];
},
/**
Group by year
*/
/** Group by year */
[AlbumGroupBy.Year]: (order, albums): AlbumGroup[] => {
const unknownYear = $t('unknown_year');
const useStartDate = userSettings.sortBy === AlbumSortBy.OldestPhoto;
@ -96,9 +92,7 @@
}));
},
/**
Group by owner
*/
/** Group by owner */
[AlbumGroupBy.Owner]: (order, albums): AlbumGroup[] => {
const currentUserId = authManager.user.id;
const groupedByOwnerIds = groupBy(albums, (album) => album.albumUsers[0].user.id);

View file

@ -108,9 +108,7 @@
updateOcrBoxes(ocrManager.showOverlay, ocrManager.data);
});
/**
Use updateOnly=true on zoom, pan, or resize.
*/
/** Use updateOnly=true on zoom, pan, or resize. */
const updateOcrBoxes = (showOverlay: boolean, ocrData: OcrBoundingBox[], updateOnly = false) => {
if (!viewer || !viewer.state.textureData || !viewer.getPlugin(MarkersPlugin)) {
return;

View file

@ -11,54 +11,30 @@
import { fade, fly } from 'svelte/transition';
interface Props {
/**
Offset from the top of the timeline (e.g., for headers)
*/
/** Offset from the top of the timeline (e.g., for headers) */
timelineTopOffset?: number;
/**
Offset from the bottom of the timeline (e.g., for footers)
*/
/** Offset from the bottom of the timeline (e.g., for footers) */
timelineBottomOffset?: number;
/**
Total height of the scrubber component
*/
/** Total height of the scrubber component */
height?: number;
/**
Timeline manager instance that controls the timeline state
*/
/** Timeline manager instance that controls the timeline state */
timelineManager: TimelineManager;
/**
Overall scroll percentage through the entire timeline (0-1), used when no specific month is targeted
*/
/** Overall scroll percentage through the entire timeline (0-1), used when no specific month is targeted */
timelineScrollPercent?: number;
/**
The percentage of scroll through the month that is currently intersecting the top boundary of the viewport
*/
/** The percentage of scroll through the month that is currently intersecting the top boundary of the viewport */
viewportTopMonthScrollPercent?: number;
/**
The year/month of the timeline month at the top of the viewport
*/
/** The year/month of the timeline month at the top of the viewport */
viewportTopMonth?: ViewportTopMonth;
/**
Width of the scrubber component in pixels (bindable for parent component margin adjustments)
*/
/** Width of the scrubber component in pixels (bindable for parent component margin adjustments) */
scrubberWidth?: number;
/**
Callback fired when user interacts with the scrubber to navigate
*/
/** Callback fired when user interacts with the scrubber to navigate */
onScrub?: ScrubberListener;
/**
Callback fired when keyboard events occur on the scrubber
*/
/** Callback fired when keyboard events occur on the scrubber */
onScrubKeyDown?: (event: KeyboardEvent, element: HTMLElement) => void;
/**
Callback fired when scrubbing starts
*/
/** Callback fired when scrubbing starts */
startScrub?: ScrubberListener;
/**
Callback fired when scrubbing stops
*/
/** Callback fired when scrubbing stops */
stopScrub?: ScrubberListener;
}

View file

@ -223,46 +223,34 @@ export const stringToSortOrder = (order: string) => {
};
const sortOptions: AlbumSortOption = {
/**
Sort by album title
*/
/** Sort by album title */
[AlbumSortBy.Title]: (order, albums) => {
const sortSign = order === SortOrder.Desc ? -1 : 1;
return albums.slice().sort((a, b) => a.albumName.localeCompare(b.albumName, get(locale)) * sortSign);
},
/**
Sort by asset count
*/
/** Sort by asset count */
[AlbumSortBy.ItemCount]: (order, albums) => {
return orderBy(albums, 'assetCount', [order]);
},
/**
Sort by last modified
*/
/** Sort by last modified */
[AlbumSortBy.DateModified]: (order, albums) => {
return orderBy(albums, [({ updatedAt }) => new Date(updatedAt)], [order]);
},
/**
Sort by creation date
*/
/** Sort by creation date */
[AlbumSortBy.DateCreated]: (order, albums) => {
return orderBy(albums, [({ createdAt }) => new Date(createdAt)], [order]);
},
/**
Sort by the most recent photo date
*/
/** Sort by the most recent photo date */
[AlbumSortBy.MostRecentPhoto]: (order, albums) => {
albums = orderBy(albums, [({ endDate }) => (endDate ? new Date(endDate) : '')], [order]);
return albums.sort(sortUnknownYearAlbums);
},
/**
Sort by the oldest photo date
*/
/** Sort by the oldest photo date */
[AlbumSortBy.OldestPhoto]: (order, albums) => {
albums = orderBy(albums, [({ startDate }) => (startDate ? new Date(startDate) : '')], [order]);
return albums.sort(sortUnknownYearAlbums);

View file

@ -6,13 +6,9 @@ import { handleError } from '$lib/utils/handle-error';
* and allowing operations to check if they're still valid.
*/
export class InvocationTracker {
/**
Counter for the number of invocations that have been started
*/
/** Counter for the number of invocations that have been started */
invocationsStarted = 0;
/**
Counter for the number of invocations that have been completed
*/
/** Counter for the number of invocations that have been completed */
invocationsEnded = 0;
constructor() {}

View file

@ -92,9 +92,7 @@ interface AssetGridRoute extends Route {
type ImmichRoute = AssetRoute | AssetGridRoute;
type NavOptions = {
/*
navigate even if url is the same
*/
/* navigate even if url is the same */
forceNavigate?: boolean | undefined;
replaceState?: boolean | undefined;
noScroll?: boolean | undefined;

View file

@ -1,9 +1,7 @@
import type { ParamMatcher } from '@sveltejs/kit';
import { UUID_REGEX } from '$lib/constants';
/*
Returns true if the given param matches UUID format
*/
/* Returns true if the given param matches UUID format */
export const match: ParamMatcher = (param: string) => {
return UUID_REGEX.test(param);
};

View file

@ -33,9 +33,7 @@
}
const groupOptions: PlacesGroupOption = {
/**
No grouping
*/
/** No grouping */
[PlacesGroupBy.None]: (places): PlacesGroup[] => {
return [
{
@ -46,9 +44,7 @@
];
},
/**
Group by year
*/
/** Group by year */
[PlacesGroupBy.Country]: (places): PlacesGroup[] => {
const unknownCountry = $t('unknown_country');