From add98f962ebe7f92c2c85695d43d8f0f8c3022a1 Mon Sep 17 00:00:00 2001 From: Christoph Brandau Date: Tue, 1 Sep 2026 21:13:46 +0200 Subject: [PATCH] feat(ui): add init repository dialog Add a modal dialog to initialize a new Git repository, replacing the previous prompt-based flow. It integrates with the app state and invokes the initialization operation then opens the repository on confirmation. Also adds styles, keyboard handling, accessibility hints, a folder browser, initial-branch input, and German/English labels with busy state. - New dialog component with folder picker, branch input, and i18n. - Wire dialog open/close and confirm handler to init and open actions. - Add CSS rules for dialog layout, controls, and error/busy states. --- src/App.svelte | 27 +++- src/app.css | 35 ++++ .../components/InitRepositoryDialog.svelte | 149 ++++++++++++++++++ 3 files changed, 207 insertions(+), 4 deletions(-) create mode 100644 src/lib/components/InitRepositoryDialog.svelte diff --git a/src/App.svelte b/src/App.svelte index d5f5a68..d0df54f 100644 --- a/src/App.svelte +++ b/src/App.svelte @@ -26,6 +26,7 @@ import DiscardConfirmDialog from "./lib/components/DiscardConfirmDialog.svelte"; import ExplorerPanel from "./lib/components/ExplorerPanel.svelte"; import HistoryPanel from "./lib/components/HistoryPanel.svelte"; + import InitRepositoryDialog from "./lib/components/InitRepositoryDialog.svelte"; import NewBranchDialog from "./lib/components/NewBranchDialog.svelte"; import RenameBranchDialog from "./lib/components/RenameBranchDialog.svelte"; import ReflogDialog from "./lib/components/ReflogDialog.svelte"; @@ -313,6 +314,7 @@ let repoStatusCache: Record = {}; let repoSearch = ""; let cloneDialogOpen = false; + let initRepositoryDialogOpen = false; let pullStrategy: PullStrategy = (localStorage.getItem("gitlite.pullStrategy") as PullStrategy) || "merge"; let selectedRemote = localStorage.getItem("gitlite.selectedRemote") || ""; let remoteActionForceWithLease = false; @@ -3926,10 +3928,17 @@ } async function initializeRepository() { - const selected = await openDialog({ directory: true, multiple: false, title: "Choose an empty or existing folder" }); - if (typeof selected !== "string") return; - const branch = window.prompt("Initial branch name", "main")?.trim(); if (!branch) return; - await runOperation("Initializing repository", async () => { await initRepository(selected, branch); await openRepo(selected); }); + initRepositoryDialogOpen = true; + } + + async function confirmInitializeRepository(path: string, branch: string) { + const selected = path.trim(); + if (!selected) return; + await runOperation("Initializing repository", async () => { + await initRepository(selected, branch); + initRepositoryDialogOpen = false; + await openRepo(selected); + }); } async function revertHistoryCommit(commit: GitCommit) { @@ -6090,6 +6099,16 @@ /> {/if} + +{#if initRepositoryDialogOpen} + { if (!isBusy) initRepositoryDialogOpen = false; }} + /> +{/if} + {#if openingRepo} diff --git a/src/app.css b/src/app.css index f3453f3..6e6b864 100644 --- a/src/app.css +++ b/src/app.css @@ -3878,6 +3878,13 @@ max-height: calc(100vh - 32px); overflow: auto; } + .init-repository-dialog { + display: block; + width: min(540px, calc(100vw - 32px)); + height: auto; + max-height: calc(100vh - 32px); + overflow: auto; + } .rename-branch-dialog { display: block; width: min(520px, calc(100vw - 32px)); @@ -4172,6 +4179,34 @@ gap: 14px; padding: 16px; } + .init-repository-header { padding: 16px 18px; } + .init-repository-heading { display: flex; align-items: center; gap: 12px; } + .init-repository-heading h2 { margin: 2px 0 0; color: var(--color-ink); font-size: 15px; line-height: 1.25; } + .init-repository-icon { + display: grid; + place-items: center; + width: 36px; + height: 36px; + flex: 0 0 auto; + border: 1px solid color-mix(in srgb, var(--color-accent) 34%, var(--color-border)); + border-radius: 9px; + color: var(--color-accent); + background: color-mix(in srgb, var(--color-accent) 10%, var(--color-surface-raised)); + } + .init-repository-form { display: flex; flex-direction: column; gap: 16px; padding: 18px; } + .init-repository-description { margin: 0; color: var(--color-ink-dim); font-size: 11.5px; line-height: 1.5; } + .init-repository-field > span { font-size: 9.5px; } + .init-repository-field > div { position: relative; align-items: center; } + .init-repository-field > div > svg { position: absolute; left: 11px; z-index: 1; color: var(--color-ink-faint); pointer-events: none; } + .init-repository-field > div > input { height: 36px; padding-left: 36px; font-family: var(--font-mono); font-size: 12px; } + .init-repository-field small { color: var(--color-ink-faint); font-size: 9.5px; line-height: 1.4; } + .init-repository-path-field { padding: 12px; border: 1px solid var(--color-border-subtle); border-radius: 9px; background: var(--color-surface-raised); } + .init-repository-path-control { display: grid !important; grid-template-columns: minmax(0, 1fr) auto; gap: 8px; } + .init-repository-path-control > input { grid-column: 1; } + .init-repository-browse { grid-column: 2; display: inline-flex; align-items: center; gap: 6px; height: 36px; font-size: 11.5px; white-space: nowrap; } + .init-repository-error { color: var(--color-danger, #ff6b78) !important; } + .init-repository-actions { padding-top: 2px; } + .init-repository-actions > button { font-size: 11.5px; } .rename-branch-form { display: flex; flex-direction: column; diff --git a/src/lib/components/InitRepositoryDialog.svelte b/src/lib/components/InitRepositoryDialog.svelte new file mode 100644 index 0000000..88e67f8 --- /dev/null +++ b/src/lib/components/InitRepositoryDialog.svelte @@ -0,0 +1,149 @@ + + +