From a2ff2e5da8326dcbe065b72a85cf9d5ec2f6b336 Mon Sep 17 00:00:00 2001 From: Zaida-3dO Date: Sun, 18 Jan 2026 07:27:57 +0000 Subject: [PATCH 1/4] Improve splitview pairing and pass clientIdentifier on asset requests - Pass clientIdentifier to getAsset() for better logging/tracking - Add selectAssetsForDisplay() to look ahead 3 images when pairing - Skip lone horizontal images by checking if 2nd or 3rd can pair - Extract removeAtIndices() helper for cleaner array manipulation --- .../lib/components/home-page/home-page.svelte | 80 +++++++++++++------ 1 file changed, 55 insertions(+), 25 deletions(-) diff --git a/immichFrame.Web/src/lib/components/home-page/home-page.svelte b/immichFrame.Web/src/lib/components/home-page/home-page.svelte index e1082981..1fd24ab8 100644 --- a/immichFrame.Web/src/lib/components/home-page/home-page.svelte +++ b/immichFrame.Web/src/lib/components/home-page/home-page.svelte @@ -118,7 +118,7 @@ async function loadAssets() { try { - let assetRequest = await api.getAsset(); + let assetRequest = await api.getAsset({ clientIdentifier: $clientIdentifierStore }); if (assetRequest.status != 200) { if (assetRequest.status == 401) { @@ -154,18 +154,10 @@ return; } - let next: api.AssetResponseDto[]; - if ( - $configStore.layout?.trim().toLowerCase() == 'splitview' && - assetBacklog.length > 1 && - isHorizontal(assetBacklog[0]) && - isHorizontal(assetBacklog[1]) - ) { - next = assetBacklog.splice(0, 2); - } else { - next = assetBacklog.splice(0, 1); - } - assetBacklog = [...assetBacklog]; + const candidates = assetBacklog.slice(0, 3); + const selectedIndices = selectAssetsForDisplay($configStore.layout, candidates); + const next = selectedIndices.map((i) => assetBacklog[i]); + assetBacklog = removeAtIndices(assetBacklog, selectedIndices); if (displayingAssets) { // Push to History @@ -187,19 +179,16 @@ return; } - let next: api.AssetResponseDto[]; - if ( - $configStore.layout?.trim().toLowerCase() == 'splitview' && - assetHistory.length > 1 && - isHorizontal(assetHistory[assetHistory.length - 1]) && - isHorizontal(assetHistory[assetHistory.length - 2]) - ) { - next = assetHistory.splice(assetHistory.length - 2, 2); - } else { - next = assetHistory.splice(assetHistory.length - 1, 1); - } + // get up to 3 candidates from the end of history, reversed for selection logic + const historyLength = assetHistory.length; + const candidateCount = Math.min(3, historyLength); + const candidates = assetHistory.slice(historyLength - candidateCount).reverse(); + const selectedIndices = selectAssetsForDisplay($configStore.layout, candidates); - assetHistory = [...assetHistory]; + // convert indices back to history positions + const historyIndices = selectedIndices.map((i) => historyLength - 1 - i); + const next = historyIndices.map((i) => assetHistory[i]); + assetHistory = removeAtIndices(assetHistory, historyIndices); // Unshift to Backlog if (displayingAssets) { @@ -220,6 +209,47 @@ return imageHeight > imageWidth; // or imageHeight > imageWidth * 1.25; } + function removeAtIndices(arr: T[], indicesToRemove: number[]): T[] { + const skipSet = new Set(indicesToRemove); + return arr.filter((_, i) => !skipSet.has(i)); + } + + // Selects which assets to display based on layout and orientation + // For splitview, tries to pair horizontal images together + function selectAssetsForDisplay(layout: string | undefined, candidates: api.AssetResponseDto[]): number[] { + if (candidates.length < 1) { + return []; + } + if (candidates.length === 1 || layout?.trim().toLowerCase() !== 'splitview') { + return [0]; + } + + const h0 = isHorizontal(candidates[0]); + const h1 = candidates.length > 1 ? isHorizontal(candidates[1]) : false; + const h2 = candidates.length > 2 ? isHorizontal(candidates[2]) : false; + + if (!h0) { + // first image is vertical, show it alone + return [0]; + } + + // pair with second if it's also horizontal + if (candidates.length > 1 && h1) { + return [0, 1]; + } + + // pair with third if it's horizontal (skip non-horizontal second) + if (candidates.length > 2 && h2) { + return [0, 2]; + } + + // no horizontal pair found, show second instead (skip lone horizontal) + if (candidates.length > 1) { + return [1]; + } + return [0]; + } + function hasBirthday(assets: api.AssetResponseDto[]) { let today = new Date(); let hasBday: boolean = false; From 5c9b6aef452cf50e9c96799e2943e7b4cd54f5d9 Mon Sep 17 00:00:00 2001 From: Zaida-3dO Date: Sun, 18 Jan 2026 21:39:33 +0000 Subject: [PATCH 2/4] fix: rename isHorizontal to isPortrait for clarity The function was incorrectly named - it checks if height > width, which means portrait orientation, not horizontal/landscape. Renamed to isPortrait and updated variable names and comments to accurately reflect the behavior. Co-Authored-By: Claude Opus 4.5 --- .../lib/components/home-page/home-page.svelte | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/immichFrame.Web/src/lib/components/home-page/home-page.svelte b/immichFrame.Web/src/lib/components/home-page/home-page.svelte index 1fd24ab8..f4464ad4 100644 --- a/immichFrame.Web/src/lib/components/home-page/home-page.svelte +++ b/immichFrame.Web/src/lib/components/home-page/home-page.svelte @@ -199,7 +199,7 @@ imagesState = await loadImages(next); } - function isHorizontal(asset: api.AssetResponseDto) { + function isPortrait(asset: api.AssetResponseDto) { const isFlipped = (orientation: number) => [5, 6, 7, 8].includes(orientation); let imageHeight = asset.exifInfo?.exifImageHeight ?? 0; let imageWidth = asset.exifInfo?.exifImageWidth ?? 0; @@ -215,7 +215,8 @@ } // Selects which assets to display based on layout and orientation - // For splitview, tries to pair horizontal images together + // For splitview, tries to pair portrait images together, to be shown side by side + // Landscape images are shown alone function selectAssetsForDisplay(layout: string | undefined, candidates: api.AssetResponseDto[]): number[] { if (candidates.length < 1) { return []; @@ -224,27 +225,30 @@ return [0]; } - const h0 = isHorizontal(candidates[0]); - const h1 = candidates.length > 1 ? isHorizontal(candidates[1]) : false; - const h2 = candidates.length > 2 ? isHorizontal(candidates[2]) : false; + const isImage0Portrait = isPortrait(candidates[0]); + const isImage1Portrait = candidates.length > 1 ? isPortrait(candidates[1]) : false; + const isImage2Portrait = candidates.length > 2 ? isPortrait(candidates[2]) : false; - if (!h0) { - // first image is vertical, show it alone + if (!isImage0Portrait) { + // first image is landscape, show it alone return [0]; } - // pair with second if it's also horizontal - if (candidates.length > 1 && h1) { + + if (candidates.length > 1 && isImage1Portrait) { + // pair with second if it's also portrait return [0, 1]; } - // pair with third if it's horizontal (skip non-horizontal second) - if (candidates.length > 2 && h2) { + + if (candidates.length > 2 && isImage2Portrait) { + // pair with third if it's portrait (skip landscape second) return [0, 2]; } + - // no horizontal pair found, show second instead (skip lone horizontal) - if (candidates.length > 1) { + if (candidates[1] != null) { + // no portrait pair found, show second (landscape) instead return [1]; } return [0]; From 30f5330a61d840067b86ec2f619e2d10a53dd234 Mon Sep 17 00:00:00 2001 From: Zaida-3dO Date: Sun, 18 Jan 2026 21:53:21 +0000 Subject: [PATCH 3/4] chore: add clarifying comments to selectAssetsForDisplay Co-Authored-By: Claude Opus 4.5 --- .../src/lib/components/home-page/home-page.svelte | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/immichFrame.Web/src/lib/components/home-page/home-page.svelte b/immichFrame.Web/src/lib/components/home-page/home-page.svelte index f4464ad4..bebbc98a 100644 --- a/immichFrame.Web/src/lib/components/home-page/home-page.svelte +++ b/immichFrame.Web/src/lib/components/home-page/home-page.svelte @@ -181,8 +181,7 @@ // get up to 3 candidates from the end of history, reversed for selection logic const historyLength = assetHistory.length; - const candidateCount = Math.min(3, historyLength); - const candidates = assetHistory.slice(historyLength - candidateCount).reverse(); + const candidates = assetHistory.slice(historyLength - Math.min(3, historyLength)).reverse(); const selectedIndices = selectAssetsForDisplay($configStore.layout, candidates); // convert indices back to history positions @@ -234,6 +233,7 @@ return [0]; } + // otherwise, first image is portrait if (candidates.length > 1 && isImage1Portrait) { // pair with second if it's also portrait @@ -251,6 +251,8 @@ // no portrait pair found, show second (landscape) instead return [1]; } + + // Unreachable state, but fallback to returning the first image. return [0]; } From 3ece9872c0e9f90eb88d9ceed28bd8164f77b7e8 Mon Sep 17 00:00:00 2001 From: Zaida-3dO Date: Mon, 19 Jan 2026 00:53:37 +0000 Subject: [PATCH 4/4] fix: correct image order when navigating backwards When going back in history, paired images were showing in reversed order. Added .reverse() to restore original display order. Co-Authored-By: Claude Opus 4.5 --- immichFrame.Web/src/lib/components/home-page/home-page.svelte | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/immichFrame.Web/src/lib/components/home-page/home-page.svelte b/immichFrame.Web/src/lib/components/home-page/home-page.svelte index bebbc98a..d11c9bc1 100644 --- a/immichFrame.Web/src/lib/components/home-page/home-page.svelte +++ b/immichFrame.Web/src/lib/components/home-page/home-page.svelte @@ -184,8 +184,8 @@ const candidates = assetHistory.slice(historyLength - Math.min(3, historyLength)).reverse(); const selectedIndices = selectAssetsForDisplay($configStore.layout, candidates); - // convert indices back to history positions - const historyIndices = selectedIndices.map((i) => historyLength - 1 - i); + // convert indices back to history positions and reverse to restore original display order + const historyIndices = selectedIndices.map((i) => historyLength - 1 - i).reverse(); const next = historyIndices.map((i) => assetHistory[i]); assetHistory = removeAtIndices(assetHistory, historyIndices);