Files
ClaudeDo/src/ClaudeDo.Ui/CLAUDE.md

6.9 KiB

ClaudeDo.Ui

Avalonia UI layer: views, viewmodels, converters, and the SignalR client.

Pattern

MVVM with CommunityToolkit.Mvvm source generators:

  • [ObservableProperty] for bindable properties
  • [RelayCommand] for commands (supports async and CanExecute)
  • All ViewModels inherit ViewModelBase (extends ObservableObject)

Views

  • MainWindow — 3-column DockPanel layout (lists | tasks | detail) with GridSplitter, status bar at bottom
  • TaskListView — ListBox of tasks with add/edit/delete toolbar
  • TaskDetailView — Task info, live log output, worktree section (merge/keep/discard)
  • TaskEditorView — Modal dialog for task create/edit
  • ListEditorView — Modal dialog for list create/edit
  • StatusBarView — Connection status indicator, active task display
  • ListSettingsModalView — edits list name, working dir, default commit type, and per-list Model/SystemPrompt/AgentPath/MaxTurns, each showing the inherited (global) value with a source-aware "inherited · Global / override" badge and a reset-to-inherited button; also deletes the list (and its tasks) via a confirmed "Delete list" button. Opened via context menu or gear button on a list row.
  • RepoImportModalView — bulk-creates lists from git repos discovered under chosen parent folders. Opened via the folder button beside "New list" in the Lists island, or the "Add repos as lists…" Help-menu item. Repos already wired to a list show as disabled/"(already added)".
  • DetailsIslandView — contains an "Agent settings (overrides)" expander with per-task Model/MaxTurns/AgentPath (override semantics, each showing the resolved inherited value as a placeholder plus a source-aware "inherited · List / inherited · Global / override" badge and reset button via the reusable InheritedBadge control + InheritanceResolver) and a SystemPrompt text box (additive — shows the inherited prompt as a "prepended automatically" note). Disabled while task is running. When notes mode is active (IsNotesMode), it hosts NotesEditorView instead of the task detail. When prep mode is active (IsPrepMode), it hosts the daily-prep panel (Plan day button, empty-state hint, embedded SessionTerminalView). The task header, metadata footer (delete/close), and AgentStripView are gated on IsTaskDetailVisible — they are hidden in both notes and prep mode.
  • WeeklyReportModalView — opened from Help menu ("Wochenbericht…"); date-range pickers default to "since last standup weekday → today"; Generate/Regenerate button; renders markdown via MarkdownView; reports are cached per range.
  • NotesEditorView — day navigator (prev/next/date-picker/Today), bullet add/edit/delete for daily notes.
  • SessionTerminalView — reusable log terminal; exposes StyledProperties Entries, Label, IsRunning, IsDone, IsFailed. Used for both the task Log and the prep PrepLog.
  • SettingsModalView — Prime Claude tab contains a DailyPrepMaxTasks numeric editor.
  • TasksIslandView (MyDay header) — icon buttons visible only when IsMyDayList: broom icon = ClearDayCommand, stroked-sun icon ("Plan My Day") = ShowPrepLogCommand.

All views use compiled bindings (x:DataType).

ViewModels

  • MainWindowViewModel — root coordinator; manages list collection, selected list, dialog creation via Func<T> factories
  • TaskListViewModel — manages task collection for selected list; handles CRUD, "Run Now"
  • TaskDetailViewModel — displays task details, streams live log, controls worktree operations
  • TaskItemViewModel / ListItemViewModel — lightweight display VMs
  • TaskEditorViewModel / ListEditorViewModel — dialog VMs with validation
  • StatusBarViewModel — connection state and active tasks
  • WeeklyReportModalViewModel — drives the weekly report modal
  • NotesEditorViewModel — manages daily note bullet CRUD for the selected day
  • DetailsIslandViewModel gains IsNotesMode, ShowNotes(), and hosts NotesEditorViewModel. Also gains daily-prep mode: IsPrepMode, PrepLog (ObservableCollection<LogLineViewModel>), ShowPrep(), PlanDayCommand (calls RunDailyPrepNowAsync), ShowPrepEmptyState, and computed IsTaskDetailVisible (= !IsNotesMode && !IsPrepMode). Subscribes to PrepStartedEvent, PrepLineEvent, PrepFinishedEvent; streams lines into PrepLog via StreamLineFormatter (same path as task logs). On open, if log is empty and no run is in progress, loads persisted last run via GetLastPrepLogAsync. The WorkConsole Session tab gains a mergeability indicator (MergePreviewPresenter) and a single-task Merge button; indicator is populated via PreviewMergeAsync and displayed for tasks in WaitingForReview.
  • TasksIslandViewModel gains a pinned "Notes" pseudo-row (ShowNotesRow, OpenNotesCommand, NotesRequested event) that switches the Details island to notes mode. Also gains IsMyDayList (true when selected list is smart:my-day), ShowPrepLogCommand (raises PrepRequested event → shell calls Details.ShowPrep()), and ClearDayCommand (calls ClearMyDayAsync).

Services

  • WorkerClient / IWorkerClient — SignalR client connecting to http://127.0.0.1:47821/hub. Auto-reconnect with exponential backoff. Methods: StartAsync, RunNowAsync, CancelTaskAsync, WakeQueueAsync, ContinueTaskAsync, ResetTaskAsync, GetAgentsAsync, UpdateAppSettingsAsync, UpdateListAsync, UpdateListConfigAsync, GetListConfigAsync, UpdateTaskAgentSettingsAsync, ApproveReviewAsync(taskId, targetBranch) -> MergeResultDto, PreviewMergeAsync(taskId, targetBranch) -> MergePreviewDto, MergeTaskAsync, GetWeekReportAsync, GenerateWeekReportAsync, GetDailyNotesAsync, AddDailyNoteAsync, UpdateDailyNoteAsync, DeleteDailyNoteAsync, RunDailyPrepNowAsync, ClearMyDayAsync, GetLastPrepLogAsync. Events: TaskStarted, TaskFinished, TaskMessage, TaskUpdated, WorktreeUpdated, ListUpdated, PrepStartedEvent, PrepLineEvent, PrepFinishedEvent
  • INotesApi / WorkerNotesApi — thin wrapper over the daily-note WorkerClient methods (mirrors IPrimeScheduleApi). UI DTO: DailyNoteDto(Id, Date, Text, SortOrder).

Converters

  • StatusColorConverter — task status string -> color (Queued=Blue, Running=Orange, Done=Green, Failed=Red, Manual=Gray)
  • ConnectionColorConverter — connection state -> color (Online=Green, Offline=Red)

Dialog Pattern

Editor dialogs use TaskCompletionSource<bool> — the dialog sets the result on save/cancel, and the caller awaits the TCS.

Notes

  • Context menus are on both list items and task items
  • Right-click selects the item before showing the context menu
  • "Run Now" CanExecute re-evaluates when worker connection state changes
  • Icon gotcha: PathIcon fills geometry. Line-art/stroke icons must be defined as filled geometry or rendered as a stroked Path (e.g. Icon.PlanDay via the Path.plan-icon style); a pure stroke path used with PathIcon is invisible.