feat(electrobun): ProjectWizard — 3-step project creation with 5 source types
Step 1 — Source: local folder (path browser + validation), git clone, GitHub URL, template (4 built-in), remote SSH Step 2 — Configure: name, branch selector, worktree toggle, group, icon, shell Step 3 — Agent: provider, model, permission mode, system prompt, auto-start - ProjectWizard.svelte: 3-step wizard with display toggle (rule 55) - PathBrowser.svelte: inline directory browser with breadcrumbs + shortcuts - git-handlers.ts: git.branches + git.clone RPC handlers - files.statEx RPC: path validation + git detection + writable check - 39 new i18n keys, 172 total TranslationKey entries - App.svelte: wizard overlay replaces simple add-project card
This commit is contained in:
parent
1d2975b07b
commit
45bca3b96f
9 changed files with 1203 additions and 45 deletions
|
|
@ -8,6 +8,7 @@
|
|||
import StatusBar from './StatusBar.svelte';
|
||||
import SearchOverlay from './SearchOverlay.svelte';
|
||||
import SplashScreen from './SplashScreen.svelte';
|
||||
import ProjectWizard from './ProjectWizard.svelte';
|
||||
import { themeStore } from './theme-store.svelte.ts';
|
||||
import { fontStore } from './font-store.svelte.ts';
|
||||
import { keybindingStore } from './keybinding-store.svelte.ts';
|
||||
|
|
@ -71,34 +72,37 @@
|
|||
]);
|
||||
|
||||
// ── Add/Remove project UI state ──────────────────────────────────
|
||||
let showAddProject = $state(false);
|
||||
let newProjectName = $state('');
|
||||
let newProjectCwd = $state('');
|
||||
let showWizard = $state(false);
|
||||
let projectToDelete = $state<string | null>(null);
|
||||
|
||||
async function addProject() {
|
||||
const name = newProjectName.trim();
|
||||
const cwd = newProjectCwd.trim();
|
||||
if (!name || !cwd) return;
|
||||
|
||||
const id = `p-${Date.now()}`;
|
||||
function handleWizardCreated(result: {
|
||||
id: string; name: string; cwd: string; provider?: string; model?: string;
|
||||
systemPrompt?: string; autoStart?: boolean; groupId?: string;
|
||||
useWorktrees?: boolean; shell?: string; icon?: string;
|
||||
}) {
|
||||
const accent = ACCENTS[PROJECTS.length % ACCENTS.length];
|
||||
const project: Project = {
|
||||
id, name, cwd, accent,
|
||||
status: 'idle', costUsd: 0, tokens: 0, messages: [],
|
||||
provider: 'claude', groupId: activeGroupId,
|
||||
id: result.id,
|
||||
name: result.name,
|
||||
cwd: result.cwd,
|
||||
accent,
|
||||
status: 'idle',
|
||||
costUsd: 0,
|
||||
tokens: 0,
|
||||
messages: [],
|
||||
provider: result.provider ?? 'claude',
|
||||
model: result.model,
|
||||
groupId: result.groupId ?? activeGroupId,
|
||||
};
|
||||
PROJECTS = [...PROJECTS, project];
|
||||
trackProject(id);
|
||||
trackProject(project.id);
|
||||
|
||||
await appRpc.request['settings.setProject']({
|
||||
id,
|
||||
config: JSON.stringify(project),
|
||||
appRpc.request['settings.setProject']({
|
||||
id: project.id,
|
||||
config: JSON.stringify({ ...project, ...result }),
|
||||
}).catch(console.error);
|
||||
|
||||
showAddProject = false;
|
||||
newProjectName = '';
|
||||
newProjectCwd = '';
|
||||
showWizard = false;
|
||||
}
|
||||
|
||||
async function confirmDeleteProject() {
|
||||
|
|
@ -357,7 +361,7 @@
|
|||
switch (detail) {
|
||||
case 'settings': settingsOpen = !settingsOpen; break;
|
||||
case 'search': searchOpen = !searchOpen; break;
|
||||
case 'new-project': showAddProject = true; break;
|
||||
case 'new-project': showWizard = true; break;
|
||||
case 'toggle-sidebar': settingsOpen = !settingsOpen; break;
|
||||
default: console.log(`[palette] unhandled command: ${detail}`);
|
||||
}
|
||||
|
|
@ -439,7 +443,7 @@
|
|||
<!-- Add project button -->
|
||||
<button
|
||||
class="sidebar-icon"
|
||||
onclick={() => showAddProject = !showAddProject}
|
||||
onclick={() => showWizard = !showWizard}
|
||||
aria-label="Add project"
|
||||
title="Add project"
|
||||
>
|
||||
|
|
@ -501,28 +505,14 @@
|
|||
<p class="empty-group-text">No projects in {activeGroup?.name ?? 'this group'}</p>
|
||||
</div>
|
||||
|
||||
<!-- Add project card -->
|
||||
<div class="add-card" role="listitem" style:display={showAddProject ? 'flex' : 'none'}>
|
||||
<div class="add-card-form">
|
||||
<input
|
||||
class="add-input"
|
||||
type="text"
|
||||
placeholder="Project name"
|
||||
bind:value={newProjectName}
|
||||
onkeydown={(e) => { if (e.key === 'Enter') addProject(); if (e.key === 'Escape') showAddProject = false; }}
|
||||
/>
|
||||
<input
|
||||
class="add-input"
|
||||
type="text"
|
||||
placeholder="Working directory (e.g. ~/code/myproject)"
|
||||
bind:value={newProjectCwd}
|
||||
onkeydown={(e) => { if (e.key === 'Enter') addProject(); if (e.key === 'Escape') showAddProject = false; }}
|
||||
/>
|
||||
<div class="add-card-actions">
|
||||
<button class="add-cancel" onclick={() => showAddProject = false}>Cancel</button>
|
||||
<button class="add-confirm" onclick={addProject}>Add</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Project wizard overlay (display toggle) -->
|
||||
<div style:display={showWizard ? 'contents' : 'none'}>
|
||||
<ProjectWizard
|
||||
onClose={() => showWizard = false}
|
||||
onCreated={handleWizardCreated}
|
||||
groupId={activeGroupId}
|
||||
groups={groups.map(g => ({ id: g.id, name: g.name }))}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Delete project confirmation -->
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue