diff --git a/web/src/lib/components/settings-popover/SettingsPopover.svelte b/web/src/lib/components/settings-popover/SettingsPopover.svelte index b7d7af0..4b733d2 100644 --- a/web/src/lib/components/settings-popover/SettingsPopover.svelte +++ b/web/src/lib/components/settings-popover/SettingsPopover.svelte @@ -3,10 +3,11 @@ -{#snippet themeItem(theme: string)} - {@const labelId = useId()} - {@const itemId = useId()} +{#snippet item(value: string)} + {@const labelId = `${uid}-${value}-label`} + {@const itemId = `${uid}-${value}-item`} @@ -22,12 +29,12 @@ {/if} {/snippet} - {capitalizeFirstLetter(theme)} + {capitalizeFirstLetter(value)} {/snippet} - - {@render themeItem("light")} - {@render themeItem("dark")} - {@render themeItem("auto")} + + {#each values as value (value)} + {@render item(value)} + {/each} diff --git a/web/src/lib/diff-viewer-multi-file.svelte.ts b/web/src/lib/diff-viewer-multi-file.svelte.ts index 78afdf4..bcf55fb 100644 --- a/web/src/lib/diff-viewer-multi-file.svelte.ts +++ b/web/src/lib/diff-viewer-multi-file.svelte.ts @@ -26,6 +26,8 @@ import { VList } from "virtua/svelte"; import { Context, Debounced } from "runed"; import { MediaQuery } from "svelte/reactivity"; +export type SidebarLocation = "left" | "right"; + export class GlobalOptions { private static readonly localStorageKey = "diff-viewer-global-options"; private static readonly context = new Context(GlobalOptions.localStorageKey); @@ -54,6 +56,8 @@ export class GlobalOptions { wordDiffs = $state(true); lineWrap = $state(true); omitPatchHeaderOnlyHunks = $state(true); + // TODO: send to server (use cookie?) to that the initial position is correct + sidebarLocation: SidebarLocation = $state("left"); private constructor() { $effect(() => { @@ -90,6 +94,7 @@ export class GlobalOptions { omitPatchHeaderOnlyHunks: this.omitPatchHeaderOnlyHunks, wordDiff: this.wordDiffs, lineWrap: this.lineWrap, + sidebarLocation: this.sidebarLocation, }; if (this.syntaxHighlightingThemeLight !== DEFAULT_THEME_LIGHT) { cereal.syntaxHighlightingThemeLight = this.syntaxHighlightingThemeLight; @@ -124,6 +129,9 @@ export class GlobalOptions { if (jsonObject.lineWrap !== undefined) { this.lineWrap = jsonObject.lineWrap; } + if (jsonObject.sidebarLocation !== undefined) { + this.sidebarLocation = jsonObject.sidebarLocation; + } } } diff --git a/web/src/routes/+page.svelte b/web/src/routes/+page.svelte index a86f3b5..2af7b09 100644 --- a/web/src/routes/+page.svelte +++ b/web/src/routes/+page.svelte @@ -20,6 +20,7 @@ import SettingsPopoverGroup from "$lib/components/settings-popover/SettingsPopoverGroup.svelte"; import LabeledCheckbox from "$lib/components/LabeledCheckbox.svelte"; import ShikiThemeSelector from "$lib/components/settings-popover/ShikiThemeSelector.svelte"; + import SimpleRadioGroup from "$lib/components/settings-popover/SimpleRadioGroup.svelte"; import DiffSearch from "./DiffSearch.svelte"; import FileHeader from "./FileHeader.svelte"; import DiffTitle from "./DiffTitle.svelte"; @@ -28,8 +29,9 @@ import ActionsPopover from "./ActionsPopover.svelte"; import LoadDiffDialog from "./LoadDiffDialog.svelte"; import InfoPopup from "./InfoPopup.svelte"; - import { Button } from "bits-ui"; + import { Button, Label } from "bits-ui"; import { onClickOutside } from "runed"; + import SidebarToggle from "./SidebarToggle.svelte"; const globalOptions = GlobalOptions.init(); const viewer = MultiFileDiffViewerState.init(); @@ -37,7 +39,11 @@ onClickOutside( () => sidebarElement, - () => { + (e) => { + if (e.target instanceof HTMLElement && e.target.closest("[data-sidebar-toggle]")) { + // Ignore toggle button clicks + return; + } if (!staticSidebar.current) { viewer.sidebarCollapsed = true; } @@ -104,21 +110,6 @@ /> -{#snippet sidebarToggle()} - -{/snippet} - {#snippet settingsPopover()} {@render globalThemeSetting()} @@ -131,6 +122,15 @@ +
+ Sidebar location + +
{/snippet} @@ -138,7 +138,12 @@
@@ -159,9 +164,7 @@ > {/if}
-
- {@render sidebarToggle()} -
+
{#if viewer.filteredFileDetails.length !== viewer.fileDetails.length}
@@ -233,8 +236,8 @@
-
-
+
+
{#if viewer.diffMetadata !== null} {/if} @@ -276,8 +279,8 @@
-
- {@render sidebarToggle()} +
+ {#await viewer.stats} {:then stats} @@ -285,7 +288,7 @@ {/await}
-
+
i} bind:this={viewer.vlist} overscan={3}> {#snippet children(value, index)} {@const lines = viewer.diffText[index] !== undefined ? viewer.diffText[index] : null} diff --git a/web/src/routes/SidebarToggle.svelte b/web/src/routes/SidebarToggle.svelte new file mode 100644 index 0000000..f632e45 --- /dev/null +++ b/web/src/routes/SidebarToggle.svelte @@ -0,0 +1,35 @@ + + + (viewer.sidebarCollapsed = !viewer.sidebarCollapsed)} + data-sidebar-toggle + {...mergedProps} +> + +