Merge remote-tracking branch 'origin/main' into chore/pnpm_alt

This commit is contained in:
Min Idzelis
2025-06-28 03:50:28 +00:00
332 changed files with 53395 additions and 3611 deletions
+10263
View File
File diff suppressed because it is too large Load Diff
@@ -30,7 +30,12 @@
import { deleteAssets, updateStackedAssetInTimeline, updateUnstackedAssetInTimeline } from '$lib/utils/actions';
import { archiveAssets, cancelMultiselect, selectAllAssets, stackAssets } from '$lib/utils/asset-utils';
import { navigate } from '$lib/utils/navigation';
import { toTimelineAsset, type ScrubberListener, type TimelinePlainYearMonth } from '$lib/utils/timeline-util';
import {
getTimes,
toTimelineAsset,
type ScrubberListener,
type TimelinePlainYearMonth,
} from '$lib/utils/timeline-util';
import { AssetVisibility, getAssetInfo, type AlbumResponseDto, type PersonResponseDto } from '@immich/sdk';
import { DateTime } from 'luxon';
import { onMount, type Snippet } from 'svelte';
@@ -768,6 +773,13 @@
void selectAssetCandidates(lastAssetMouseEvent);
}
});
$effect(() => {
if ($showAssetViewer) {
const { localDateTime } = getTimes($viewingAsset.fileCreatedAt, DateTime.local().offset / 60);
void timelineManager.loadMonthGroup({ year: localDateTime.year, month: localDateTime.month });
}
});
</script>
<svelte:document onkeydown={onKeyDown} onkeyup={onKeyUp} onselectstart={onSelectStart} use:shortcuts={shortcutList} />
@@ -0,0 +1,24 @@
import { eventManager } from '$lib/managers/event-manager.svelte';
import { getSupportedMediaTypes, type ServerMediaTypesResponseDto } from '@immich/sdk';
class UploadManager {
mediaTypes = $state<ServerMediaTypesResponseDto>({ image: [], sidecar: [], video: [] });
constructor() {
eventManager.on('app.init', () => void this.#loadExtensions());
}
async #loadExtensions() {
try {
this.mediaTypes = await getSupportedMediaTypes();
} catch {
console.error('Failed to load supported media types');
}
}
getExtensions() {
return [...this.mediaTypes.image, ...this.mediaTypes.video];
}
}
export const uploadManager = new UploadManager();
@@ -8,7 +8,7 @@
import { handleError } from '$lib/utils/handle-error';
import { mergePerson, type PersonResponseDto } from '@immich/sdk';
import { Button, HStack, IconButton, Modal, ModalBody, ModalFooter } from '@immich/ui';
import { mdiArrowLeft, mdiMerge } from '@mdi/js';
import { mdiArrowLeft, mdiCallMerge, mdiSwapHorizontal } from '@mdi/js';
import { onMount, tick } from 'svelte';
import { t } from 'svelte-i18n';
import ImageThumbnail from '../components/assets/thumbnail/image-thumbnail.svelte';
@@ -62,7 +62,7 @@
<Modal title="{$t('merge_people')} - {title}" {onClose}>
<ModalBody>
<div class="flex items-center justify-center py-4 md:h-36 md:py-4">
<div class="flex items-center justify-center gap-2 py-4 md:h-36">
{#if !choosePersonToMerge}
<div class="flex h-20 w-20 items-center px-1 md:h-24 md:w-24 md:px-2">
<ImageThumbnail
@@ -73,15 +73,24 @@
widthStyle="100%"
/>
</div>
<div class="mx-0.5 flex md:mx-2">
<IconButton
shape="round"
variant="ghost"
color="secondary"
aria-label={$t('swap_merge_direction')}
icon={mdiMerge}
onclick={() => ([personToMerge, personToBeMergedInto] = [personToBeMergedInto, personToMerge])}
/>
<div class="grid grid-rows-3">
<div></div>
<div class="flex flex-col h-full items-center justify-center">
<div class="flex h-full items-center justify-center">
<Icon path={mdiCallMerge} size={48} class="rotate-90 dark:text-white" />
</div>
</div>
<div>
<IconButton
shape="round"
color="secondary"
variant="ghost"
aria-label={$t('swap_merge_direction')}
icon={mdiSwapHorizontal}
onclick={() => ([personToMerge, personToBeMergedInto] = [personToBeMergedInto, personToMerge])}
/>
</div>
</div>
<button
+3 -13
View File
@@ -1,4 +1,5 @@
import { authManager } from '$lib/managers/auth-manager.svelte';
import { uploadManager } from '$lib/managers/upload-manager.svelte';
import { UploadState } from '$lib/models/upload-asset';
import { uploadAssetsStore } from '$lib/stores/upload';
import { uploadRequest } from '$lib/utils';
@@ -11,7 +12,6 @@ import {
checkBulkUpload,
getAssetOriginalPath,
getBaseUrl,
getSupportedMediaTypes,
type AssetMediaResponseDto,
} from '@immich/sdk';
import { tick } from 'svelte';
@@ -40,25 +40,15 @@ export const addDummyItems = () => {
// addDummyItems();
let _extensions: string[];
export const uploadExecutionQueue = new ExecutorQueue({ concurrency: 2 });
const getExtensions = async () => {
if (!_extensions) {
const { image, video } = await getSupportedMediaTypes();
_extensions = [...image, ...video];
}
return _extensions;
};
type FileUploadParam = { multiple?: boolean } & (
| { albumId?: string; assetId?: never }
| { albumId?: never; assetId?: string }
);
export const openFileUploadDialog = async (options: FileUploadParam = {}) => {
const { albumId, multiple = true, assetId } = options;
const extensions = await getExtensions();
const extensions = uploadManager.getExtensions();
return new Promise<(string | undefined)[]>((resolve, reject) => {
try {
@@ -99,7 +89,7 @@ export const fileUploadHandler = async ({
replaceAssetId,
isLockedAssets = false,
}: FileUploadHandlerParams): Promise<string[]> => {
const extensions = await getExtensions();
const extensions = uploadManager.getExtensions();
const promises = [];
for (const file of files) {
const name = file.name.toLowerCase();