mirror of
https://github.com/immich-app/immich
synced 2025-11-07 17:27:20 +00:00
refactor(web) open api client (#7103)
* refactor: person api * refactor: shared link and others
This commit is contained in:
parent
5fc1d43012
commit
d8631a00bb
81 changed files with 638 additions and 656 deletions
|
|
@ -1,12 +1,10 @@
|
|||
<script lang="ts">
|
||||
import { locale } from '$lib/stores/preferences.store';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import { JobCommand, type JobCommandDto, type JobCountsDto, type QueueStatusDto } from '@api';
|
||||
import Badge from '$lib/components/elements/badge.svelte';
|
||||
import JobTileButton from './job-tile-button.svelte';
|
||||
import JobTileStatus from './job-tile-status.svelte';
|
||||
import Button from '$lib/components/elements/buttons/button.svelte';
|
||||
import Icon from '$lib/components/elements/icon.svelte';
|
||||
import { locale } from '$lib/stores/preferences.store';
|
||||
import { type JobCommandDto, type JobCountsDto, type QueueStatusDto } from '@immich/sdk';
|
||||
import { JobCommand } from '@immich/sdk/axios';
|
||||
import {
|
||||
mdiAlertCircle,
|
||||
mdiAllInclusive,
|
||||
|
|
@ -16,6 +14,9 @@
|
|||
mdiPlay,
|
||||
mdiSelectionSearch,
|
||||
} from '@mdi/js';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import JobTileButton from './job-tile-button.svelte';
|
||||
import JobTileStatus from './job-tile-status.svelte';
|
||||
|
||||
export let title: string;
|
||||
export let subtitle: string | undefined;
|
||||
|
|
|
|||
|
|
@ -4,9 +4,10 @@
|
|||
NotificationType,
|
||||
} from '$lib/components/shared-components/notification/notification';
|
||||
import { featureFlags } from '$lib/stores/server-config.store';
|
||||
import { getJobName } from '$lib/utils';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { type AllJobStatusResponseDto, api, JobCommand, type JobCommandDto, JobName } from '@api';
|
||||
import type { ComponentType } from 'svelte';
|
||||
import { sendJobCommand, type AllJobStatusResponseDto, type JobCommandDto } from '@immich/sdk';
|
||||
import { JobCommand, JobName } from '@immich/sdk/axios';
|
||||
import {
|
||||
mdiFaceRecognition,
|
||||
mdiFileJpgBox,
|
||||
|
|
@ -18,10 +19,10 @@
|
|||
mdiTagFaces,
|
||||
mdiVideo,
|
||||
} from '@mdi/js';
|
||||
import type { ComponentType } from 'svelte';
|
||||
import ConfirmDialogue from '../../shared-components/confirm-dialogue.svelte';
|
||||
import JobTile from './job-tile.svelte';
|
||||
import StorageMigrationDescription from './storage-migration-description.svelte';
|
||||
import { sendJobCommand } from '@immich/sdk';
|
||||
|
||||
export let jobs: AllJobStatusResponseDto;
|
||||
|
||||
|
|
@ -59,23 +60,23 @@
|
|||
$: jobDetails = <Partial<Record<JobName, JobDetails>>>{
|
||||
[JobName.ThumbnailGeneration]: {
|
||||
icon: mdiFileJpgBox,
|
||||
title: api.getJobName(JobName.ThumbnailGeneration),
|
||||
title: getJobName(JobName.ThumbnailGeneration),
|
||||
subtitle: 'Generate large, small and blurred thumbnails for each asset, as well as thumbnails for each person',
|
||||
},
|
||||
[JobName.MetadataExtraction]: {
|
||||
icon: mdiTable,
|
||||
title: api.getJobName(JobName.MetadataExtraction),
|
||||
title: getJobName(JobName.MetadataExtraction),
|
||||
subtitle: 'Extract metadata information from each asset, such as GPS and resolution',
|
||||
},
|
||||
[JobName.Library]: {
|
||||
icon: mdiLibraryShelves,
|
||||
title: api.getJobName(JobName.Library),
|
||||
title: getJobName(JobName.Library),
|
||||
subtitle: 'Perform library tasks',
|
||||
allText: 'ALL',
|
||||
missingText: 'REFRESH',
|
||||
},
|
||||
[JobName.Sidecar]: {
|
||||
title: api.getJobName(JobName.Sidecar),
|
||||
title: getJobName(JobName.Sidecar),
|
||||
icon: mdiFileXmlBox,
|
||||
subtitle: 'Discover or synchronize sidecar metadata from the filesystem',
|
||||
allText: 'SYNC',
|
||||
|
|
@ -84,13 +85,13 @@
|
|||
},
|
||||
[JobName.SmartSearch]: {
|
||||
icon: mdiImageSearch,
|
||||
title: api.getJobName(JobName.SmartSearch),
|
||||
title: getJobName(JobName.SmartSearch),
|
||||
subtitle: 'Run machine learning on assets to support smart search',
|
||||
disabled: !$featureFlags.smartSearch,
|
||||
},
|
||||
[JobName.FaceDetection]: {
|
||||
icon: mdiFaceRecognition,
|
||||
title: api.getJobName(JobName.FaceDetection),
|
||||
title: getJobName(JobName.FaceDetection),
|
||||
subtitle:
|
||||
'Detect the faces in assets using machine learning. For videos, only the thumbnail is considered. "All" (re-)processes all assets. "Missing" queues assets that haven\'t been processed yet. Detected faces will be queued for Facial Recognition after Face Detection is complete, grouping them into existing or new people.',
|
||||
handleCommand: handleConfirmCommand,
|
||||
|
|
@ -98,7 +99,7 @@
|
|||
},
|
||||
[JobName.FacialRecognition]: {
|
||||
icon: mdiTagFaces,
|
||||
title: api.getJobName(JobName.FacialRecognition),
|
||||
title: getJobName(JobName.FacialRecognition),
|
||||
subtitle:
|
||||
'Group detected faces into people. This step runs after Face Detection is complete. "All" (re-)clusters all faces. "Missing" queues faces that don\'t have a person assigned.',
|
||||
handleCommand: handleConfirmCommand,
|
||||
|
|
@ -106,18 +107,18 @@
|
|||
},
|
||||
[JobName.VideoConversion]: {
|
||||
icon: mdiVideo,
|
||||
title: api.getJobName(JobName.VideoConversion),
|
||||
title: getJobName(JobName.VideoConversion),
|
||||
subtitle: 'Transcode videos for wider compatibility with browsers and devices',
|
||||
},
|
||||
[JobName.StorageTemplateMigration]: {
|
||||
icon: mdiFolderMove,
|
||||
title: api.getJobName(JobName.StorageTemplateMigration),
|
||||
title: getJobName(JobName.StorageTemplateMigration),
|
||||
allowForceCommand: false,
|
||||
component: StorageMigrationDescription,
|
||||
},
|
||||
[JobName.Migration]: {
|
||||
icon: mdiFolderMove,
|
||||
title: api.getJobName(JobName.Migration),
|
||||
title: getJobName(JobName.Migration),
|
||||
subtitle: 'Migrate thumbnails for assets and faces to the latest folder structure',
|
||||
allowForceCommand: false,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
<script lang="ts">
|
||||
import { locale } from '$lib/stores/preferences.store';
|
||||
import type { ServerStatsResponseDto } from '@api';
|
||||
import { asByteUnitString, getBytesWithUnit } from '$lib/utils/byte-units';
|
||||
import StatsCard from './stats-card.svelte';
|
||||
import { mdiCameraIris, mdiChartPie, mdiPlayCircle } from '@mdi/js';
|
||||
import Icon from '$lib/components/elements/icon.svelte';
|
||||
import { locale } from '$lib/stores/preferences.store';
|
||||
import { asByteUnitString, getBytesWithUnit } from '$lib/utils/byte-units';
|
||||
import type { ServerStatsResponseDto } from '@immich/sdk';
|
||||
import { mdiCameraIris, mdiChartPie, mdiPlayCircle } from '@mdi/js';
|
||||
import StatsCard from './stats-card.svelte';
|
||||
|
||||
export let stats: ServerStatsResponseDto = {
|
||||
photos: 0,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import type { ResetOptions } from '$lib/utils/dipatch';
|
||||
import type { SystemConfigDto } from '@api';
|
||||
import type { SystemConfigDto } from '@immich/sdk';
|
||||
|
||||
export type SettingsEventType = {
|
||||
reset: ResetOptions & { configKeys: Array<keyof SystemConfigDto> };
|
||||
|
|
|
|||
|
|
@ -1,25 +1,18 @@
|
|||
<script lang="ts">
|
||||
import {
|
||||
AudioCodec,
|
||||
CQMode,
|
||||
type SystemConfigDto,
|
||||
ToneMapping,
|
||||
TranscodeHWAccel,
|
||||
TranscodePolicy,
|
||||
VideoCodec,
|
||||
} from '@api';
|
||||
import Icon from '$lib/components/elements/icon.svelte';
|
||||
import { type SystemConfigDto } from '@immich/sdk';
|
||||
import { AudioCodec, CQMode, ToneMapping, TranscodeHWAccel, TranscodePolicy, VideoCodec } from '@immich/sdk/axios';
|
||||
import { mdiHelpCircleOutline } from '@mdi/js';
|
||||
import { isEqual, sortBy } from 'lodash-es';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import { fade } from 'svelte/transition';
|
||||
import type { SettingsEventType } from '../admin-settings';
|
||||
import SettingAccordion from '../setting-accordion.svelte';
|
||||
import SettingButtonsRow from '../setting-buttons-row.svelte';
|
||||
import SettingCheckboxes from '../setting-checkboxes.svelte';
|
||||
import SettingInputField, { SettingInputFieldType } from '../setting-input-field.svelte';
|
||||
import SettingSelect from '../setting-select.svelte';
|
||||
import SettingSwitch from '../setting-switch.svelte';
|
||||
import SettingCheckboxes from '../setting-checkboxes.svelte';
|
||||
import { isEqual, sortBy } from 'lodash-es';
|
||||
import { fade } from 'svelte/transition';
|
||||
import SettingAccordion from '../setting-accordion.svelte';
|
||||
import { mdiHelpCircleOutline } from '@mdi/js';
|
||||
import Icon from '$lib/components/elements/icon.svelte';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import type { SettingsEventType } from '../admin-settings';
|
||||
|
||||
export let savedConfig: SystemConfigDto;
|
||||
export let defaultConfig: SystemConfigDto;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
<script lang="ts">
|
||||
import { api, JobName, type SystemConfigDto, type SystemConfigJobDto } from '@api';
|
||||
import { getJobName } from '$lib/utils';
|
||||
import { type SystemConfigDto, type SystemConfigJobDto } from '@immich/sdk';
|
||||
import { JobName } from '@immich/sdk/axios';
|
||||
import { isEqual } from 'lodash-es';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import { fade } from 'svelte/transition';
|
||||
|
|
@ -41,7 +43,7 @@
|
|||
<SettingInputField
|
||||
inputType={SettingInputFieldType.NUMBER}
|
||||
{disabled}
|
||||
label="{api.getJobName(jobName)} Concurrency"
|
||||
label="{getJobName(jobName)} Concurrency"
|
||||
desc=""
|
||||
bind:value={config.job[jobName].concurrency}
|
||||
required={true}
|
||||
|
|
@ -50,7 +52,7 @@
|
|||
{:else}
|
||||
<SettingInputField
|
||||
inputType={SettingInputFieldType.NUMBER}
|
||||
label="{api.getJobName(jobName)} Concurrency"
|
||||
label="{getJobName(jobName)} Concurrency"
|
||||
desc=""
|
||||
value="1"
|
||||
disabled={true}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts">
|
||||
import type { SystemConfigDto } from '@api';
|
||||
import type { SystemConfigDto } from '@immich/sdk';
|
||||
import { isEqual } from 'lodash-es';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import { fade } from 'svelte/transition';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<script lang="ts">
|
||||
import { LogLevel, type SystemConfigDto } from '@api';
|
||||
import { type SystemConfigDto } from '@immich/sdk';
|
||||
import { LogLevel } from '@immich/sdk/axios';
|
||||
import { isEqual } from 'lodash-es';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import { fade } from 'svelte/transition';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts">
|
||||
import type { SystemConfigDto } from '@api';
|
||||
import type { SystemConfigDto } from '@immich/sdk';
|
||||
import { isEqual } from 'lodash-es';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import { fade } from 'svelte/transition';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts">
|
||||
import type { SystemConfigDto } from '@api';
|
||||
import type { SystemConfigDto } from '@immich/sdk';
|
||||
import { isEqual } from 'lodash-es';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import { fade } from 'svelte/transition';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts">
|
||||
import type { SystemConfigDto } from '@api';
|
||||
import type { SystemConfigDto } from '@immich/sdk';
|
||||
import { isEqual } from 'lodash-es';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import { fade } from 'svelte/transition';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts">
|
||||
import type { SystemConfigDto } from '@api';
|
||||
import type { SystemConfigDto } from '@immich/sdk';
|
||||
import { isEqual } from 'lodash-es';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import { fade } from 'svelte/transition';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts">
|
||||
import type { SystemConfigDto } from '@api';
|
||||
import type { SystemConfigDto } from '@immich/sdk';
|
||||
import { isEqual } from 'lodash-es';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import { fade } from 'svelte/transition';
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
<script lang="ts">
|
||||
import SettingButtonsRow from '$lib/components/admin-page/settings/setting-buttons-row.svelte';
|
||||
import type { SystemConfigDto } from '@api';
|
||||
import type { SystemConfigDto } from '@immich/sdk';
|
||||
import { isEqual } from 'lodash-es';
|
||||
import { fade } from 'svelte/transition';
|
||||
import SettingInputField, { SettingInputFieldType } from '../setting-input-field.svelte';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import { fade } from 'svelte/transition';
|
||||
import type { SettingsEventType } from '../admin-settings';
|
||||
import SettingInputField, { SettingInputFieldType } from '../setting-input-field.svelte';
|
||||
|
||||
export let savedConfig: SystemConfigDto;
|
||||
export let defaultConfig: SystemConfigDto;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts">
|
||||
import type { SystemConfigTemplateStorageOptionDto } from '@api';
|
||||
import type { SystemConfigTemplateStorageOptionDto } from '@immich/sdk';
|
||||
import * as luxon from 'luxon';
|
||||
|
||||
export let options: SystemConfigTemplateStorageOptionDto;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts">
|
||||
import type { SystemConfigDto } from '@api';
|
||||
import type { SystemConfigDto } from '@immich/sdk';
|
||||
import { isEqual } from 'lodash-es';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import { fade } from 'svelte/transition';
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
<script lang="ts">
|
||||
import SettingButtonsRow from '$lib/components/admin-page/settings/setting-buttons-row.svelte';
|
||||
import SettingSelect from '$lib/components/admin-page/settings/setting-select.svelte';
|
||||
import { Colorspace, type SystemConfigDto } from '@api';
|
||||
import { type SystemConfigDto } from '@immich/sdk';
|
||||
import { Colorspace } from '@immich/sdk/axios';
|
||||
import { isEqual } from 'lodash-es';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import { fade } from 'svelte/transition';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts">
|
||||
import type { SystemConfigDto } from '@api';
|
||||
import type { SystemConfigDto } from '@immich/sdk';
|
||||
import { isEqual } from 'lodash-es';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import { fade } from 'svelte/transition';
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
import Icon from '$lib/components/elements/icon.svelte';
|
||||
import { locale } from '$lib/stores/preferences.store';
|
||||
import { user } from '$lib/stores/user.store';
|
||||
import { getAssetThumbnailUrl } from '$lib/utils';
|
||||
import { ThumbnailFormat, api, type AlbumResponseDto } from '@api';
|
||||
import { getUserById } from '@immich/sdk';
|
||||
import { mdiDotsVertical } from '@mdi/js';
|
||||
|
|
@ -19,7 +20,7 @@
|
|||
let showVerticalDots = false;
|
||||
|
||||
$: imageData = album.albumThumbnailAssetId
|
||||
? api.getAssetThumbnailUrl(album.albumThumbnailAssetId, ThumbnailFormat.Webp)
|
||||
? getAssetThumbnailUrl(album.albumThumbnailAssetId, ThumbnailFormat.Webp)
|
||||
: noThumbnailUrl;
|
||||
|
||||
const dispatchClick = createEventDispatcher<OnClick>();
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type { AlbumResponseDto } from '@api';
|
||||
import type { AlbumResponseDto } from '@immich/sdk';
|
||||
|
||||
export type OnShowContextMenu = {
|
||||
showalbumcontextmenu: OnShowContextMenuDetail;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts">
|
||||
import { type AlbumResponseDto, type UserResponseDto } from '@api';
|
||||
import { type AlbumResponseDto, type UserResponseDto } from '@immich/sdk';
|
||||
import { getMyUserInfo, removeUserFromAlbum } from '@immich/sdk';
|
||||
import { mdiDotsVertical } from '@mdi/js';
|
||||
import { createEventDispatcher, onMount } from 'svelte';
|
||||
|
|
|
|||
|
|
@ -2,8 +2,13 @@
|
|||
import { goto } from '$app/navigation';
|
||||
import Icon from '$lib/components/elements/icon.svelte';
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { api, type AlbumResponseDto, type SharedLinkResponseDto, type UserResponseDto } from '@api';
|
||||
import { getAllUsers } from '@immich/sdk';
|
||||
import {
|
||||
getAllSharedLinks,
|
||||
getAllUsers,
|
||||
type AlbumResponseDto,
|
||||
type SharedLinkResponseDto,
|
||||
type UserResponseDto,
|
||||
} from '@immich/sdk';
|
||||
import { mdiCheck, mdiLink, mdiShareCircle } from '@mdi/js';
|
||||
import { createEventDispatcher, onMount } from 'svelte';
|
||||
import Button from '../elements/buttons/button.svelte';
|
||||
|
|
@ -35,8 +40,7 @@
|
|||
});
|
||||
|
||||
const getSharedLinks = async () => {
|
||||
const { data } = await api.sharedLinkApi.getAllSharedLinks();
|
||||
|
||||
const data = await getAllSharedLinks();
|
||||
sharedLinks = data.filter((link) => link.album?.id === album.id);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,20 +1,21 @@
|
|||
<script lang="ts">
|
||||
import Icon from '$lib/components/elements/icon.svelte';
|
||||
import { timeBeforeShowLoadingSpinner } from '$lib/constants';
|
||||
import { getAssetThumbnailUrl } from '$lib/utils';
|
||||
import { getAssetType } from '$lib/utils/asset-utils';
|
||||
import { autoGrowHeight } from '$lib/utils/autogrow';
|
||||
import { clickOutside } from '$lib/utils/click-outside';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { isTenMinutesApart } from '$lib/utils/timesince';
|
||||
import {
|
||||
AssetTypeEnum,
|
||||
ReactionType,
|
||||
ThumbnailFormat,
|
||||
api,
|
||||
createActivity,
|
||||
deleteActivity,
|
||||
getActivities,
|
||||
type ActivityResponseDto,
|
||||
type AssetTypeEnum,
|
||||
type UserResponseDto,
|
||||
} from '@api';
|
||||
import { createActivity, deleteActivity, getActivities } from '@immich/sdk';
|
||||
} from '@immich/sdk';
|
||||
import { ReactionType, ThumbnailFormat } from '@immich/sdk/axios';
|
||||
import { mdiClose, mdiDotsVertical, mdiHeart, mdiSend } from '@mdi/js';
|
||||
import * as luxon from 'luxon';
|
||||
import { createEventDispatcher, onMount } from 'svelte';
|
||||
|
|
@ -191,7 +192,7 @@
|
|||
<div class="aspect-square w-[75px] h-[75px]">
|
||||
<img
|
||||
class="rounded-lg w-[75px] h-[75px] object-cover"
|
||||
src={api.getAssetThumbnailUrl(reaction.assetId, ThumbnailFormat.Webp)}
|
||||
src={getAssetThumbnailUrl(reaction.assetId, ThumbnailFormat.Webp)}
|
||||
alt="comment-thumbnail"
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -237,7 +238,7 @@
|
|||
<div class="aspect-square w-[75px] h-[75px]">
|
||||
<img
|
||||
class="rounded-lg w-[75px] h-[75px] object-cover"
|
||||
src={api.getAssetThumbnailUrl(reaction.assetId, ThumbnailFormat.Webp)}
|
||||
src={getAssetThumbnailUrl(reaction.assetId, ThumbnailFormat.Webp)}
|
||||
alt="like-thumbnail"
|
||||
/>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<script lang="ts">
|
||||
import { type AlbumResponseDto, ThumbnailFormat, api } from '@api';
|
||||
import { getAssetThumbnailUrl } from '$lib/utils';
|
||||
import { ThumbnailFormat, type AlbumResponseDto } from '@api';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
|
||||
const dispatch = createEventDispatcher<{
|
||||
|
|
@ -32,7 +33,7 @@
|
|||
<div class="h-12 w-12 shrink-0 rounded-xl bg-slate-300">
|
||||
{#if album.albumThumbnailAssetId}
|
||||
<img
|
||||
src={api.getAssetThumbnailUrl(album.albumThumbnailAssetId, ThumbnailFormat.Webp)}
|
||||
src={getAssetThumbnailUrl(album.albumThumbnailAssetId, ThumbnailFormat.Webp)}
|
||||
alt={album.albumName}
|
||||
class="z-0 h-full w-full rounded-xl object-cover transition-all duration-300 hover:shadow-lg"
|
||||
data-testid="album-image"
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
<script lang="ts">
|
||||
import CircleIconButton from '$lib/components/elements/buttons/circle-icon-button.svelte';
|
||||
import { user } from '$lib/stores/user.store';
|
||||
import { photoZoomState } from '$lib/stores/zoom-image.store';
|
||||
import { getAssetJobName } from '$lib/utils';
|
||||
import { clickOutside } from '$lib/utils/click-outside';
|
||||
import { getContextMenuPosition } from '$lib/utils/context-menu';
|
||||
import { AssetJobName, type AssetResponseDto, AssetTypeEnum, api } from '@api';
|
||||
import { AssetJobName, AssetTypeEnum, type AssetResponseDto } from '@api';
|
||||
import {
|
||||
mdiAlertOutline,
|
||||
mdiArrowLeft,
|
||||
|
|
@ -22,7 +24,6 @@
|
|||
import { createEventDispatcher } from 'svelte';
|
||||
import ContextMenu from '../shared-components/context-menu/context-menu.svelte';
|
||||
import MenuOption from '../shared-components/context-menu/menu-option.svelte';
|
||||
import { user } from '$lib/stores/user.store';
|
||||
|
||||
export let asset: AssetResponseDto;
|
||||
export let showCopyButton: boolean;
|
||||
|
|
@ -182,16 +183,16 @@
|
|||
|
||||
<MenuOption
|
||||
on:click={() => onJobClick(AssetJobName.RefreshMetadata)}
|
||||
text={api.getAssetJobName(AssetJobName.RefreshMetadata)}
|
||||
text={getAssetJobName(AssetJobName.RefreshMetadata)}
|
||||
/>
|
||||
<MenuOption
|
||||
on:click={() => onJobClick(AssetJobName.RegenerateThumbnail)}
|
||||
text={api.getAssetJobName(AssetJobName.RegenerateThumbnail)}
|
||||
text={getAssetJobName(AssetJobName.RegenerateThumbnail)}
|
||||
/>
|
||||
{#if asset.type === AssetTypeEnum.Video}
|
||||
<MenuOption
|
||||
on:click={() => onJobClick(AssetJobName.TranscodeVideo)}
|
||||
text={api.getAssetJobName(AssetJobName.TranscodeVideo)}
|
||||
text={getAssetJobName(AssetJobName.TranscodeVideo)}
|
||||
/>
|
||||
{/if}
|
||||
{/if}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
import { SlideshowState, slideshowStore } from '$lib/stores/slideshow.store';
|
||||
import { stackAssetsStore } from '$lib/stores/stacked-asset.store';
|
||||
import { user } from '$lib/stores/user.store';
|
||||
import { getAssetJobMessage, isSharedLink } from '$lib/utils';
|
||||
import { addAssetsToAlbum, downloadFile } from '$lib/utils/asset-utils';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { shouldIgnoreShortcut } from '$lib/utils/shortcut';
|
||||
|
|
@ -19,7 +20,6 @@
|
|||
AssetJobName,
|
||||
AssetTypeEnum,
|
||||
ReactionType,
|
||||
api,
|
||||
type ActivityResponseDto,
|
||||
type AlbumResponseDto,
|
||||
type AssetResponseDto,
|
||||
|
|
@ -29,9 +29,13 @@
|
|||
createActivity,
|
||||
createAlbum,
|
||||
deleteActivity,
|
||||
deleteAssets,
|
||||
getActivities,
|
||||
getActivityStatistics,
|
||||
getAllAlbums,
|
||||
runAssetJobs,
|
||||
updateAsset,
|
||||
updateAssets,
|
||||
} from '@immich/sdk';
|
||||
import { mdiChevronLeft, mdiChevronRight, mdiImageBrokenVariant } from '@mdi/js';
|
||||
import { createEventDispatcher, onDestroy, onMount } from 'svelte';
|
||||
|
|
@ -235,7 +239,7 @@
|
|||
$: asset.id && !sharedLink && handleGetAllAlbums(); // Update the album information when the asset ID changes
|
||||
|
||||
const handleGetAllAlbums = async () => {
|
||||
if (api.isSharedLink) {
|
||||
if (isSharedLink()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -386,7 +390,7 @@
|
|||
|
||||
const trashAsset = async () => {
|
||||
try {
|
||||
await api.assetApi.deleteAssets({ assetBulkDeleteDto: { ids: [asset.id] } });
|
||||
await deleteAssets({ assetBulkDeleteDto: { ids: [asset.id] } });
|
||||
|
||||
dispatch('action', { type: AssetAction.TRASH, asset });
|
||||
|
||||
|
|
@ -401,7 +405,7 @@
|
|||
|
||||
const deleteAsset = async () => {
|
||||
try {
|
||||
await api.assetApi.deleteAssets({ assetBulkDeleteDto: { ids: [asset.id], force: true } });
|
||||
await deleteAssets({ assetBulkDeleteDto: { ids: [asset.id], force: true } });
|
||||
|
||||
dispatch('action', { type: AssetAction.DELETE, asset });
|
||||
|
||||
|
|
@ -418,7 +422,7 @@
|
|||
|
||||
const toggleFavorite = async () => {
|
||||
try {
|
||||
const { data } = await api.assetApi.updateAsset({
|
||||
const data = await updateAsset({
|
||||
id: asset.id,
|
||||
updateAssetDto: {
|
||||
isFavorite: !asset.isFavorite,
|
||||
|
|
@ -470,7 +474,7 @@
|
|||
|
||||
const toggleArchive = async () => {
|
||||
try {
|
||||
const { data } = await api.assetApi.updateAsset({
|
||||
const data = await updateAsset({
|
||||
id: asset.id,
|
||||
updateAssetDto: {
|
||||
isArchived: !asset.isArchived,
|
||||
|
|
@ -491,8 +495,8 @@
|
|||
|
||||
const handleRunJob = async (name: AssetJobName) => {
|
||||
try {
|
||||
await api.assetApi.runAssetJobs({ assetJobsDto: { assetIds: [asset.id], name } });
|
||||
notificationController.show({ type: NotificationType.Info, message: api.getAssetJobMessage(name) });
|
||||
await runAssetJobs({ assetJobsDto: { assetIds: [asset.id], name } });
|
||||
notificationController.show({ type: NotificationType.Info, message: getAssetJobMessage(name) });
|
||||
} catch (error) {
|
||||
await handleError(error, `Unable to submit job`);
|
||||
}
|
||||
|
|
@ -552,7 +556,7 @@
|
|||
const handleUnstack = async () => {
|
||||
try {
|
||||
const ids = $stackAssetsStore.map(({ id }) => id);
|
||||
await api.assetApi.updateAssets({ assetBulkUpdateDto: { ids, removeParent: true } });
|
||||
await updateAssets({ assetBulkUpdateDto: { ids, removeParent: true } });
|
||||
for (const child of $stackAssetsStore) {
|
||||
child.stackParentId = null;
|
||||
child.stackCount = 0;
|
||||
|
|
|
|||
|
|
@ -1,15 +1,18 @@
|
|||
<script lang="ts">
|
||||
import Icon from '$lib/components/elements/icon.svelte';
|
||||
import ChangeDate from '$lib/components/shared-components/change-date.svelte';
|
||||
import { AppRoute, QueryParameter } from '$lib/constants';
|
||||
import { boundingBoxesArray } from '$lib/stores/people.store';
|
||||
import { locale } from '$lib/stores/preferences.store';
|
||||
import { featureFlags } from '$lib/stores/server-config.store';
|
||||
import { user } from '$lib/stores/user.store';
|
||||
import { websocketStore } from '$lib/stores/websocket';
|
||||
import { getAssetThumbnailUrl, getPeopleThumbnailUrl, isSharedLink } from '$lib/utils';
|
||||
import { getAssetFilename } from '$lib/utils/asset-utils';
|
||||
import { type AlbumResponseDto, type AssetResponseDto, ThumbnailFormat, api } from '@api';
|
||||
import { DateTime } from 'luxon';
|
||||
import { createEventDispatcher, onDestroy } from 'svelte';
|
||||
import { slide } from 'svelte/transition';
|
||||
import { asByteUnitString } from '../../utils/byte-units';
|
||||
import ImageThumbnail from '../assets/thumbnail/image-thumbnail.svelte';
|
||||
import UserAvatar from '../shared-components/user-avatar.svelte';
|
||||
import ChangeDate from '$lib/components/shared-components/change-date.svelte';
|
||||
import { autoGrowHeight } from '$lib/utils/autogrow';
|
||||
import { clickOutside } from '$lib/utils/click-outside';
|
||||
import { ThumbnailFormat, type AlbumResponseDto, type AssetResponseDto } from '@api';
|
||||
import { getAssetInfo, updateAsset } from '@immich/sdk';
|
||||
import {
|
||||
mdiCalendar,
|
||||
mdiCameraIris,
|
||||
|
|
@ -17,22 +20,21 @@
|
|||
mdiEye,
|
||||
mdiEyeOff,
|
||||
mdiImageOutline,
|
||||
mdiMapMarkerOutline,
|
||||
mdiInformationOutline,
|
||||
mdiMapMarkerOutline,
|
||||
mdiPencil,
|
||||
} from '@mdi/js';
|
||||
import Icon from '$lib/components/elements/icon.svelte';
|
||||
import PersonSidePanel from '../faces-page/person-side-panel.svelte';
|
||||
import CircleIconButton from '../elements/buttons/circle-icon-button.svelte';
|
||||
import Map from '../shared-components/map/map.svelte';
|
||||
import { boundingBoxesArray } from '$lib/stores/people.store';
|
||||
import { websocketStore } from '$lib/stores/websocket';
|
||||
import { AppRoute, QueryParameter } from '$lib/constants';
|
||||
import ChangeLocation from '../shared-components/change-location.svelte';
|
||||
import { DateTime } from 'luxon';
|
||||
import { createEventDispatcher, onDestroy } from 'svelte';
|
||||
import { slide } from 'svelte/transition';
|
||||
import { asByteUnitString } from '../../utils/byte-units';
|
||||
import { handleError } from '../../utils/handle-error';
|
||||
import { user } from '$lib/stores/user.store';
|
||||
import { autoGrowHeight } from '$lib/utils/autogrow';
|
||||
import { clickOutside } from '$lib/utils/click-outside';
|
||||
import ImageThumbnail from '../assets/thumbnail/image-thumbnail.svelte';
|
||||
import CircleIconButton from '../elements/buttons/circle-icon-button.svelte';
|
||||
import PersonSidePanel from '../faces-page/person-side-panel.svelte';
|
||||
import ChangeLocation from '../shared-components/change-location.svelte';
|
||||
import Map from '../shared-components/map/map.svelte';
|
||||
import UserAvatar from '../shared-components/user-avatar.svelte';
|
||||
|
||||
export let asset: AssetResponseDto;
|
||||
export let albums: AlbumResponseDto[] = [];
|
||||
|
|
@ -61,8 +63,8 @@
|
|||
description = newAsset?.exifInfo?.description || '';
|
||||
|
||||
// Get latest description from server
|
||||
if (newAsset.id && !api.isSharedLink) {
|
||||
const { data } = await api.assetApi.getAssetInfo({ id: asset.id });
|
||||
if (newAsset.id && !isSharedLink()) {
|
||||
const data = await getAssetInfo({ id: asset.id });
|
||||
people = data?.people || [];
|
||||
|
||||
description = data.exifInfo?.description || '';
|
||||
|
|
@ -127,9 +129,9 @@
|
|||
};
|
||||
|
||||
const handleRefreshPeople = async () => {
|
||||
await api.assetApi.getAssetInfo({ id: asset.id }).then((res) => {
|
||||
people = res.data?.people || [];
|
||||
textArea.value = res.data?.exifInfo?.description || '';
|
||||
await getAssetInfo({ id: asset.id }).then((data) => {
|
||||
people = data?.people || [];
|
||||
textArea.value = data?.exifInfo?.description || '';
|
||||
});
|
||||
showEditFaces = false;
|
||||
};
|
||||
|
|
@ -146,10 +148,7 @@
|
|||
originalDescription = description;
|
||||
dispatch('descriptionFocusOut');
|
||||
try {
|
||||
await api.assetApi.updateAsset({
|
||||
id: asset.id,
|
||||
updateAssetDto: { description },
|
||||
});
|
||||
await updateAsset({ id: asset.id, updateAssetDto: { description } });
|
||||
} catch (error) {
|
||||
handleError(error, 'Cannot update the description');
|
||||
}
|
||||
|
|
@ -162,7 +161,7 @@
|
|||
async function handleConfirmChangeDate(dateTimeOriginal: string) {
|
||||
isShowChangeDate = false;
|
||||
try {
|
||||
await api.assetApi.updateAsset({ id: asset.id, updateAssetDto: { dateTimeOriginal } });
|
||||
await updateAsset({ id: asset.id, updateAssetDto: { dateTimeOriginal } });
|
||||
} catch (error) {
|
||||
handleError(error, 'Unable to change date');
|
||||
}
|
||||
|
|
@ -174,13 +173,7 @@
|
|||
isShowChangeLocation = false;
|
||||
|
||||
try {
|
||||
await api.assetApi.updateAsset({
|
||||
id: asset.id,
|
||||
updateAssetDto: {
|
||||
latitude: gps.lat,
|
||||
longitude: gps.lng,
|
||||
},
|
||||
});
|
||||
await updateAsset({ id: asset.id, updateAssetDto: { latitude: gps.lat, longitude: gps.lng } });
|
||||
} catch (error) {
|
||||
handleError(error, 'Unable to change location');
|
||||
}
|
||||
|
|
@ -219,7 +212,7 @@
|
|||
<section class="px-4 mt-10">
|
||||
{#key asset.id}
|
||||
<textarea
|
||||
disabled={!isOwner || api.isSharedLink}
|
||||
disabled={!isOwner || isSharedLink()}
|
||||
bind:this={textArea}
|
||||
class="max-h-[500px]
|
||||
w-full resize-none overflow-hidden border-b border-gray-500 bg-transparent text-base text-black outline-none transition-all focus:border-b-2 focus:border-immich-primary disabled:border-none dark:text-white dark:focus:border-immich-dark-primary"
|
||||
|
|
@ -238,7 +231,7 @@
|
|||
<p class="px-4 break-words whitespace-pre-line w-full text-black dark:text-white text-base">{description}</p>
|
||||
{/if}
|
||||
|
||||
{#if !api.isSharedLink && people.length > 0}
|
||||
{#if !isSharedLink() && people.length > 0}
|
||||
<section class="px-4 py-4 text-sm">
|
||||
<div class="flex h-10 w-full items-center justify-between">
|
||||
<h2>PEOPLE</h2>
|
||||
|
|
@ -284,7 +277,7 @@
|
|||
<ImageThumbnail
|
||||
curve
|
||||
shadow
|
||||
url={api.getPeopleThumbnailUrl(person.id)}
|
||||
url={getPeopleThumbnailUrl(person.id)}
|
||||
altText={person.name}
|
||||
title={person.name}
|
||||
widthStyle="90px"
|
||||
|
|
@ -670,7 +663,7 @@
|
|||
alt={album.albumName}
|
||||
class="h-[50px] w-[50px] rounded object-cover"
|
||||
src={album.albumThumbnailAssetId &&
|
||||
api.getAssetThumbnailUrl(album.albumThumbnailAssetId, ThumbnailFormat.Jpeg)}
|
||||
getAssetThumbnailUrl(album.albumThumbnailAssetId, ThumbnailFormat.Jpeg)}
|
||||
draggable="false"
|
||||
/>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -2,12 +2,13 @@
|
|||
import { fade } from 'svelte/transition';
|
||||
import LoadingSpinner from '../shared-components/loading-spinner.svelte';
|
||||
import { api, type AssetResponseDto } from '@api';
|
||||
import { getKey } from '$lib/utils';
|
||||
|
||||
export let asset: AssetResponseDto;
|
||||
|
||||
const loadAssetData = async () => {
|
||||
const { data } = await api.assetApi.serveFile(
|
||||
{ id: asset.id, isThumb: false, isWeb: false, key: api.getKey() },
|
||||
{ id: asset.id, isThumb: false, isWeb: false, key: getKey() },
|
||||
{ responseType: 'blob' },
|
||||
);
|
||||
if (data instanceof Blob) {
|
||||
|
|
|
|||
|
|
@ -1,17 +1,18 @@
|
|||
<script lang="ts">
|
||||
import { fade } from 'svelte/transition';
|
||||
import { onDestroy, onMount } from 'svelte';
|
||||
import LoadingSpinner from '../shared-components/loading-spinner.svelte';
|
||||
import { api, type AssetResponseDto } from '@api';
|
||||
import { notificationController, NotificationType } from '../shared-components/notification/notification';
|
||||
import { useZoomImageWheel } from '@zoom-image/svelte';
|
||||
import { photoZoomState } from '$lib/stores/zoom-image.store';
|
||||
import { isWebCompatibleImage } from '$lib/utils/asset-utils';
|
||||
import { shouldIgnoreShortcut } from '$lib/utils/shortcut';
|
||||
import { photoViewer } from '$lib/stores/assets.store';
|
||||
import { getBoundingBox } from '$lib/utils/people-utils';
|
||||
import { boundingBoxesArray } from '$lib/stores/people.store';
|
||||
import { alwaysLoadOriginalFile } from '$lib/stores/preferences.store';
|
||||
import { photoZoomState } from '$lib/stores/zoom-image.store';
|
||||
import { getKey } from '$lib/utils';
|
||||
import { isWebCompatibleImage } from '$lib/utils/asset-utils';
|
||||
import { getBoundingBox } from '$lib/utils/people-utils';
|
||||
import { shouldIgnoreShortcut } from '$lib/utils/shortcut';
|
||||
import { api, type AssetResponseDto } from '@api';
|
||||
import { useZoomImageWheel } from '@zoom-image/svelte';
|
||||
import { onDestroy, onMount } from 'svelte';
|
||||
import { fade } from 'svelte/transition';
|
||||
import LoadingSpinner from '../shared-components/loading-spinner.svelte';
|
||||
import { NotificationType, notificationController } from '../shared-components/notification/notification';
|
||||
|
||||
export let asset: AssetResponseDto;
|
||||
export let element: HTMLDivElement | undefined = undefined;
|
||||
|
|
@ -50,7 +51,7 @@
|
|||
abortController = new AbortController();
|
||||
|
||||
const { data } = await api.assetApi.serveFile(
|
||||
{ id: asset.id, isThumb: false, isWeb: !loadOriginal, key: api.getKey() },
|
||||
{ id: asset.id, isThumb: false, isWeb: !loadOriginal, key: getKey() },
|
||||
{
|
||||
responseType: 'blob',
|
||||
signal: abortController.signal,
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
<script lang="ts">
|
||||
import { ThumbnailFormat, api } from '@api';
|
||||
import { fade } from 'svelte/transition';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import { videoViewerVolume } from '$lib/stores/preferences.store';
|
||||
import LoadingSpinner from '../shared-components/loading-spinner.svelte';
|
||||
import { getAssetFileUrl, getAssetThumbnailUrl } from '$lib/utils';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { ThumbnailFormat } from '@api';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import { fade } from 'svelte/transition';
|
||||
import LoadingSpinner from '../shared-components/loading-spinner.svelte';
|
||||
|
||||
export let assetId: string;
|
||||
|
||||
|
|
@ -35,9 +36,9 @@
|
|||
on:canplay={handleCanPlay}
|
||||
on:ended={() => dispatch('onVideoEnded')}
|
||||
bind:volume={$videoViewerVolume}
|
||||
poster={api.getAssetThumbnailUrl(assetId, ThumbnailFormat.Jpeg)}
|
||||
poster={getAssetThumbnailUrl(assetId, ThumbnailFormat.Jpeg)}
|
||||
>
|
||||
<source src={api.getAssetFileUrl(assetId, false, true)} type="video/mp4" />
|
||||
<source src={getAssetFileUrl(assetId, false, true)} type="video/mp4" />
|
||||
<track kind="captions" />
|
||||
</video>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
<script lang="ts">
|
||||
import { ProjectionType } from '$lib/constants';
|
||||
import IntersectionObserver from '$lib/components/asset-viewer/intersection-observer.svelte';
|
||||
import Icon from '$lib/components/elements/icon.svelte';
|
||||
import { ProjectionType } from '$lib/constants';
|
||||
import { getAssetFileUrl, getAssetThumbnailUrl, isSharedLink } from '$lib/utils';
|
||||
import { timeToSeconds } from '$lib/utils/time-to-seconds';
|
||||
import { api, type AssetResponseDto, AssetTypeEnum, ThumbnailFormat } from '@api';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import { fade } from 'svelte/transition';
|
||||
import ImageThumbnail from './image-thumbnail.svelte';
|
||||
import VideoThumbnail from './video-thumbnail.svelte';
|
||||
import { AssetTypeEnum, ThumbnailFormat, type AssetResponseDto } from '@api';
|
||||
import {
|
||||
mdiArchiveArrowDownOutline,
|
||||
mdiCameraBurst,
|
||||
|
|
@ -17,7 +15,10 @@
|
|||
mdiMotionPlayOutline,
|
||||
mdiRotate360,
|
||||
} from '@mdi/js';
|
||||
import Icon from '$lib/components/elements/icon.svelte';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import { fade } from 'svelte/transition';
|
||||
import ImageThumbnail from './image-thumbnail.svelte';
|
||||
import VideoThumbnail from './video-thumbnail.svelte';
|
||||
|
||||
const dispatch = createEventDispatcher<{
|
||||
click: { asset: AssetResponseDto };
|
||||
|
|
@ -138,13 +139,13 @@
|
|||
/>
|
||||
|
||||
<!-- Favorite asset star -->
|
||||
{#if !api.isSharedLink && asset.isFavorite}
|
||||
{#if !isSharedLink() && asset.isFavorite}
|
||||
<div class="absolute bottom-2 left-2 z-10">
|
||||
<Icon path={mdiHeart} size="24" class="text-white" />
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if !api.isSharedLink && showArchiveIcon && asset.isArchived}
|
||||
{#if !isSharedLink() && showArchiveIcon && asset.isArchived}
|
||||
<div class="absolute {asset.isFavorite ? 'bottom-10' : 'bottom-2'} left-2 z-10">
|
||||
<Icon path={mdiArchiveArrowDownOutline} size="24" class="text-white" />
|
||||
</div>
|
||||
|
|
@ -175,7 +176,7 @@
|
|||
|
||||
{#if asset.resized}
|
||||
<ImageThumbnail
|
||||
url={api.getAssetThumbnailUrl(asset.id, format)}
|
||||
url={getAssetThumbnailUrl(asset.id, format)}
|
||||
altText={asset.originalFileName}
|
||||
widthStyle="{width}px"
|
||||
heightStyle="{height}px"
|
||||
|
|
@ -191,7 +192,7 @@
|
|||
{#if asset.type === AssetTypeEnum.Video}
|
||||
<div class="absolute top-0 h-full w-full">
|
||||
<VideoThumbnail
|
||||
url={api.getAssetFileUrl(asset.id, false, true)}
|
||||
url={getAssetFileUrl(asset.id, false, true)}
|
||||
enablePlayback={mouseOver}
|
||||
curve={selected}
|
||||
durationInSeconds={timeToSeconds(asset.duration)}
|
||||
|
|
@ -202,7 +203,7 @@
|
|||
{#if asset.type === AssetTypeEnum.Image && asset.livePhotoVideoId}
|
||||
<div class="absolute top-0 h-full w-full">
|
||||
<VideoThumbnail
|
||||
url={api.getAssetFileUrl(asset.livePhotoVideoId, false, true)}
|
||||
url={getAssetFileUrl(asset.livePhotoVideoId, false, true)}
|
||||
pauseIcon={mdiMotionPauseOutline}
|
||||
playIcon={mdiMotionPlayOutline}
|
||||
showTime={false}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,18 @@
|
|||
<script lang="ts">
|
||||
import { api, AssetTypeEnum, type AssetFaceResponseDto, type PersonResponseDto, ThumbnailFormat } from '@api';
|
||||
import { maximumLengthSearchPeople, timeBeforeShowLoadingSpinner } from '$lib/constants';
|
||||
import { photoViewer } from '$lib/stores/assets.store';
|
||||
import { getAssetThumbnailUrl, getPeopleThumbnailUrl } from '$lib/utils';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { getPersonNameWithHiddenValue, searchNameLocal } from '$lib/utils/person';
|
||||
import { AssetTypeEnum, ThumbnailFormat, type AssetFaceResponseDto, type PersonResponseDto } from '@api';
|
||||
import { searchPerson } from '@immich/sdk';
|
||||
import { mdiArrowLeftThin, mdiClose, mdiMagnify, mdiPlus } from '@mdi/js';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import { linear } from 'svelte/easing';
|
||||
import { fly } from 'svelte/transition';
|
||||
import Icon from '../elements/icon.svelte';
|
||||
import { mdiArrowLeftThin, mdiClose, mdiMagnify, mdiPlus } from '@mdi/js';
|
||||
import LoadingSpinner from '../shared-components/loading-spinner.svelte';
|
||||
import ImageThumbnail from '../assets/thumbnail/image-thumbnail.svelte';
|
||||
import { getPersonNameWithHiddenValue, searchNameLocal } from '$lib/utils/person';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { photoViewer } from '$lib/stores/assets.store';
|
||||
import { maximumLengthSearchPeople, timeBeforeShowLoadingSpinner } from '$lib/constants';
|
||||
import Icon from '../elements/icon.svelte';
|
||||
import LoadingSpinner from '../shared-components/loading-spinner.svelte';
|
||||
|
||||
export let peopleWithFaces: AssetFaceResponseDto[];
|
||||
export let allPeople: PersonResponseDto[];
|
||||
|
|
@ -42,7 +44,7 @@
|
|||
if (assetType === AssetTypeEnum.Image) {
|
||||
image = $photoViewer;
|
||||
} else if (assetType === AssetTypeEnum.Video) {
|
||||
const data = await api.getAssetThumbnailUrl(assetId, ThumbnailFormat.Webp);
|
||||
const data = await getAssetThumbnailUrl(assetId, ThumbnailFormat.Webp);
|
||||
const img: HTMLImageElement = new Image();
|
||||
img.src = data;
|
||||
|
||||
|
|
@ -116,7 +118,7 @@
|
|||
}
|
||||
const timeout = setTimeout(() => (isShowLoadingSearch = true), timeBeforeShowLoadingSpinner);
|
||||
try {
|
||||
const { data } = await api.searchApi.searchPerson({ name: searchName });
|
||||
const data = await searchPerson({ name: searchName });
|
||||
searchedPeople = data;
|
||||
searchedPeopleCopy = data;
|
||||
searchWord = searchName;
|
||||
|
|
@ -229,7 +231,7 @@
|
|||
<ImageThumbnail
|
||||
curve
|
||||
shadow
|
||||
url={api.getPeopleThumbnailUrl(person.id)}
|
||||
url={getPeopleThumbnailUrl(person.id)}
|
||||
altText={getPersonNameWithHiddenValue(person.name, person.isHidden)}
|
||||
title={getPersonNameWithHiddenValue(person.name, person.isHidden)}
|
||||
widthStyle="90px"
|
||||
|
|
@ -255,7 +257,7 @@
|
|||
<ImageThumbnail
|
||||
curve
|
||||
shadow
|
||||
url={api.getPeopleThumbnailUrl(person.id)}
|
||||
url={getPeopleThumbnailUrl(person.id)}
|
||||
altText={getPersonNameWithHiddenValue(person.name, person.isHidden)}
|
||||
title={getPersonNameWithHiddenValue(person.name, person.isHidden)}
|
||||
widthStyle="90px"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
<script lang="ts">
|
||||
import { api, type PersonResponseDto } from '@api';
|
||||
import ImageThumbnail from '../assets/thumbnail/image-thumbnail.svelte';
|
||||
import { getPeopleThumbnailUrl } from '$lib/utils';
|
||||
import { type PersonResponseDto } from '@api';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import ImageThumbnail from '../assets/thumbnail/image-thumbnail.svelte';
|
||||
|
||||
export let person: PersonResponseDto;
|
||||
export let selectable = false;
|
||||
|
|
@ -34,13 +35,7 @@
|
|||
class:dark:border-immich-dark-primary={border}
|
||||
class:border-immich-primary={border}
|
||||
>
|
||||
<ImageThumbnail
|
||||
{circle}
|
||||
url={api.getPeopleThumbnailUrl(person.id)}
|
||||
altText={person.name}
|
||||
widthStyle="100%"
|
||||
shadow
|
||||
/>
|
||||
<ImageThumbnail {circle} url={getPeopleThumbnailUrl(person.id)} altText={person.name} widthStyle="100%" shadow />
|
||||
</div>
|
||||
|
||||
<div
|
||||
|
|
|
|||
|
|
@ -1,22 +1,23 @@
|
|||
<script lang="ts">
|
||||
import { goto } from '$app/navigation';
|
||||
import { page } from '$app/stores';
|
||||
import Icon from '$lib/components/elements/icon.svelte';
|
||||
import { ActionQueryParameterValue, AppRoute, QueryParameter } from '$lib/constants';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { type PersonResponseDto } from '@api';
|
||||
import { getAllPeople, getPerson, mergePerson } from '@immich/sdk';
|
||||
import { mdiCallMerge, mdiMerge, mdiSwapHorizontal } from '@mdi/js';
|
||||
import { createEventDispatcher, onMount } from 'svelte';
|
||||
import { api, type PersonResponseDto } from '@api';
|
||||
import FaceThumbnail from './face-thumbnail.svelte';
|
||||
import { flip } from 'svelte/animate';
|
||||
import { quintOut } from 'svelte/easing';
|
||||
import { fly } from 'svelte/transition';
|
||||
import ControlAppBar from '../shared-components/control-app-bar.svelte';
|
||||
import Button from '../elements/buttons/button.svelte';
|
||||
import { flip } from 'svelte/animate';
|
||||
import { NotificationType, notificationController } from '../shared-components/notification/notification';
|
||||
import ConfirmDialogue from '../shared-components/confirm-dialogue.svelte';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { goto } from '$app/navigation';
|
||||
import { ActionQueryParameterValue, AppRoute, QueryParameter } from '$lib/constants';
|
||||
import { mdiCallMerge, mdiMerge, mdiSwapHorizontal } from '@mdi/js';
|
||||
import Icon from '$lib/components/elements/icon.svelte';
|
||||
import CircleIconButton from '../elements/buttons/circle-icon-button.svelte';
|
||||
import ConfirmDialogue from '../shared-components/confirm-dialogue.svelte';
|
||||
import ControlAppBar from '../shared-components/control-app-bar.svelte';
|
||||
import { NotificationType, notificationController } from '../shared-components/notification/notification';
|
||||
import FaceThumbnail from './face-thumbnail.svelte';
|
||||
import PeopleList from './people-list.svelte';
|
||||
import { page } from '$app/stores';
|
||||
|
||||
export let person: PersonResponseDto;
|
||||
let people: PersonResponseDto[] = [];
|
||||
|
|
@ -35,7 +36,7 @@
|
|||
);
|
||||
|
||||
onMount(async () => {
|
||||
const { data } = await api.personApi.getAllPeople({ withHidden: false });
|
||||
const data = await getAllPeople({ withHidden: false });
|
||||
people = data.people;
|
||||
});
|
||||
|
||||
|
|
@ -68,11 +69,11 @@
|
|||
|
||||
const handleMerge = async () => {
|
||||
try {
|
||||
let { data: results } = await api.personApi.mergePerson({
|
||||
let results = await mergePerson({
|
||||
id: person.id,
|
||||
mergePersonDto: { ids: selectedPeople.map(({ id }) => id) },
|
||||
});
|
||||
const { data: mergedPerson } = await api.personApi.getPerson({ id: person.id });
|
||||
const mergedPerson = await getPerson({ id: person.id });
|
||||
const count = results.filter(({ success }) => success).length;
|
||||
notificationController.show({
|
||||
message: `Merged ${count} ${count === 1 ? 'person' : 'people'}`,
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
<script lang="ts">
|
||||
import Icon from '$lib/components/elements/icon.svelte';
|
||||
import FullScreenModal from '$lib/components/shared-components/full-screen-modal.svelte';
|
||||
import { api, type PersonResponseDto } from '@api';
|
||||
import { getPeopleThumbnailUrl } from '$lib/utils';
|
||||
import { type PersonResponseDto } from '@api';
|
||||
import { mdiArrowLeft, mdiClose, mdiMerge } from '@mdi/js';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import ImageThumbnail from '../assets/thumbnail/image-thumbnail.svelte';
|
||||
import Button from '../elements/buttons/button.svelte';
|
||||
import CircleIconButton from '../elements/buttons/circle-icon-button.svelte';
|
||||
import { mdiArrowLeft, mdiClose, mdiMerge } from '@mdi/js';
|
||||
import Icon from '$lib/components/elements/icon.svelte';
|
||||
|
||||
export let personMerge1: PersonResponseDto;
|
||||
export let personMerge2: PersonResponseDto;
|
||||
|
|
@ -60,7 +61,7 @@
|
|||
<ImageThumbnail
|
||||
circle
|
||||
shadow
|
||||
url={api.getPeopleThumbnailUrl(personMerge1.id)}
|
||||
url={getPeopleThumbnailUrl(personMerge1.id)}
|
||||
altText={personMerge1.name}
|
||||
widthStyle="100%"
|
||||
/>
|
||||
|
|
@ -85,7 +86,7 @@
|
|||
border={potentialMergePeople.length > 0}
|
||||
circle
|
||||
shadow
|
||||
url={api.getPeopleThumbnailUrl(personMerge2.id)}
|
||||
url={getPeopleThumbnailUrl(personMerge2.id)}
|
||||
altText={personMerge2.name}
|
||||
widthStyle="100%"
|
||||
/>
|
||||
|
|
@ -104,7 +105,7 @@
|
|||
border={true}
|
||||
circle
|
||||
shadow
|
||||
url={api.getPeopleThumbnailUrl(person.id)}
|
||||
url={getPeopleThumbnailUrl(person.id)}
|
||||
altText={person.name}
|
||||
widthStyle="100%"
|
||||
on:click={() => changePersonToMerge(person)}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,16 @@
|
|||
<script lang="ts">
|
||||
import { type PersonResponseDto, api } from '@api';
|
||||
import Icon from '$lib/components/elements/icon.svelte';
|
||||
import { AppRoute, QueryParameter } from '$lib/constants';
|
||||
import { getPeopleThumbnailUrl } from '$lib/utils';
|
||||
import { getContextMenuPosition } from '$lib/utils/context-menu';
|
||||
import { type PersonResponseDto } from '@api';
|
||||
import { mdiDotsVertical } from '@mdi/js';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import ImageThumbnail from '../assets/thumbnail/image-thumbnail.svelte';
|
||||
import IconButton from '../elements/buttons/icon-button.svelte';
|
||||
import ContextMenu from '../shared-components/context-menu/context-menu.svelte';
|
||||
import MenuOption from '../shared-components/context-menu/menu-option.svelte';
|
||||
import Portal from '../shared-components/portal/portal.svelte';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import { AppRoute, QueryParameter } from '$lib/constants';
|
||||
import { mdiDotsVertical } from '@mdi/js';
|
||||
import Icon from '$lib/components/elements/icon.svelte';
|
||||
|
||||
export let person: PersonResponseDto;
|
||||
export let preload = false;
|
||||
|
|
@ -50,7 +51,7 @@
|
|||
<ImageThumbnail
|
||||
shadow
|
||||
{preload}
|
||||
url={api.getPeopleThumbnailUrl(person.id)}
|
||||
url={getPeopleThumbnailUrl(person.id)}
|
||||
altText={person.name}
|
||||
title={person.name}
|
||||
widthStyle="100%"
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
<script lang="ts">
|
||||
import { api, type PersonResponseDto } from '@api';
|
||||
import FaceThumbnail from './face-thumbnail.svelte';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import { maximumLengthSearchPeople, timeBeforeShowLoadingSpinner } from '$lib/constants';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { searchNameLocal } from '$lib/utils/person';
|
||||
import { type PersonResponseDto } from '@api';
|
||||
import { searchPerson } from '@immich/sdk';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import FaceThumbnail from './face-thumbnail.svelte';
|
||||
import SearchBar from './search-bar.svelte';
|
||||
import { maximumLengthSearchPeople, timeBeforeShowLoadingSpinner } from '$lib/constants';
|
||||
|
||||
export let screenHeight: number;
|
||||
export let people: PersonResponseDto[];
|
||||
|
|
@ -40,8 +41,7 @@
|
|||
|
||||
const timeout = setTimeout(() => (isSearchingPeople = true), timeBeforeShowLoadingSpinner);
|
||||
try {
|
||||
const { data } = await api.searchApi.searchPerson({ name });
|
||||
people = data;
|
||||
people = await searchPerson({ name });
|
||||
searchWord = name;
|
||||
} catch (error) {
|
||||
handleError(error, "Can't search people");
|
||||
|
|
|
|||
|
|
@ -1,20 +1,21 @@
|
|||
<script lang="ts">
|
||||
import { fly } from 'svelte/transition';
|
||||
import { linear } from 'svelte/easing';
|
||||
import { api, type PersonResponseDto, type AssetFaceResponseDto, AssetTypeEnum } from '@api';
|
||||
import ImageThumbnail from '../assets/thumbnail/image-thumbnail.svelte';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { createEventDispatcher, onMount } from 'svelte';
|
||||
import LoadingSpinner from '$lib/components/shared-components/loading-spinner.svelte';
|
||||
import { NotificationType, notificationController } from '../shared-components/notification/notification';
|
||||
import { mdiArrowLeftThin, mdiRestart } from '@mdi/js';
|
||||
import Icon from '../elements/icon.svelte';
|
||||
import { timeBeforeShowLoadingSpinner } from '$lib/constants';
|
||||
import { boundingBoxesArray } from '$lib/stores/people.store';
|
||||
import { websocketStore } from '$lib/stores/websocket';
|
||||
import AssignFaceSidePanel from './assign-face-side-panel.svelte';
|
||||
import { getPeopleThumbnailUrl } from '$lib/utils';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { getPersonNameWithHiddenValue } from '$lib/utils/person';
|
||||
import { timeBeforeShowLoadingSpinner } from '$lib/constants';
|
||||
import { getFaces, reassignFacesById } from '@immich/sdk';
|
||||
import { AssetTypeEnum, type AssetFaceResponseDto, type PersonResponseDto } from '@api';
|
||||
import { createPerson, getAllPeople, getFaces, reassignFacesById } from '@immich/sdk';
|
||||
import { mdiArrowLeftThin, mdiRestart } from '@mdi/js';
|
||||
import { createEventDispatcher, onMount } from 'svelte';
|
||||
import { linear } from 'svelte/easing';
|
||||
import { fly } from 'svelte/transition';
|
||||
import ImageThumbnail from '../assets/thumbnail/image-thumbnail.svelte';
|
||||
import Icon from '../elements/icon.svelte';
|
||||
import { NotificationType, notificationController } from '../shared-components/notification/notification';
|
||||
import AssignFaceSidePanel from './assign-face-side-panel.svelte';
|
||||
|
||||
export let assetId: string;
|
||||
export let assetType: AssetTypeEnum;
|
||||
|
|
@ -69,8 +70,8 @@
|
|||
onMount(async () => {
|
||||
const timeout = setTimeout(() => (isShowLoadingPeople = true), timeBeforeShowLoadingSpinner);
|
||||
try {
|
||||
const { data } = await api.personApi.getAllPeople({ withHidden: true });
|
||||
allPeople = data.people;
|
||||
const { people } = await getAllPeople({ withHidden: true });
|
||||
allPeople = people;
|
||||
peopleWithFaces = await getFaces({ id: assetId });
|
||||
selectedPersonToCreate = Array.from({ length: peopleWithFaces.length });
|
||||
selectedPersonToReassign = Array.from({ length: peopleWithFaces.length });
|
||||
|
|
@ -115,7 +116,7 @@
|
|||
faceDto: { id: peopleWithFace.id },
|
||||
});
|
||||
} else if (selectedPersonToCreate[index]) {
|
||||
const { data } = await api.personApi.createPerson();
|
||||
const data = await createPerson();
|
||||
numberOfPersonToCreate.push(data.id);
|
||||
await reassignFacesById({
|
||||
id: data.id,
|
||||
|
|
@ -214,7 +215,7 @@
|
|||
curve
|
||||
shadow
|
||||
url={selectedPersonToCreate[index] ||
|
||||
api.getPeopleThumbnailUrl(selectedPersonToReassign[index]?.id || face.person.id)}
|
||||
getPeopleThumbnailUrl(selectedPersonToReassign[index]?.id || face.person.id)}
|
||||
altText={selectedPersonToReassign[index]
|
||||
? selectedPersonToReassign[index]?.name || ''
|
||||
: selectedPersonToCreate[index]
|
||||
|
|
|
|||
|
|
@ -1,18 +1,24 @@
|
|||
<script lang="ts">
|
||||
import { createEventDispatcher, onMount } from 'svelte';
|
||||
import FaceThumbnail from './face-thumbnail.svelte';
|
||||
import { quintOut } from 'svelte/easing';
|
||||
import { fly } from 'svelte/transition';
|
||||
import { api, type AssetFaceUpdateItem, type PersonResponseDto } from '@api';
|
||||
import ControlAppBar from '../shared-components/control-app-bar.svelte';
|
||||
import Button from '../elements/buttons/button.svelte';
|
||||
import { mdiPlus, mdiMerge } from '@mdi/js';
|
||||
import LoadingSpinner from '../shared-components/loading-spinner.svelte';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { notificationController, NotificationType } from '../shared-components/notification/notification';
|
||||
import PeopleList from './people-list.svelte';
|
||||
import Icon from '$lib/components/elements/icon.svelte';
|
||||
import { timeBeforeShowLoadingSpinner } from '$lib/constants';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import {
|
||||
createPerson,
|
||||
getAllPeople,
|
||||
reassignFaces,
|
||||
type AssetFaceUpdateItem,
|
||||
type PersonResponseDto,
|
||||
} from '@immich/sdk';
|
||||
import { mdiMerge, mdiPlus } from '@mdi/js';
|
||||
import { createEventDispatcher, onMount } from 'svelte';
|
||||
import { quintOut } from 'svelte/easing';
|
||||
import { fly } from 'svelte/transition';
|
||||
import Button from '../elements/buttons/button.svelte';
|
||||
import ControlAppBar from '../shared-components/control-app-bar.svelte';
|
||||
import LoadingSpinner from '../shared-components/loading-spinner.svelte';
|
||||
import { NotificationType, notificationController } from '../shared-components/notification/notification';
|
||||
import FaceThumbnail from './face-thumbnail.svelte';
|
||||
import PeopleList from './people-list.svelte';
|
||||
|
||||
export let assetIds: string[];
|
||||
export let personAssets: PersonResponseDto;
|
||||
|
|
@ -41,7 +47,7 @@
|
|||
}
|
||||
|
||||
onMount(async () => {
|
||||
const { data } = await api.personApi.getAllPeople({ withHidden: false });
|
||||
const data = await getAllPeople({ withHidden: false });
|
||||
people = data.people;
|
||||
});
|
||||
|
||||
|
|
@ -68,11 +74,8 @@
|
|||
|
||||
try {
|
||||
disableButtons = true;
|
||||
const { data } = await api.personApi.createPerson();
|
||||
await api.personApi.reassignFaces({
|
||||
id: data.id,
|
||||
assetFaceUpdateDto: { data: selectedPeople },
|
||||
});
|
||||
const data = await createPerson();
|
||||
await reassignFaces({ id: data.id, assetFaceUpdateDto: { data: selectedPeople } });
|
||||
|
||||
notificationController.show({
|
||||
message: `Re-assigned ${assetIds.length} asset${assetIds.length > 1 ? 's' : ''} to a new person`,
|
||||
|
|
@ -93,10 +96,7 @@
|
|||
try {
|
||||
disableButtons = true;
|
||||
if (selectedPerson) {
|
||||
await api.personApi.reassignFaces({
|
||||
id: selectedPerson.id,
|
||||
assetFaceUpdateDto: { data: selectedPeople },
|
||||
});
|
||||
await reassignFaces({ id: selectedPerson.id, assetFaceUpdateDto: { data: selectedPeople } });
|
||||
notificationController.show({
|
||||
message: `Re-assigned ${assetIds.length} asset${assetIds.length > 1 ? 's' : ''} to ${
|
||||
selectedPerson.name || 'an existing person'
|
||||
|
|
|
|||
|
|
@ -1,20 +1,21 @@
|
|||
<script lang="ts">
|
||||
import { memoryStore } from '$lib/stores/memory.store';
|
||||
import { DateTime } from 'luxon';
|
||||
import { onMount } from 'svelte';
|
||||
import { api } from '@api';
|
||||
import { goto } from '$app/navigation';
|
||||
import ControlAppBar from '$lib/components/shared-components/control-app-bar.svelte';
|
||||
import { fromLocalDateTime } from '$lib/utils/timeline-util';
|
||||
import { AppRoute, QueryParameter } from '$lib/constants';
|
||||
import { page } from '$app/stores';
|
||||
import noThumbnailUrl from '$lib/assets/no-thumbnail.png';
|
||||
import GalleryViewer from '$lib/components/shared-components/gallery-viewer/gallery-viewer.svelte';
|
||||
import CircleIconButton from '$lib/components/elements/buttons/circle-icon-button.svelte';
|
||||
import IntersectionObserver from '$lib/components/asset-viewer/intersection-observer.svelte';
|
||||
import { fade } from 'svelte/transition';
|
||||
import { tweened } from 'svelte/motion';
|
||||
import CircleIconButton from '$lib/components/elements/buttons/circle-icon-button.svelte';
|
||||
import ControlAppBar from '$lib/components/shared-components/control-app-bar.svelte';
|
||||
import GalleryViewer from '$lib/components/shared-components/gallery-viewer/gallery-viewer.svelte';
|
||||
import { AppRoute, QueryParameter } from '$lib/constants';
|
||||
import { memoryStore } from '$lib/stores/memory.store';
|
||||
import { getAssetThumbnailUrl } from '$lib/utils';
|
||||
import { fromLocalDateTime } from '$lib/utils/timeline-util';
|
||||
import { getMemoryLane } from '@immich/sdk';
|
||||
import { mdiChevronDown, mdiChevronLeft, mdiChevronRight, mdiChevronUp, mdiPause, mdiPlay } from '@mdi/js';
|
||||
import { DateTime } from 'luxon';
|
||||
import { onMount } from 'svelte';
|
||||
import { tweened } from 'svelte/motion';
|
||||
import { fade } from 'svelte/transition';
|
||||
|
||||
const parseIndex = (s: string | null, max: number | null) =>
|
||||
Math.max(Math.min(Number.parseInt(s ?? '') || 0, max ?? 0), 0);
|
||||
|
|
@ -87,11 +88,10 @@
|
|||
onMount(async () => {
|
||||
if (!$memoryStore) {
|
||||
const localTime = new Date();
|
||||
const { data } = await api.assetApi.getMemoryLane({
|
||||
$memoryStore = await getMemoryLane({
|
||||
month: localTime.getMonth() + 1,
|
||||
day: localTime.getDate(),
|
||||
});
|
||||
$memoryStore = data;
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -168,7 +168,7 @@
|
|||
<button class="relative h-full w-full rounded-2xl" disabled={!previousMemory} on:click={toPreviousMemory}>
|
||||
<img
|
||||
class="h-full w-full rounded-2xl object-cover"
|
||||
src={previousMemory ? api.getAssetThumbnailUrl(previousMemory.assets[0].id, 'JPEG') : noThumbnailUrl}
|
||||
src={previousMemory ? getAssetThumbnailUrl(previousMemory.assets[0].id, 'JPEG') : noThumbnailUrl}
|
||||
alt=""
|
||||
draggable="false"
|
||||
/>
|
||||
|
|
@ -191,7 +191,7 @@
|
|||
<img
|
||||
transition:fade
|
||||
class="h-full w-full rounded-2xl object-contain transition-all"
|
||||
src={api.getAssetThumbnailUrl(currentAsset.id, 'JPEG')}
|
||||
src={getAssetThumbnailUrl(currentAsset.id, 'JPEG')}
|
||||
alt=""
|
||||
draggable="false"
|
||||
/>
|
||||
|
|
@ -231,7 +231,7 @@
|
|||
<button class="relative h-full w-full rounded-2xl" on:click={toNextMemory} disabled={!nextMemory}>
|
||||
<img
|
||||
class="h-full w-full rounded-2xl object-cover"
|
||||
src={nextMemory ? api.getAssetThumbnailUrl(nextMemory.assets[0].id, 'JPEG') : noThumbnailUrl}
|
||||
src={nextMemory ? getAssetThumbnailUrl(nextMemory.assets[0].id, 'JPEG') : noThumbnailUrl}
|
||||
alt=""
|
||||
draggable="false"
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -4,12 +4,12 @@
|
|||
NotificationType,
|
||||
notificationController,
|
||||
} from '$lib/components/shared-components/notification/notification';
|
||||
import type { OnArchive } from '$lib/utils/actions';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { api } from '@api';
|
||||
import { updateAssets } from '@immich/sdk';
|
||||
import { mdiArchiveArrowDownOutline, mdiArchiveArrowUpOutline, mdiTimerSand } from '@mdi/js';
|
||||
import MenuOption from '../../shared-components/context-menu/menu-option.svelte';
|
||||
import { getAssetControlContext } from '../asset-select-control-bar.svelte';
|
||||
import { mdiArchiveArrowUpOutline, mdiArchiveArrowDownOutline, mdiTimerSand } from '@mdi/js';
|
||||
import type { OnArchive } from '$lib/utils/actions';
|
||||
|
||||
export let onArchive: OnArchive | undefined = undefined;
|
||||
|
||||
|
|
@ -32,7 +32,7 @@
|
|||
const ids = assets.map(({ id }) => id);
|
||||
|
||||
if (ids.length > 0) {
|
||||
await api.assetApi.updateAssets({ assetBulkUpdateDto: { ids, isArchived } });
|
||||
await updateAssets({ assetBulkUpdateDto: { ids, isArchived } });
|
||||
}
|
||||
|
||||
for (const asset of assets) {
|
||||
|
|
|
|||
|
|
@ -4,8 +4,10 @@
|
|||
NotificationType,
|
||||
notificationController,
|
||||
} from '$lib/components/shared-components/notification/notification';
|
||||
import { getAssetJobMessage, getAssetJobName } from '$lib/utils';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { AssetJobName, AssetTypeEnum, api } from '@api';
|
||||
import { AssetJobName, AssetTypeEnum } from '@api';
|
||||
import { runAssetJobs } from '@immich/sdk';
|
||||
import { getAssetControlContext } from '../asset-select-control-bar.svelte';
|
||||
|
||||
export let jobs: AssetJobName[] = [
|
||||
|
|
@ -21,8 +23,8 @@
|
|||
const handleRunJob = async (name: AssetJobName) => {
|
||||
try {
|
||||
const ids = [...getOwnedAssets()].map(({ id }) => id);
|
||||
await api.assetApi.runAssetJobs({ assetJobsDto: { assetIds: ids, name } });
|
||||
notificationController.show({ message: api.getAssetJobMessage(name), type: NotificationType.Info });
|
||||
await runAssetJobs({ assetJobsDto: { assetIds: ids, name } });
|
||||
notificationController.show({ message: getAssetJobMessage(name), type: NotificationType.Info });
|
||||
clearSelect();
|
||||
} catch (error) {
|
||||
handleError(error, 'Unable to submit job');
|
||||
|
|
@ -32,6 +34,6 @@
|
|||
|
||||
{#each jobs as job}
|
||||
{#if isAllVideos || job !== AssetJobName.TranscodeVideo}
|
||||
<MenuOption text={api.getAssetJobName(job)} on:click={() => handleRunJob(job)} />
|
||||
<MenuOption text={getAssetJobName(job)} on:click={() => handleRunJob(job)} />
|
||||
{/if}
|
||||
{/each}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
<script lang="ts">
|
||||
import ChangeDate from '$lib/components/shared-components/change-date.svelte';
|
||||
import { user } from '$lib/stores/user.store';
|
||||
import { getSelectedAssets } from '$lib/utils/asset-utils';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { api } from '@api';
|
||||
import { updateAssets } from '@immich/sdk';
|
||||
import { DateTime } from 'luxon';
|
||||
import MenuOption from '../../shared-components/context-menu/menu-option.svelte';
|
||||
import { getAssetControlContext } from '../asset-select-control-bar.svelte';
|
||||
import { user } from '$lib/stores/user.store';
|
||||
import { getSelectedAssets } from '$lib/utils/asset-utils';
|
||||
export let menuItem = false;
|
||||
const { clearSelect, getOwnedAssets } = getAssetControlContext();
|
||||
|
||||
|
|
@ -17,9 +17,7 @@
|
|||
const ids = getSelectedAssets(getOwnedAssets(), $user);
|
||||
|
||||
try {
|
||||
await api.assetApi.updateAssets({
|
||||
assetBulkUpdateDto: { ids, dateTimeOriginal },
|
||||
});
|
||||
await updateAssets({ assetBulkUpdateDto: { ids, dateTimeOriginal } });
|
||||
} catch (error) {
|
||||
handleError(error, 'Unable to change date');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
<script lang="ts">
|
||||
import { api } from '@api';
|
||||
import MenuOption from '../../shared-components/context-menu/menu-option.svelte';
|
||||
import { getAssetControlContext } from '../asset-select-control-bar.svelte';
|
||||
import ChangeLocation from '$lib/components/shared-components/change-location.svelte';
|
||||
import { handleError } from '../../../utils/handle-error';
|
||||
import { user } from '$lib/stores/user.store';
|
||||
import { getSelectedAssets } from '$lib/utils/asset-utils';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { updateAssets } from '@immich/sdk';
|
||||
import MenuOption from '../../shared-components/context-menu/menu-option.svelte';
|
||||
import { getAssetControlContext } from '../asset-select-control-bar.svelte';
|
||||
|
||||
export let menuItem = false;
|
||||
const { clearSelect, getOwnedAssets } = getAssetControlContext();
|
||||
|
|
@ -17,13 +17,7 @@
|
|||
const ids = getSelectedAssets(getOwnedAssets(), $user);
|
||||
|
||||
try {
|
||||
await api.assetApi.updateAssets({
|
||||
assetBulkUpdateDto: {
|
||||
ids,
|
||||
latitude: point.lat,
|
||||
longitude: point.lng,
|
||||
},
|
||||
});
|
||||
await updateAssets({ assetBulkUpdateDto: { ids, latitude: point.lat, longitude: point.lng } });
|
||||
} catch (error) {
|
||||
handleError(error, 'Unable to update location');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,11 +5,11 @@
|
|||
NotificationType,
|
||||
notificationController,
|
||||
} from '$lib/components/shared-components/notification/notification';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { api } from '@api';
|
||||
import { getAssetControlContext } from '../asset-select-control-bar.svelte';
|
||||
import { mdiHeartMinusOutline, mdiHeartOutline, mdiTimerSand } from '@mdi/js';
|
||||
import type { OnFavorite } from '$lib/utils/actions';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { updateAssets } from '@immich/sdk';
|
||||
import { mdiHeartMinusOutline, mdiHeartOutline, mdiTimerSand } from '@mdi/js';
|
||||
import { getAssetControlContext } from '../asset-select-control-bar.svelte';
|
||||
|
||||
export let onFavorite: OnFavorite | undefined = undefined;
|
||||
|
||||
|
|
@ -33,7 +33,7 @@
|
|||
const ids = assets.map(({ id }) => id);
|
||||
|
||||
if (ids.length > 0) {
|
||||
await api.assetApi.updateAssets({ assetBulkUpdateDto: { ids, isFavorite } });
|
||||
await updateAssets({ assetBulkUpdateDto: { ids, isFavorite } });
|
||||
}
|
||||
|
||||
for (const asset of assets) {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
<script lang="ts">
|
||||
import CircleIconButton from '$lib/components/elements/buttons/circle-icon-button.svelte';
|
||||
import { type SharedLinkResponseDto, api } from '@api';
|
||||
import ConfirmDialogue from '../../shared-components/confirm-dialogue.svelte';
|
||||
import { getAssetControlContext } from '../asset-select-control-bar.svelte';
|
||||
import { NotificationType, notificationController } from '../../shared-components/notification/notification';
|
||||
import { handleError } from '../../../utils/handle-error';
|
||||
import { getKey } from '$lib/utils';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { type SharedLinkResponseDto } from '@api';
|
||||
import { removeSharedLinkAssets } from '@immich/sdk';
|
||||
import { mdiDeleteOutline } from '@mdi/js';
|
||||
import ConfirmDialogue from '../../shared-components/confirm-dialogue.svelte';
|
||||
import { NotificationType, notificationController } from '../../shared-components/notification/notification';
|
||||
import { getAssetControlContext } from '../asset-select-control-bar.svelte';
|
||||
|
||||
export let sharedLink: SharedLinkResponseDto;
|
||||
|
||||
|
|
@ -15,12 +17,12 @@
|
|||
|
||||
const handleRemove = async () => {
|
||||
try {
|
||||
const { data: results } = await api.sharedLinkApi.removeSharedLinkAssets({
|
||||
const results = await removeSharedLinkAssets({
|
||||
id: sharedLink.id,
|
||||
assetIdsDto: {
|
||||
assetIds: [...getAssets()].map((asset) => asset.id),
|
||||
},
|
||||
key: api.getKey(),
|
||||
key: getKey(),
|
||||
});
|
||||
|
||||
for (const result of results) {
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
<script lang="ts">
|
||||
import MenuOption from '$lib/components/shared-components/context-menu/menu-option.svelte';
|
||||
import { api } from '@api';
|
||||
import { getAssetControlContext } from '../asset-select-control-bar.svelte';
|
||||
import {
|
||||
NotificationType,
|
||||
notificationController,
|
||||
} from '$lib/components/shared-components/notification/notification';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import type { OnStack } from '$lib/utils/actions';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { updateAssets } from '@immich/sdk';
|
||||
import { getAssetControlContext } from '../asset-select-control-bar.svelte';
|
||||
|
||||
export let onStack: OnStack | undefined;
|
||||
|
||||
|
|
@ -26,7 +26,7 @@
|
|||
const ids = children.map(({ id }) => id);
|
||||
|
||||
if (children.length > 0) {
|
||||
await api.assetApi.updateAssets({ assetBulkUpdateDto: { ids, stackParentId: parent.id } });
|
||||
await updateAssets({ assetBulkUpdateDto: { ids, stackParentId: parent.id } });
|
||||
}
|
||||
|
||||
let childrenCount = parent.stackCount ?? 0;
|
||||
|
|
|
|||
|
|
@ -1,22 +1,19 @@
|
|||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import { api } from '@api';
|
||||
import Icon from '$lib/components/elements/icon.svelte';
|
||||
import { memoryStore } from '$lib/stores/memory.store';
|
||||
import { goto } from '$app/navigation';
|
||||
import { fade } from 'svelte/transition';
|
||||
import { mdiChevronLeft, mdiChevronRight } from '@mdi/js';
|
||||
import Icon from '$lib/components/elements/icon.svelte';
|
||||
import { AppRoute, QueryParameter } from '$lib/constants';
|
||||
import { memoryStore } from '$lib/stores/memory.store';
|
||||
import { getAssetThumbnailUrl } from '$lib/utils';
|
||||
import { getMemoryLane } from '@immich/sdk';
|
||||
import { mdiChevronLeft, mdiChevronRight } from '@mdi/js';
|
||||
import { onMount } from 'svelte';
|
||||
import { fade } from 'svelte/transition';
|
||||
|
||||
$: shouldRender = $memoryStore?.length > 0;
|
||||
|
||||
onMount(async () => {
|
||||
const localTime = new Date();
|
||||
const { data } = await api.assetApi.getMemoryLane({
|
||||
month: localTime.getMonth() + 1,
|
||||
day: localTime.getDate(),
|
||||
});
|
||||
$memoryStore = data;
|
||||
$memoryStore = await getMemoryLane({ month: localTime.getMonth() + 1, day: localTime.getDate() });
|
||||
});
|
||||
|
||||
let memoryLaneElement: HTMLElement;
|
||||
|
|
@ -76,7 +73,7 @@
|
|||
>
|
||||
<img
|
||||
class="h-full w-full rounded-xl object-cover"
|
||||
src={api.getAssetThumbnailUrl(memory.assets[0].id, 'JPEG')}
|
||||
src={getAssetThumbnailUrl(memory.assets[0].id, 'JPEG')}
|
||||
alt={memory.title}
|
||||
draggable="false"
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,14 @@
|
|||
<script lang="ts">
|
||||
import { goto } from '$app/navigation';
|
||||
import { fileUploadHandler, openFileUploadDialog } from '$lib/utils/file-uploader';
|
||||
import { downloadArchive } from '$lib/utils/asset-utils';
|
||||
import { api, type AssetResponseDto, type SharedLinkResponseDto } from '@api';
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { dragAndDropFilesStore } from '$lib/stores/drag-and-drop-files.store';
|
||||
import { getKey } from '$lib/utils';
|
||||
import { downloadArchive } from '$lib/utils/asset-utils';
|
||||
import { fileUploadHandler, openFileUploadDialog } from '$lib/utils/file-uploader';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { type AssetResponseDto, type SharedLinkResponseDto } from '@api';
|
||||
import { addSharedLinkAssets } from '@immich/sdk';
|
||||
import { mdiArrowLeft, mdiFileImagePlusOutline, mdiFolderDownloadOutline, mdiSelectAll } from '@mdi/js';
|
||||
import CircleIconButton from '../elements/buttons/circle-icon-button.svelte';
|
||||
import DownloadAction from '../photos-page/actions/download-action.svelte';
|
||||
import RemoveFromSharedLink from '../photos-page/actions/remove-from-shared-link.svelte';
|
||||
|
|
@ -11,10 +16,7 @@
|
|||
import ControlAppBar from '../shared-components/control-app-bar.svelte';
|
||||
import GalleryViewer from '../shared-components/gallery-viewer/gallery-viewer.svelte';
|
||||
import ImmichLogo from '../shared-components/immich-logo.svelte';
|
||||
import { notificationController, NotificationType } from '../shared-components/notification/notification';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { mdiArrowLeft, mdiFileImagePlusOutline, mdiFolderDownloadOutline, mdiSelectAll } from '@mdi/js';
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { NotificationType, notificationController } from '../shared-components/notification/notification';
|
||||
|
||||
export let sharedLink: SharedLinkResponseDto;
|
||||
export let isOwned: boolean;
|
||||
|
|
@ -41,12 +43,12 @@
|
|||
results = await (!files || files.length === 0 || !Array.isArray(files)
|
||||
? openFileUploadDialog()
|
||||
: fileUploadHandler(files));
|
||||
const { data } = await api.sharedLinkApi.addSharedLinkAssets({
|
||||
const data = await addSharedLinkAssets({
|
||||
id: sharedLink.id,
|
||||
assetIdsDto: {
|
||||
assetIds: results.filter((id) => !!id) as string[],
|
||||
},
|
||||
key: api.getKey(),
|
||||
key: getKey(),
|
||||
});
|
||||
|
||||
const added = data.filter((item) => item.success).length;
|
||||
|
|
|
|||
|
|
@ -4,16 +4,17 @@
|
|||
} from '$lib/components/admin-page/settings/setting-input-field.svelte';
|
||||
import SettingSwitch from '$lib/components/admin-page/settings/setting-switch.svelte';
|
||||
import Button from '$lib/components/elements/buttons/button.svelte';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { api, copyToClipboard, makeSharedLinkUrl, type SharedLinkResponseDto, SharedLinkType } from '@api';
|
||||
import { createEventDispatcher, onMount } from 'svelte';
|
||||
import Icon from '$lib/components/elements/icon.svelte';
|
||||
import { serverConfig } from '$lib/stores/server-config.store';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { SharedLinkType, copyToClipboard, makeSharedLinkUrl, type SharedLinkResponseDto } from '@api';
|
||||
import { createSharedLink, updateSharedLink } from '@immich/sdk';
|
||||
import { mdiLink } from '@mdi/js';
|
||||
import { createEventDispatcher, onMount } from 'svelte';
|
||||
import BaseModal from '../base-modal.svelte';
|
||||
import type { ImmichDropDownOption } from '../dropdown-button.svelte';
|
||||
import DropdownButton from '../dropdown-button.svelte';
|
||||
import { notificationController, NotificationType } from '../notification/notification';
|
||||
import { mdiLink } from '@mdi/js';
|
||||
import { serverConfig } from '$lib/stores/server-config.store';
|
||||
import { NotificationType, notificationController } from '../notification/notification';
|
||||
|
||||
export let albumId: string | undefined = undefined;
|
||||
export let assetIds: string[] = [];
|
||||
|
|
@ -70,7 +71,7 @@
|
|||
const expirationDate = expirationTime ? new Date(currentTime + expirationTime).toISOString() : undefined;
|
||||
|
||||
try {
|
||||
const { data } = await api.sharedLinkApi.createSharedLink({
|
||||
const data = await createSharedLink({
|
||||
sharedLinkCreateDto: {
|
||||
type: shareType,
|
||||
albumId,
|
||||
|
|
@ -135,7 +136,7 @@
|
|||
? new Date(currentTime + expirationTime).toISOString()
|
||||
: null;
|
||||
|
||||
await api.sharedLinkApi.updateSharedLink({
|
||||
await updateSharedLink({
|
||||
id: editingLink.id,
|
||||
sharedLinkEditDto: {
|
||||
description,
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
import Icon from '$lib/components/elements/icon.svelte';
|
||||
import { Theme } from '$lib/constants';
|
||||
import { colorTheme, mapSettings } from '$lib/stores/preferences.store';
|
||||
import { api, type MapMarkerResponseDto } from '@api';
|
||||
import { getMapStyle } from '@immich/sdk';
|
||||
import { getAssetThumbnailUrl } from '$lib/utils';
|
||||
import { getMapStyle, type MapMarkerResponseDto } from '@immich/sdk';
|
||||
import { mdiCog, mdiMapMarker } from '@mdi/js';
|
||||
import type { Feature, GeoJsonProperties, Geometry, Point } from 'geojson';
|
||||
import type { GeoJSONSource, LngLatLike, StyleSpecification } from 'maplibre-gl';
|
||||
|
|
@ -174,7 +174,7 @@
|
|||
/>
|
||||
{:else}
|
||||
<img
|
||||
src={api.getAssetThumbnailUrl(feature.properties?.id)}
|
||||
src={getAssetThumbnailUrl(feature.properties?.id, undefined)}
|
||||
class="rounded-full w-[60px] h-[60px] border-2 border-immich-primary shadow-lg hover:border-immich-dark-primary transition-all duration-200 hover:scale-150 object-cover bg-immich-primary"
|
||||
alt={`Image with id ${feature.properties?.id}`}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -4,12 +4,11 @@
|
|||
import { AppRoute } from '$lib/constants';
|
||||
import { user } from '$lib/stores/user.store';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { UserAvatarColor } from '@api';
|
||||
import { deleteProfileImage, updateUser } from '@immich/sdk';
|
||||
import { deleteProfileImage, updateUser, type UserAvatarColor } from '@immich/sdk';
|
||||
import { mdiCog, mdiLogout, mdiPencil } from '@mdi/js';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import { fade } from 'svelte/transition';
|
||||
import { notificationController, NotificationType } from '../notification/notification';
|
||||
import { NotificationType, notificationController } from '../notification/notification';
|
||||
import UserAvatar from '../user-avatar.svelte';
|
||||
import AvatarSelector from './avatar-selector.svelte';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,15 @@
|
|||
<script lang="ts">
|
||||
import ImageThumbnail from '$lib/components/assets/thumbnail/image-thumbnail.svelte';
|
||||
import Button from '$lib/components/elements/buttons/button.svelte';
|
||||
import Icon from '$lib/components/elements/icon.svelte';
|
||||
import { getPeopleThumbnailUrl } from '$lib/utils';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { SearchSuggestionType, type PersonResponseDto } from '@api';
|
||||
import { getAllPeople, getSearchSuggestions } from '@immich/sdk';
|
||||
import { mdiArrowRight, mdiClose } from '@mdi/js';
|
||||
import { onMount } from 'svelte';
|
||||
import { fly } from 'svelte/transition';
|
||||
import Combobox, { type ComboBoxOption } from '../combobox.svelte';
|
||||
import { SearchSuggestionType, api, type PersonResponseDto } from '@api';
|
||||
import ImageThumbnail from '$lib/components/assets/thumbnail/image-thumbnail.svelte';
|
||||
import Icon from '$lib/components/elements/icon.svelte';
|
||||
import { mdiArrowRight, mdiClose } from '@mdi/js';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
enum MediaType {
|
||||
All = 'all',
|
||||
|
|
@ -108,8 +110,8 @@
|
|||
|
||||
const getPeople = async () => {
|
||||
try {
|
||||
const { data } = await api.personApi.getAllPeople({ withHidden: false });
|
||||
suggestions.people = data.people;
|
||||
const { people } = await getAllPeople({ withHidden: false });
|
||||
suggestions.people = people;
|
||||
} catch (error) {
|
||||
handleError(error, 'Failed to get people');
|
||||
}
|
||||
|
|
@ -143,8 +145,8 @@
|
|||
}
|
||||
|
||||
try {
|
||||
const { data } = await api.searchApi.getSearchSuggestions({
|
||||
type: type,
|
||||
const data = await getSearchSuggestions({
|
||||
$type: type,
|
||||
country: params.country,
|
||||
state: params.state,
|
||||
make: params.cameraMake,
|
||||
|
|
@ -251,7 +253,7 @@
|
|||
<ImageThumbnail
|
||||
circle
|
||||
shadow
|
||||
url={api.getPeopleThumbnailUrl(person.id)}
|
||||
url={getPeopleThumbnailUrl(person.id)}
|
||||
altText={person.name}
|
||||
widthStyle="100px"
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
import { page } from '$app/stores';
|
||||
import { locale, sidebarSettings } from '$lib/stores/preferences.store';
|
||||
import { featureFlags } from '$lib/stores/server-config.store';
|
||||
import { api, type AssetApiGetAssetStatisticsRequest } from '@api';
|
||||
import { getAlbumCount } from '@immich/sdk';
|
||||
import { type AssetApiGetAssetStatisticsRequest } from '@api';
|
||||
import { getAlbumCount, getAssetStatistics } from '@immich/sdk';
|
||||
import {
|
||||
mdiAccount,
|
||||
mdiAccountMultiple,
|
||||
|
|
@ -24,10 +24,7 @@
|
|||
import SideBarButton from './side-bar-button.svelte';
|
||||
import SideBarSection from './side-bar-section.svelte';
|
||||
|
||||
const getStats = async (dto: AssetApiGetAssetStatisticsRequest) => {
|
||||
const { data: stats } = await api.assetApi.getAssetStatistics(dto);
|
||||
return stats;
|
||||
};
|
||||
const getStats = (dto: AssetApiGetAssetStatisticsRequest) => getAssetStatistics(dto);
|
||||
|
||||
const handleAlbumCount = async () => {
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -3,8 +3,9 @@
|
|||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import { getProfileImageUrl } from '$lib/utils';
|
||||
import { type UserAvatarColor } from '@immich/sdk';
|
||||
import { onMount, tick } from 'svelte';
|
||||
import { UserAvatarColor, api } from '@api';
|
||||
|
||||
interface User {
|
||||
id: string;
|
||||
|
|
@ -74,7 +75,7 @@
|
|||
{#if showProfileImage && user.profileImagePath}
|
||||
<img
|
||||
bind:this={img}
|
||||
src={api.getProfileImageUrl(user.id)}
|
||||
src={getProfileImageUrl(user.id)}
|
||||
alt="Profile image of {title}"
|
||||
class="h-full w-full object-cover"
|
||||
class:hidden={showFallback}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,16 @@
|
|||
<script lang="ts">
|
||||
import { api, type AssetResponseDto, type SharedLinkResponseDto, SharedLinkType, ThumbnailFormat } from '@api';
|
||||
import LoadingSpinner from '../shared-components/loading-spinner.svelte';
|
||||
import Icon from '$lib/components/elements/icon.svelte';
|
||||
import * as luxon from 'luxon';
|
||||
import CircleIconButton from '../elements/buttons/circle-icon-button.svelte';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import { goto } from '$app/navigation';
|
||||
import { mdiCircleEditOutline, mdiContentCopy, mdiDelete, mdiOpenInNew } from '@mdi/js';
|
||||
import noThumbnailUrl from '$lib/assets/no-thumbnail.png';
|
||||
import Icon from '$lib/components/elements/icon.svelte';
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { getAssetThumbnailUrl } from '$lib/utils';
|
||||
import { SharedLinkType, ThumbnailFormat, type AssetResponseDto, type SharedLinkResponseDto } from '@api';
|
||||
import { getAssetInfo } from '@immich/sdk';
|
||||
import { mdiCircleEditOutline, mdiContentCopy, mdiDelete, mdiOpenInNew } from '@mdi/js';
|
||||
import * as luxon from 'luxon';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import CircleIconButton from '../elements/buttons/circle-icon-button.svelte';
|
||||
import LoadingSpinner from '../shared-components/loading-spinner.svelte';
|
||||
|
||||
export let link: SharedLinkResponseDto;
|
||||
|
||||
|
|
@ -28,9 +30,7 @@
|
|||
assetId = link.assets[0].id;
|
||||
}
|
||||
|
||||
const { data } = await api.assetApi.getAssetInfo({ id: assetId });
|
||||
|
||||
return data;
|
||||
return getAssetInfo({ id: assetId });
|
||||
};
|
||||
|
||||
const getCountDownExpirationDate = () => {
|
||||
|
|
@ -72,7 +72,7 @@
|
|||
{:then asset}
|
||||
<img
|
||||
id={asset.id}
|
||||
src={api.getAssetThumbnailUrl(asset.id, ThumbnailFormat.Webp)}
|
||||
src={getAssetThumbnailUrl(asset.id, ThumbnailFormat.Webp)}
|
||||
alt={asset.id}
|
||||
class="h-[100px] w-[100px] rounded-lg object-cover"
|
||||
loading="lazy"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue