diff --git a/web/src/lib/components/layouts/user-page-layout.svelte b/web/src/lib/components/layouts/user-page-layout.svelte index 70e17792e0..7f40bf7a6d 100644 --- a/web/src/lib/components/layouts/user-page-layout.svelte +++ b/web/src/lib/components/layouts/user-page-layout.svelte @@ -49,7 +49,7 @@
diff --git a/web/src/lib/components/search/SearchResults.svelte b/web/src/lib/components/search/SearchResults.svelte new file mode 100644 index 0000000000..3a93d8ba2b --- /dev/null +++ b/web/src/lib/components/search/SearchResults.svelte @@ -0,0 +1,91 @@ + + + + {#snippet assetViewer({ onViewerClose })} + + {/snippet} + + {@render children?.()} + + {#snippet skeleton({ segment })} + + {/snippet} + + {#snippet segment({ segment, onScrollCompensationMonthInDOM })} + + {#snippet content({ onAssetOpen, onAssetSelect, onAssetHover })} + + {#snippet thumbnail({ asset, position })} + {@const isAssetSelectionCandidate = assetInteraction.hasSelectionCandidate(asset.id)} + {@const isAssetSelected = assetInteraction.hasSelectedAsset(asset.id)} + onAssetOpen(asset)} + onSelect={() => onAssetSelect(asset)} + onMouseEvent={() => onAssetHover(asset)} + selected={isAssetSelected} + selectionCandidate={isAssetSelectionCandidate} + thumbnailWidth={position.width} + thumbnailHeight={position.height} + /> + {/snippet} + + {/snippet} + + {/snippet} + + diff --git a/web/src/lib/components/search/SearchResultsAssetViewer.svelte b/web/src/lib/components/search/SearchResultsAssetViewer.svelte new file mode 100644 index 0000000000..28fa477efb --- /dev/null +++ b/web/src/lib/components/search/SearchResultsAssetViewer.svelte @@ -0,0 +1,76 @@ + + +{#await import('../asset-viewer/asset-viewer.svelte') then { default: AssetViewer }} + +{/await} diff --git a/web/src/lib/components/timeline/Photostream.svelte b/web/src/lib/components/timeline/Photostream.svelte index c5777df308..a29138db61 100644 --- a/web/src/lib/components/timeline/Photostream.svelte +++ b/web/src/lib/components/timeline/Photostream.svelte @@ -23,6 +23,7 @@ [ { segment: PhotostreamSegment; + stylePaddingHorizontalPx: number; }, ] >; @@ -37,7 +38,6 @@ alwaysShowScrollbar?: boolean; showSkeleton?: boolean; isShowDeleteConfirmation?: boolean; - styleMarginRightOverride?: string; header?: Snippet<[scrollToFunction: (top: number) => void]>; children?: Snippet; @@ -53,8 +53,9 @@ rowHeight: number; headerHeight: number; }; - styleMarginContentHorizontal?: string; - styleMarginTop?: string; + stylePaddingHorizontalPx?: number; + styleMarginTopPx?: number; + styleMarginRightPx?: number; } let { @@ -64,9 +65,9 @@ timelineManager = $bindable(), showSkeleton = $bindable(true), showScrollbar, - styleMarginRightOverride, - styleMarginContentHorizontal = '0px', - styleMarginTop = '0px', + styleMarginRightPx = 0, + stylePaddingHorizontalPx = 0, + styleMarginTopPx = 0, alwaysShowScrollbar, isShowDeleteConfirmation = $bindable(false), @@ -221,23 +222,26 @@ { 'm-0': isEmpty }, { 'ms-0': !isEmpty }, ]} - style:height={`calc(100% - ${styleMarginTop})`} - style:margin-top={styleMarginTop} - style:margin-right={styleMarginRightOverride} + style:height={`calc(100% - ${styleMarginTopPx}px)`} + style:margin-top={styleMarginTopPx + 'px'} + style:margin-right={styleMarginRightPx + 'px'} + style:padding-left={stylePaddingHorizontalPx + 'px'} + style:padding-right={stylePaddingHorizontalPx + 'px'} style:scrollbar-width={showScrollbar ? 'thin' : 'none'} tabindex="-1" bind:clientHeight={timelineManager.viewportHeight} + bind:clientWidth={ + null, (v: number) => ((timelineManager.viewportWidth = v - stylePaddingHorizontalPx * 2), updateSlidingWindow()) + } bind:this={element} onscroll={() => (handleTimelineScroll(), updateSlidingWindow(), updateIsScrolling())} >
((timelineManager.viewportWidth = v), updateSlidingWindow())} >
- {#each timelineManager.months as monthGroup (monthGroup.id)} {@const shouldDisplay = monthGroup.intersecting && monthGroup.isLoaded} {@const absoluteHeight = monthGroup.top} @@ -266,7 +269,7 @@ style:width="100%" > {#if !shouldDisplay} - {@render skeleton({ segment: monthGroup })} + {@render skeleton({ segment: monthGroup, stylePaddingHorizontalPx })} {:else} {@render segment({ segment: monthGroup, diff --git a/web/src/lib/components/timeline/PhotostreamWithScrubber.svelte b/web/src/lib/components/timeline/PhotostreamWithScrubber.svelte index c9de357c47..9bfd797c04 100644 --- a/web/src/lib/components/timeline/PhotostreamWithScrubber.svelte +++ b/web/src/lib/components/timeline/PhotostreamWithScrubber.svelte @@ -172,7 +172,7 @@ {timelineManager} {showSkeleton} {isShowDeleteConfirmation} - styleMarginRightOverride={scrubberWidth + 'px'} + styleMarginRightPx={scrubberWidth} {handleTimelineScroll} {segment} {skeleton} diff --git a/web/src/lib/components/timeline/actions/ArchiveAction.svelte b/web/src/lib/components/timeline/actions/ArchiveAction.svelte index 7dea81076f..7bd1b57908 100644 --- a/web/src/lib/components/timeline/actions/ArchiveAction.svelte +++ b/web/src/lib/components/timeline/actions/ArchiveAction.svelte @@ -14,9 +14,10 @@ menuItem?: boolean; unarchive?: boolean; manager?: PhotostreamManager; + removeOnArchive?: boolean; } - let { onArchive, menuItem = false, unarchive = false, manager }: Props = $props(); + let { onArchive, menuItem = false, unarchive = false, manager, removeOnArchive }: Props = $props(); let text = $derived(unarchive ? $t('unarchive') : $t('to_archive')); let icon = $derived(unarchive ? mdiArchiveArrowUpOutline : mdiArchiveArrowDownOutline); @@ -31,7 +32,12 @@ loading = true; const ids = await archiveAssets(assets, visibility as AssetVisibility); if (ids) { - manager?.updateAssetOperation(ids, (asset) => ((asset.visibility = visibility), void 0)); + manager?.updateAssetOperation(ids, (asset) => { + asset.visibility = visibility; + return { + remove: removeOnArchive, + }; + }); onArchive?.(ids, visibility ? AssetVisibility.Archive : AssetVisibility.Timeline); clearSelect(); } diff --git a/web/src/lib/components/timeline/actions/DeleteAssetsAction.svelte b/web/src/lib/components/timeline/actions/DeleteAssetsAction.svelte index 4ecef2bd14..8d813e0bf4 100644 --- a/web/src/lib/components/timeline/actions/DeleteAssetsAction.svelte +++ b/web/src/lib/components/timeline/actions/DeleteAssetsAction.svelte @@ -41,9 +41,11 @@ const assets = [...getOwnedAssets()]; const undo = (assets: TimelineAsset[]) => { manager?.upsertAssets(assets); + manager?.order(assetOrdering ?? []); onUndoDelete?.(assets); }; await deleteAssets(force, onAssetDelete, assets, undo); + const assetOrdering = manager?.assets.map((asset) => asset.id); manager?.removeAssets(assets.map((asset) => asset.id)); clearSelect(); isShowConfirmation = false; diff --git a/web/src/lib/elements/Skeleton.svelte b/web/src/lib/elements/Skeleton.svelte index 8ee05f4e61..ccaf2628bd 100644 --- a/web/src/lib/elements/Skeleton.svelte +++ b/web/src/lib/elements/Skeleton.svelte @@ -2,12 +2,13 @@ interface Props { height: number; title?: string; + stylePaddingHorizontalPx?: number; } - let { height = 0, title }: Props = $props(); + let { height = 0, title, stylePaddingHorizontalPx = 0 }: Props = $props(); -
+ {#if title}
{/if}
-
+