mirror of
https://github.com/awizemann/scarf.git
synced 2026-05-10 18:44:45 +00:00
b34f432f00
Adds the user-facing side of v2.3 template configuration. Install-time flow: templates with a non-empty config.schema get a Configure step between the parent-directory pick and the preview sheet. Post-install flow: a Configuration button on the dashboard header + a context-menu entry on the project list opens the same form pre-filled with current values. New files: - Features/Templates/ViewModels/TemplateConfigViewModel.swift — drives the form. Keeps freshly-entered secret bytes in `pendingSecrets` in-memory until commit() succeeds, then calls ProjectConfigService.storeSecret for each one. Cancelling never leaves orphan Keychain entries — the form is transactional. Validates via ProjectConfigService.validateValues on commit and populates per-field `errors` the sheet surfaces inline. Two modes: .install (needs a project passed at commit time) and .edit(project:) (VM already holds the target). - Features/Templates/Views/TemplateConfigSheet.swift — the form. One row per field with a control dispatched by type: TextField (string), TextEditor (text), number input, Toggle (bool), segmented/dropdown Picker (enum, picks form by option count), add/remove list editor, SecureField with show/hide toggle (secret). Required-field asterisk + per-field error display. Optional modelRecommendation panel at the bottom — informational badge; no auto-switch. - Features/Templates/ViewModels/TemplateConfigEditorViewModel.swift — loads <project>/.scarf/manifest.json + config.json, hands a TemplateConfigViewModel to the sheet, writes edited values back on commit. Has a .notConfigurable stage for projects without a manifest cache (hand-added projects, schema-less templates). - Features/Templates/Views/ConfigEditorSheet.swift — thin wrapper that owns the editor VM and routes its stages to loading / form / saving / success / error / not-configurable views. Wiring: - TemplateInstallerViewModel gains an .awaitingConfig stage between .awaitingParentDirectory and .planned. pickParentDirectory() now inspects plan.configSchema and either routes to .awaitingConfig (non-empty schema) or straight to .planned (schema-less). New submitConfig(values:) stashes finalized values in plan.configValues and advances; cancelConfig() returns to .awaitingParentDirectory. - TemplateInstallSheet renders a new `configureView` that inlines TemplateConfigSheet into the install flow for .awaitingConfig. The existing preview (.planned) gains a new "Configuration" section listing each field + its display value (secrets shown as "•••••• (Keychain)", lists shown as "first + N more", "(not set)" for missing values). - ProjectsView adds an isConfigurable(_:) check (transport.fileExists on .scarf/manifest.json), a new @State configEditorProject for sheet presentation, a new "Configuration…" context-menu entry on project list rows (for configurable projects), and a new slider.horizontal.3 button on the dashboard header next to the existing Uninstall button. 50/50 tests still pass. This commit is UI-only — no new Phase C tests (sheet behaviour is hard to unit-test without UI automation and the underlying VM logic is exercised by Phase A/B's config-round-trip tests). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>