feat(builder): view the output as a diff (#787)

This commit is contained in:
bo0tzz
2026-09-04 14:02:30 -04:00
committed by GitHub
parent d8396d0646
commit 8a7b1fee0a
3 changed files with 69 additions and 9 deletions
+2
View File
@@ -19,6 +19,7 @@
"@sveltejs/kit": "^2.55.0",
"@sveltejs/vite-plugin-svelte": "^7.0.0",
"@tailwindcss/vite": "^4.2.2",
"@types/diff": "^8.0.0",
"@types/lodash-es": "^4.17.12",
"@types/luxon": "^3.7.1",
"@types/node": "^24.13.3",
@@ -42,6 +43,7 @@
"@immich/ui": "workspace:*",
"@mdi/js": "^7.4.47",
"deepmerge": "^4.3.1",
"diff": "^9.0.0",
"feed": "^6.0.0",
"front-matter": "^4.0.2",
"lodash-es": "^4.18.1",
@@ -54,9 +54,10 @@
mdiShareVariant,
} from '@mdi/js';
import { siGithub } from 'simple-icons';
import { createTwoFilesPatch } from 'diff';
import { onMount } from 'svelte';
import { SvelteURL } from 'svelte/reactivity';
import { yaml as yamlLanguage } from 'svelte-highlight/languages';
import { diff as diffLanguage, yaml as yamlLanguage } from 'svelte-highlight/languages';
const config = $state(structuredClone(DEFAULT_CONFIG));
const defaultDatabaseLocation =
@@ -74,7 +75,6 @@
});
const compose = $derived(buildCompose(effectiveConfig, version));
const errors = $derived(validate(effectiveConfig));
const hasErrors = $derived(Object.keys(errors).length > 0);
const fields = $derived(buildComposeFields(effectiveConfig, version));
let focusedField = $state<string | undefined>();
@@ -96,6 +96,20 @@
const timezones = Intl.supportedValuesOf('timeZone');
let detectedTimezone = $state('');
let showDiff = $state(false);
const composeDiff = $derived.by(() => {
const baseline = { ...DEFAULT_CONFIG, timezone: detectedTimezone || DEFAULT_CONFIG.timezone };
const patch = createTwoFilesPatch('defaults', 'yours', buildCompose(baseline, majorVersion), compose, '', '', {
context: Number.MAX_SAFE_INTEGER,
});
const body = patch.split('\n').slice(4).join('\n').trimEnd();
// with no changes there is no hunk at all, so show the file as all-context lines
return body || compose.trimEnd().replaceAll(/^/gm, ' ');
});
let decoded = $state(false);
let routerReady = $state(false);
@@ -707,13 +721,37 @@
{#if versionFailed}
<Text color="danger">Could not reach the Immich version service. Reload the page to try again.</Text>
{:else if version}
<CodeBlock
code={compose}
language={yamlLanguage}
lineNumbers
highlightedLines={focusedLines}
copy={!hasErrors}
/>
<div class="relative">
<div
class="absolute inset-e-2 top-2 z-10 flex gap-1 rounded-full border bg-light-50 p-0.5 dark:bg-light-100"
>
<Button
size="tiny"
shape="round"
variant={showDiff ? 'ghost' : 'filled'}
color={showDiff ? 'secondary' : 'primary'}
onclick={() => (showDiff = false)}
>
YAML
</Button>
<Button
size="tiny"
shape="round"
variant={showDiff ? 'filled' : 'ghost'}
color={showDiff ? 'primary' : 'secondary'}
onclick={() => (showDiff = true)}
>
Diff
</Button>
</div>
<CodeBlock
code={showDiff ? composeDiff : compose}
language={showDiff ? diffLanguage : yamlLanguage}
lineNumbers={!showDiff}
highlightedLines={showDiff ? [] : focusedLines}
copy={false}
/>
</div>
{:else}
<LoadingSpinner />
{/if}
+20
View File
@@ -555,6 +555,9 @@ importers:
deepmerge:
specifier: ^4.3.1
version: 4.3.1
diff:
specifier: ^9.0.0
version: 9.0.0
feed:
specifier: ^6.0.0
version: 6.0.0
@@ -598,6 +601,9 @@ importers:
'@tailwindcss/vite':
specifier: ^4.2.2
version: 4.3.3(vite@8.2.2(@types/node@24.13.3)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.23.12)(yaml@2.9.0))
'@types/diff':
specifier: ^8.0.0
version: 8.0.0
'@types/lodash-es':
specifier: ^4.17.12
version: 4.17.12
@@ -2618,6 +2624,10 @@ packages:
'@types/deep-eql@4.0.2':
resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==}
'@types/diff@8.0.0':
resolution: {integrity: sha512-o7jqJM04gfaYrdCecCVMbZhNdG6T1MHg/oQoRFdERLV+4d+V7FijhiEAbFu0Usww84Yijk9yH58U4Jk4HbtzZw==}
deprecated: This is a stub types definition. diff provides its own type definitions, so you do not need this installed.
'@types/docker-modem@3.0.6':
resolution: {integrity: sha512-yKpAGEuKRSS8wwx0joknWxsmLha78wNMe9R2S3UNsVOkZded8UqOrV8KoeDXoXsjndxwyF3eIhyClGbO1SEhEg==}
@@ -3419,6 +3429,10 @@ packages:
devlop@1.1.0:
resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==}
diff@9.0.0:
resolution: {integrity: sha512-svtcdpS8CgJyqAjEQIXdb3OjhFVVYjzGAPO8WGCmRbrml64SPw/jJD4GoE98aR7r25A0XcgrK3F02yw9R/vhQw==}
engines: {node: '>=0.3.1'}
dijkstrajs@1.0.3:
resolution: {integrity: sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==}
@@ -6808,6 +6822,10 @@ snapshots:
'@types/deep-eql@4.0.2': {}
'@types/diff@8.0.0':
dependencies:
diff: 9.0.0
'@types/docker-modem@3.0.6':
dependencies:
'@types/node': 26.4.0
@@ -7612,6 +7630,8 @@ snapshots:
dependencies:
dequal: 2.0.3
diff@9.0.0: {}
dijkstrajs@1.0.3: {}
docker-compose@1.4.2: