feat(web): lighter timeline buckets
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
<script lang="ts">
|
||||
import CircleIconButton from '$lib/components/elements/buttons/circle-icon-button.svelte';
|
||||
import type { OnArchive } from '$lib/utils/actions';
|
||||
import { archiveAssets } from '$lib/utils/asset-utils';
|
||||
import { mdiArchiveArrowDownOutline, mdiArchiveArrowUpOutline, mdiTimerSand } from '@mdi/js';
|
||||
import { t } from 'svelte-i18n';
|
||||
import MenuOption from '../../shared-components/context-menu/menu-option.svelte';
|
||||
import { getAssetControlContext } from '../asset-select-control-bar.svelte';
|
||||
import { archiveAssets } from '$lib/utils/asset-utils';
|
||||
import { t } from 'svelte-i18n';
|
||||
|
||||
interface Props {
|
||||
onArchive?: OnArchive;
|
||||
|
||||
@@ -6,9 +6,10 @@
|
||||
} from '$lib/components/shared-components/notification/notification';
|
||||
import { getAssetJobIcon, getAssetJobMessage, getAssetJobName } from '$lib/utils';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { AssetJobName, AssetTypeEnum, runAssetJobs } from '@immich/sdk';
|
||||
import { getAssetControlContext } from '../asset-select-control-bar.svelte';
|
||||
import { isTimelineAsset } from '$lib/utils/timeline-util';
|
||||
import { AssetJobName, AssetTypeEnum, runAssetJobs, type AssetResponseDto } from '@immich/sdk';
|
||||
import { t } from 'svelte-i18n';
|
||||
import { getAssetControlContext } from '../asset-select-control-bar.svelte';
|
||||
|
||||
interface Props {
|
||||
jobs?: AssetJobName[];
|
||||
@@ -19,7 +20,11 @@
|
||||
|
||||
const { clearSelect, getOwnedAssets } = getAssetControlContext();
|
||||
|
||||
let isAllVideos = $derived([...getOwnedAssets()].every((asset) => asset.type === AssetTypeEnum.Video));
|
||||
let isAllVideos = $derived(
|
||||
[...getOwnedAssets()].every((asset) =>
|
||||
isTimelineAsset(asset) ? asset.isVideo : (asset as AssetResponseDto).type === AssetTypeEnum.Video,
|
||||
),
|
||||
);
|
||||
|
||||
const handleRunJob = async (name: AssetJobName) => {
|
||||
try {
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
import { getSelectedAssets } from '$lib/utils/asset-utils';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { updateAssets } from '@immich/sdk';
|
||||
import { mdiCalendarEditOutline } from '@mdi/js';
|
||||
import { DateTime } from 'luxon';
|
||||
import { t } from 'svelte-i18n';
|
||||
import MenuOption from '../../shared-components/context-menu/menu-option.svelte';
|
||||
import { getAssetControlContext } from '../asset-select-control-bar.svelte';
|
||||
import { mdiCalendarEditOutline } from '@mdi/js';
|
||||
import { t } from 'svelte-i18n';
|
||||
interface Props {
|
||||
menuItem?: boolean;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
<script lang="ts">
|
||||
import CircleIconButton from '$lib/components/elements/buttons/circle-icon-button.svelte';
|
||||
import { downloadArchive, downloadFile } from '$lib/utils/asset-utils';
|
||||
import MenuOption from '../../shared-components/context-menu/menu-option.svelte';
|
||||
import { shortcut } from '$lib/actions/shortcut';
|
||||
import { getAssetControlContext } from '../asset-select-control-bar.svelte';
|
||||
import CircleIconButton from '$lib/components/elements/buttons/circle-icon-button.svelte';
|
||||
import { getKey } from '$lib/utils';
|
||||
import { downloadArchive, downloadFile } from '$lib/utils/asset-utils';
|
||||
import { isTimelineAsset } from '$lib/utils/timeline-util';
|
||||
import { getAssetInfo, type AssetResponseDto } from '@immich/sdk';
|
||||
import { mdiCloudDownloadOutline, mdiFileDownloadOutline, mdiFolderDownloadOutline } from '@mdi/js';
|
||||
import { t } from 'svelte-i18n';
|
||||
import MenuOption from '../../shared-components/context-menu/menu-option.svelte';
|
||||
import { getAssetControlContext } from '../asset-select-control-bar.svelte';
|
||||
|
||||
interface Props {
|
||||
filename?: string;
|
||||
@@ -20,7 +23,11 @@
|
||||
const assets = [...getAssets()];
|
||||
if (assets.length === 1) {
|
||||
clearSelect();
|
||||
await downloadFile(assets[0]);
|
||||
let asset: AssetResponseDto = assets[0] as AssetResponseDto;
|
||||
if (isTimelineAsset(assets[0])) {
|
||||
asset = await getAssetInfo({ id: assets[0].id, key: getKey() });
|
||||
}
|
||||
await downloadFile(asset);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
<script lang="ts">
|
||||
import CircleIconButton from '$lib/components/elements/buttons/circle-icon-button.svelte';
|
||||
import { getAssetControlContext } from '$lib/components/photos-page/asset-select-control-bar.svelte';
|
||||
import type { TimelineAsset } from '$lib/stores/assets-store.svelte';
|
||||
import type { OnLink, OnUnlink } from '$lib/utils/actions';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { AssetTypeEnum, getAssetInfo, updateAsset } from '@immich/sdk';
|
||||
import { toTimelineAsset } from '$lib/utils/timeline-util';
|
||||
import { getAssetInfo, updateAsset } from '@immich/sdk';
|
||||
import { mdiLinkOff, mdiMotionPlayOutline, mdiTimerSand } from '@mdi/js';
|
||||
import { t } from 'svelte-i18n';
|
||||
import MenuOption from '../../shared-components/context-menu/menu-option.svelte';
|
||||
import { getAssetControlContext } from '../asset-select-control-bar.svelte';
|
||||
|
||||
interface Props {
|
||||
onLink: OnLink;
|
||||
@@ -28,14 +30,14 @@
|
||||
|
||||
const handleLink = async () => {
|
||||
let [still, motion] = [...getOwnedAssets()];
|
||||
if (still.type === AssetTypeEnum.Video) {
|
||||
if ((still as TimelineAsset).isVideo) {
|
||||
[still, motion] = [motion, still];
|
||||
}
|
||||
|
||||
try {
|
||||
loading = true;
|
||||
const stillResponse = await updateAsset({ id: still.id, updateAssetDto: { livePhotoVideoId: motion.id } });
|
||||
onLink({ still: stillResponse, motion });
|
||||
onLink({ still: toTimelineAsset(stillResponse), motion: motion as TimelineAsset });
|
||||
clearSelect();
|
||||
} catch (error) {
|
||||
handleError(error, $t('errors.unable_to_link_motion_video'));
|
||||
@@ -46,22 +48,22 @@
|
||||
|
||||
const handleUnlink = async () => {
|
||||
const [still] = [...getOwnedAssets()];
|
||||
|
||||
const motionId = still?.livePhotoVideoId;
|
||||
if (!motionId) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
loading = true;
|
||||
const stillResponse = await updateAsset({ id: still.id, updateAssetDto: { livePhotoVideoId: null } });
|
||||
const motionResponse = await getAssetInfo({ id: motionId });
|
||||
onUnlink({ still: stillResponse, motion: motionResponse });
|
||||
clearSelect();
|
||||
} catch (error) {
|
||||
handleError(error, $t('errors.unable_to_unlink_motion_video'));
|
||||
} finally {
|
||||
loading = false;
|
||||
if (still) {
|
||||
const motionId = (still as TimelineAsset).livePhotoVideoId;
|
||||
if (!motionId) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
loading = true;
|
||||
const stillResponse = await updateAsset({ id: still.id, updateAssetDto: { livePhotoVideoId: null } });
|
||||
const motionResponse = await getAssetInfo({ id: motionId });
|
||||
onUnlink({ still: toTimelineAsset(stillResponse), motion: toTimelineAsset(motionResponse) });
|
||||
clearSelect();
|
||||
} catch (error) {
|
||||
handleError(error, $t('errors.unable_to_unlink_motion_video'));
|
||||
} finally {
|
||||
loading = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
<script lang="ts">
|
||||
import CircleIconButton from '$lib/components/elements/buttons/circle-icon-button.svelte';
|
||||
import type { AssetInteraction, BaseInteractionAsset } from '$lib/stores/asset-interaction.svelte';
|
||||
import { type AssetStore, isSelectingAllAssets } from '$lib/stores/assets-store.svelte';
|
||||
import { cancelMultiselect, selectAllAssets } from '$lib/utils/asset-utils';
|
||||
import { mdiSelectAll, mdiSelectRemove } from '@mdi/js';
|
||||
import { selectAllAssets, cancelMultiselect } from '$lib/utils/asset-utils';
|
||||
import { t } from 'svelte-i18n';
|
||||
import type { AssetInteraction } from '$lib/stores/asset-interaction.svelte';
|
||||
|
||||
interface Props {
|
||||
assetStore: AssetStore;
|
||||
assetInteraction: AssetInteraction;
|
||||
assetInteraction: AssetInteraction<BaseInteractionAsset>;
|
||||
}
|
||||
|
||||
let { assetStore, assetInteraction }: Props = $props();
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
<script lang="ts">
|
||||
import MenuOption from '$lib/components/shared-components/context-menu/menu-option.svelte';
|
||||
import { getAssetControlContext } from '$lib/components/photos-page/asset-select-control-bar.svelte';
|
||||
import { mdiImageMinusOutline, mdiImageMultipleOutline } from '@mdi/js';
|
||||
import { stackAssets, deleteStack } from '$lib/utils/asset-utils';
|
||||
import MenuOption from '$lib/components/shared-components/context-menu/menu-option.svelte';
|
||||
import type { OnStack, OnUnstack } from '$lib/utils/actions';
|
||||
import { deleteStack, stackAssets } from '$lib/utils/asset-utils';
|
||||
import { toTimelineAsset } from '$lib/utils/timeline-util';
|
||||
import { mdiImageMinusOutline, mdiImageMultipleOutline } from '@mdi/js';
|
||||
import { t } from 'svelte-i18n';
|
||||
|
||||
interface Props {
|
||||
@@ -34,7 +35,7 @@
|
||||
}
|
||||
const unstackedAssets = await deleteStack([stack.id]);
|
||||
if (unstackedAssets) {
|
||||
onUnstack?.(unstackedAssets);
|
||||
onUnstack?.(unstackedAssets.map((a) => toTimelineAsset(a)));
|
||||
}
|
||||
clearSelect();
|
||||
};
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
<script lang="ts">
|
||||
import Icon from '$lib/components/elements/icon.svelte';
|
||||
import {
|
||||
type AssetStore,
|
||||
type AssetBucket,
|
||||
assetSnapshot,
|
||||
assetsSnapshot,
|
||||
type AssetStore,
|
||||
isSelectingAllAssets,
|
||||
type TimelineAsset,
|
||||
} from '$lib/stores/assets-store.svelte';
|
||||
import { navigate } from '$lib/utils/navigation';
|
||||
import { getDateLocaleString } from '$lib/utils/timeline-util';
|
||||
import type { AssetResponseDto } from '@immich/sdk';
|
||||
|
||||
import type { AssetInteraction, BaseInteractionAsset } from '$lib/stores/asset-interaction.svelte';
|
||||
import { mdiCheckCircle, mdiCircleOutline } from '@mdi/js';
|
||||
import { fly } from 'svelte/transition';
|
||||
import { fly, scale } from 'svelte/transition';
|
||||
import Thumbnail from '../assets/thumbnail/thumbnail.svelte';
|
||||
import type { AssetInteraction } from '$lib/stores/asset-interaction.svelte';
|
||||
import { scale } from 'svelte/transition';
|
||||
|
||||
import { flip } from 'svelte/animate';
|
||||
|
||||
@@ -29,11 +29,11 @@
|
||||
showArchiveIcon: boolean;
|
||||
bucket: AssetBucket;
|
||||
assetStore: AssetStore;
|
||||
assetInteraction: AssetInteraction;
|
||||
assetInteraction: AssetInteraction<BaseInteractionAsset>;
|
||||
|
||||
onSelect: ({ title, assets }: { title: string; assets: AssetResponseDto[] }) => void;
|
||||
onSelectAssets: (asset: AssetResponseDto) => void;
|
||||
onSelectAssetCandidates: (asset: AssetResponseDto | null) => void;
|
||||
onSelect: ({ title, assets }: { title: string; assets: TimelineAsset[] }) => void;
|
||||
onSelectAssets: (asset: TimelineAsset) => void;
|
||||
onSelectAssetCandidates: (asset: TimelineAsset | null) => void;
|
||||
}
|
||||
|
||||
let {
|
||||
@@ -54,7 +54,7 @@
|
||||
|
||||
const transitionDuration = $derived.by(() => (bucket.store.suspendTransitions && !$isUploading ? 0 : 150));
|
||||
const scaleDuration = $derived(transitionDuration === 0 ? 0 : transitionDuration + 100);
|
||||
const onClick = (assetStore: AssetStore, assets: AssetResponseDto[], groupTitle: string, asset: AssetResponseDto) => {
|
||||
const onClick = (assetStore: AssetStore, assets: TimelineAsset[], groupTitle: string, asset: TimelineAsset) => {
|
||||
if (isSelectionMode || assetInteraction.selectionActive) {
|
||||
assetSelectHandler(assetStore, asset, assets, groupTitle);
|
||||
return;
|
||||
@@ -62,12 +62,12 @@
|
||||
void navigate({ targetRoute: 'current', assetId: asset.id });
|
||||
};
|
||||
|
||||
const handleSelectGroup = (title: string, assets: AssetResponseDto[]) => onSelect({ title, assets });
|
||||
const handleSelectGroup = (title: string, assets: TimelineAsset[]) => onSelect({ title, assets });
|
||||
|
||||
const assetSelectHandler = (
|
||||
assetStore: AssetStore,
|
||||
asset: AssetResponseDto,
|
||||
assetsInDateGroup: AssetResponseDto[],
|
||||
asset: TimelineAsset,
|
||||
assetsInDateGroup: TimelineAsset[],
|
||||
groupTitle: string,
|
||||
) => {
|
||||
onSelectAssets(asset);
|
||||
@@ -91,7 +91,7 @@
|
||||
}
|
||||
};
|
||||
|
||||
const assetMouseEventHandler = (groupTitle: string, asset: AssetResponseDto | null) => {
|
||||
const assetMouseEventHandler = (groupTitle: string, asset: TimelineAsset | null) => {
|
||||
// Show multi select icon on hover on date group
|
||||
hoveredDateGroup = groupTitle;
|
||||
|
||||
@@ -100,7 +100,7 @@
|
||||
}
|
||||
};
|
||||
|
||||
const assetOnFocusHandler = (asset: AssetResponseDto) => {
|
||||
const assetOnFocusHandler = (asset: TimelineAsset) => {
|
||||
assetInteraction.focussedAssetId = asset.id;
|
||||
};
|
||||
function filterIntersecting<R extends { intersecting: boolean }>(intersectable: R[]) {
|
||||
|
||||
@@ -1,10 +1,21 @@
|
||||
<script lang="ts">
|
||||
import { afterNavigate, beforeNavigate, goto } from '$app/navigation';
|
||||
import { page } from '$app/stores';
|
||||
import { resizeObserver, type OnResizeCallback } from '$lib/actions/resize-observer';
|
||||
import { shortcuts, type ShortcutOptions } from '$lib/actions/shortcut';
|
||||
import type { Action } from '$lib/components/asset-viewer/actions/action';
|
||||
import Skeleton from '$lib/components/photos-page/skeleton.svelte';
|
||||
import { AppRoute, AssetAction } from '$lib/constants';
|
||||
import type { AssetInteraction } from '$lib/stores/asset-interaction.svelte';
|
||||
import { assetViewingStore } from '$lib/stores/asset-viewing.store';
|
||||
import { AssetBucket, assetsSnapshot, AssetStore, isSelectingAllAssets } from '$lib/stores/assets-store.svelte';
|
||||
import {
|
||||
AssetBucket,
|
||||
assetsSnapshot,
|
||||
AssetStore,
|
||||
isSelectingAllAssets,
|
||||
type TimelineAsset,
|
||||
} from '$lib/stores/assets-store.svelte';
|
||||
import { mobileDevice } from '$lib/stores/mobile-device.svelte';
|
||||
import { showDeleteModal } from '$lib/stores/preferences.store';
|
||||
import { searchStore } from '$lib/stores/search.svelte';
|
||||
import { featureFlags } from '$lib/stores/server-config.store';
|
||||
@@ -13,19 +24,14 @@
|
||||
import { archiveAssets, cancelMultiselect, selectAllAssets, stackAssets } from '$lib/utils/asset-utils';
|
||||
import { navigate } from '$lib/utils/navigation';
|
||||
import { type ScrubberListener } from '$lib/utils/timeline-util';
|
||||
import type { AlbumResponseDto, AssetResponseDto, PersonResponseDto } from '@immich/sdk';
|
||||
import { getAssetInfo, type AlbumResponseDto, type PersonResponseDto } from '@immich/sdk';
|
||||
import { onMount, type Snippet } from 'svelte';
|
||||
import type { UpdatePayload } from 'vite';
|
||||
import Portal from '../shared-components/portal/portal.svelte';
|
||||
import Scrubber from '../shared-components/scrubber/scrubber.svelte';
|
||||
import ShowShortcuts from '../shared-components/show-shortcuts.svelte';
|
||||
import AssetDateGroup from './asset-date-group.svelte';
|
||||
import DeleteAssetDialog from './delete-asset-dialog.svelte';
|
||||
import { resizeObserver, type OnResizeCallback } from '$lib/actions/resize-observer';
|
||||
import Skeleton from '$lib/components/photos-page/skeleton.svelte';
|
||||
import { page } from '$app/stores';
|
||||
import type { UpdatePayload } from 'vite';
|
||||
import type { AssetInteraction } from '$lib/stores/asset-interaction.svelte';
|
||||
import { mobileDevice } from '$lib/stores/mobile-device.svelte';
|
||||
|
||||
interface Props {
|
||||
isSelectionMode?: boolean;
|
||||
@@ -35,7 +41,7 @@
|
||||
additionally, update the page location/url with the asset as the asset-grid is scrolled */
|
||||
enableRouting: boolean;
|
||||
assetStore: AssetStore;
|
||||
assetInteraction: AssetInteraction;
|
||||
assetInteraction: AssetInteraction<TimelineAsset>;
|
||||
removeAction?: AssetAction.UNARCHIVE | AssetAction.ARCHIVE | AssetAction.FAVORITE | AssetAction.UNFAVORITE | null;
|
||||
withStacked?: boolean;
|
||||
showArchiveIcon?: boolean;
|
||||
@@ -43,7 +49,7 @@
|
||||
album?: AlbumResponseDto | null;
|
||||
person?: PersonResponseDto | null;
|
||||
isShowDeleteConfirmation?: boolean;
|
||||
onSelect?: (asset: AssetResponseDto) => void;
|
||||
onSelect?: (asset: TimelineAsset) => void;
|
||||
onEscape?: () => void;
|
||||
children?: Snippet;
|
||||
empty?: Snippet;
|
||||
@@ -352,7 +358,7 @@
|
||||
}
|
||||
};
|
||||
|
||||
const handleSelectAsset = (asset: AssetResponseDto) => {
|
||||
const handleSelectAsset = (asset: TimelineAsset) => {
|
||||
if (!assetStore.albumAssets.has(asset.id)) {
|
||||
assetInteraction.selectAsset(asset);
|
||||
}
|
||||
@@ -363,7 +369,8 @@
|
||||
|
||||
if (previousAsset) {
|
||||
const preloadAsset = await assetStore.getPreviousAsset(previousAsset);
|
||||
assetViewingStore.setAsset(previousAsset, preloadAsset ? [preloadAsset] : []);
|
||||
const asset = await getAssetInfo({ id: previousAsset.id });
|
||||
assetViewingStore.setAsset(asset, preloadAsset ? [preloadAsset] : []);
|
||||
await navigate({ targetRoute: 'current', assetId: previousAsset.id });
|
||||
}
|
||||
|
||||
@@ -375,7 +382,8 @@
|
||||
|
||||
if (nextAsset) {
|
||||
const preloadAsset = await assetStore.getNextAsset(nextAsset);
|
||||
assetViewingStore.setAsset(nextAsset, preloadAsset ? [preloadAsset] : []);
|
||||
const asset = await getAssetInfo({ id: nextAsset.id });
|
||||
assetViewingStore.setAsset(asset, preloadAsset ? [preloadAsset] : []);
|
||||
await navigate({ targetRoute: 'current', assetId: nextAsset.id });
|
||||
}
|
||||
|
||||
@@ -387,14 +395,14 @@
|
||||
|
||||
if (randomAsset) {
|
||||
const preloadAsset = await assetStore.getNextAsset(randomAsset);
|
||||
assetViewingStore.setAsset(randomAsset, preloadAsset ? [preloadAsset] : []);
|
||||
const asset = await getAssetInfo({ id: randomAsset.id });
|
||||
assetViewingStore.setAsset(asset, preloadAsset ? [preloadAsset] : []);
|
||||
await navigate({ targetRoute: 'current', assetId: randomAsset.id });
|
||||
return asset;
|
||||
}
|
||||
|
||||
return randomAsset;
|
||||
};
|
||||
|
||||
const handleClose = async ({ asset }: { asset: AssetResponseDto }) => {
|
||||
const handleClose = async (asset: { id: string }) => {
|
||||
assetViewingStore.showAssetViewer(false);
|
||||
showSkeleton = true;
|
||||
$gridScrollTarget = { at: asset.id };
|
||||
@@ -410,7 +418,7 @@
|
||||
case AssetAction.ARCHIVE: {
|
||||
// find the next asset to show or close the viewer
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
||||
(await handleNext()) || (await handlePrevious()) || (await handleClose({ asset: action.asset }));
|
||||
(await handleNext()) || (await handlePrevious()) || (await handleClose(action.asset));
|
||||
|
||||
// delete after find the next one
|
||||
assetStore.removeAssets([action.asset.id]);
|
||||
@@ -439,7 +447,7 @@
|
||||
}
|
||||
};
|
||||
|
||||
let lastAssetMouseEvent: AssetResponseDto | null = $state(null);
|
||||
let lastAssetMouseEvent: TimelineAsset | null = $state(null);
|
||||
|
||||
let shiftKeyIsDown = $state(false);
|
||||
|
||||
@@ -469,14 +477,14 @@
|
||||
}
|
||||
};
|
||||
|
||||
const handleSelectAssetCandidates = (asset: AssetResponseDto | null) => {
|
||||
const handleSelectAssetCandidates = (asset: TimelineAsset | null) => {
|
||||
if (asset) {
|
||||
selectAssetCandidates(asset);
|
||||
}
|
||||
lastAssetMouseEvent = asset;
|
||||
};
|
||||
|
||||
const handleGroupSelect = (assetStore: AssetStore, group: string, assets: AssetResponseDto[]) => {
|
||||
const handleGroupSelect = (assetStore: AssetStore, group: string, assets: TimelineAsset[]) => {
|
||||
if (assetInteraction.selectedGroup.has(group)) {
|
||||
assetInteraction.removeGroupFromMultiselectGroup(group);
|
||||
for (const asset of assets) {
|
||||
@@ -496,7 +504,7 @@
|
||||
}
|
||||
};
|
||||
|
||||
const handleSelectAssets = async (asset: AssetResponseDto) => {
|
||||
const handleSelectAssets = async (asset: TimelineAsset) => {
|
||||
if (!asset) {
|
||||
return;
|
||||
}
|
||||
@@ -579,7 +587,7 @@
|
||||
assetInteraction.setAssetSelectionStart(deselect ? null : asset);
|
||||
};
|
||||
|
||||
const selectAssetCandidates = (endAsset: AssetResponseDto) => {
|
||||
const selectAssetCandidates = (endAsset: TimelineAsset) => {
|
||||
if (!shiftKeyIsDown) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
|
||||
export interface AssetControlContext {
|
||||
// Wrap assets in a function, because context isn't reactive.
|
||||
getAssets: () => AssetResponseDto[]; // All assets includes partners' assets
|
||||
getOwnedAssets: () => AssetResponseDto[]; // Only assets owned by the user
|
||||
getAssets: () => BaseInteractionAsset[]; // All assets includes partners' assets
|
||||
getOwnedAssets: () => BaseInteractionAsset[]; // Only assets owned by the user
|
||||
clearSelect: () => void;
|
||||
}
|
||||
|
||||
@@ -14,13 +14,13 @@
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import type { AssetResponseDto } from '@immich/sdk';
|
||||
import type { BaseInteractionAsset } from '$lib/stores/asset-interaction.svelte';
|
||||
import { mdiClose } from '@mdi/js';
|
||||
import ControlAppBar from '../shared-components/control-app-bar.svelte';
|
||||
import type { Snippet } from 'svelte';
|
||||
import ControlAppBar from '../shared-components/control-app-bar.svelte';
|
||||
|
||||
interface Props {
|
||||
assets: AssetResponseDto[];
|
||||
assets: BaseInteractionAsset[];
|
||||
clearSelect: () => void;
|
||||
ownerId?: string | undefined;
|
||||
children?: Snippet;
|
||||
|
||||
Reference in New Issue
Block a user