refactor(web) open api client (#7103)

* refactor: person api

* refactor: shared link and others
This commit is contained in:
Jason Rasmussen
2024-02-14 08:09:49 -05:00
committed by GitHub
parent 5fc1d43012
commit d8631a00bb
81 changed files with 638 additions and 656 deletions

View File

@@ -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>

View File

@@ -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"

View File

@@ -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}

View File

@@ -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;

View File

@@ -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>

View File

@@ -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) {

View File

@@ -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,

View File

@@ -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>