101 lines
3.9 KiB
Markdown
101 lines
3.9 KiB
Markdown
# APP-3919: Commit Dialog — Tech Spec
|
|
|
|
Product spec: `specs/APP-3919/PRODUCT.md`
|
|
Branch: `edward/commit-dialog`
|
|
|
|
## Relevant Code
|
|
|
|
- `app/src/code_review/commit_dialog.rs` — new file, entire dialog view
|
|
- `app/src/code_review/code_review_view.rs` — `open_commit_dialog`, dialog overlay rendering, action wiring
|
|
- `app/src/util/git.rs` — `get_file_change_entries`, `FileChangeEntry`
|
|
- `app/src/code_review/mod.rs` — module registration
|
|
|
|
## Changes
|
|
|
|
### 1. `CommitDialog` view (`commit_dialog.rs`)
|
|
|
|
New 718-line view implementing the dialog UI. Key types:
|
|
|
|
- `CommitIntent` enum — `CommitOnly` (future: `CommitAndPush`, `CommitAndCreatePr`)
|
|
- `CommitDialogAction` — internal actions: `Cancel`, `Confirm`, `SetIntent`, `ToggleIncludeUnstaged`, `ToggleChangesExpanded`
|
|
- `CommitDialogEvent` — events emitted to parent: `Confirmed { message, intent, include_unstaged }`, `Cancelled`
|
|
|
|
State:
|
|
- `repo_path`, `branch_name` — set at construction
|
|
- `intent: CommitIntent` — which action to take on confirm
|
|
- `include_unstaged: bool` — toggle for staged-only vs all changes (default: true)
|
|
- `file_changes: Vec<FileChangeEntry>` — loaded async on open and on toggle
|
|
- `changes_expanded: bool` — collapsible file list
|
|
- `message_editor: ViewHandle<EditorView>` — commit message input
|
|
|
|
The dialog uses the existing `Dialog` component with `dialog_styles`. The message editor uses `EditorView` with `soft_wrap`, `autogrow`, and `supports_vim_mode: false`.
|
|
|
|
File changes are loaded on construction and reloaded when `include_unstaged` is toggled. The confirm button is disabled when there are no files or no message.
|
|
|
|
### 2. `get_file_change_entries` (`git.rs`)
|
|
|
|
New async function that returns per-file change stats:
|
|
|
|
```rust
|
|
pub async fn get_file_change_entries(
|
|
repo_path: &Path,
|
|
include_unstaged: bool,
|
|
) -> Result<Vec<FileChangeEntry>>
|
|
```
|
|
|
|
- When `include_unstaged` is true: runs `git diff --numstat HEAD` + `git ls-files --others --exclude-standard` for untracked files
|
|
- When false: runs `git diff --cached --numstat` (staged only)
|
|
- Returns `FileChangeEntry { path, additions, deletions }` for each file
|
|
|
|
### 3. Dialog lifecycle in `CodeReviewView`
|
|
|
|
New field: `commit_dialog: Option<ViewHandle<CommitDialog>>`
|
|
|
|
`open_commit_dialog` method:
|
|
1. Guards against double-open
|
|
2. Gets repo path and branch name from `DiffStateModel`
|
|
3. Creates `CommitDialog` view
|
|
4. Subscribes to `CommitDialogEvent`:
|
|
- `Confirmed` → closes dialog, spawns async `run_commit`, shows success/error toast, reloads diffs + metadata + PR info
|
|
- `Cancelled` → closes dialog
|
|
5. Focuses the dialog
|
|
|
|
### 4. Overlay rendering
|
|
|
|
The dialog is rendered as a positioned overlay in `View::render`, using the same pattern as the discard confirmation dialog. Both dialogs are mutually exclusive — only one modal can be open at a time.
|
|
|
|
### 5. Action wiring
|
|
|
|
`CodeReviewAction::OpenCommitDialog` now calls `self.open_commit_dialog(ctx)` instead of being a TODO stub. `CommitAndPush` and `CommitAndCreatePr` remain stubs for child branches.
|
|
|
|
### 6. Post-commit refresh
|
|
|
|
After commit (success or failure):
|
|
- `load_diffs_for_active_repo(false, ctx)` — reloads diffs
|
|
- `refresh_diff_metadata_for_current_repo(PromptRefresh)` — updates stats
|
|
- `refresh_pr_info(ctx)` — updates PR button state
|
|
|
|
## End-to-End Flow
|
|
|
|
```mermaid
|
|
graph TD
|
|
A[User clicks Commit button] --> B[open_commit_dialog]
|
|
B --> C[CommitDialog created + focused]
|
|
C --> D{User action}
|
|
D -->|Cancel/ESC| E[Dialog closes]
|
|
D -->|Confirm| F[CommitDialogEvent::Confirmed emitted]
|
|
F --> G[run_commit async]
|
|
G -->|success| H[Toast: 'Changes successfully committed']
|
|
G -->|failure| I[Toast: error message]
|
|
H --> J[Reload diffs + metadata + PR info]
|
|
I --> J
|
|
```
|
|
|
|
## Follow-ups
|
|
|
|
- Wire `CommitAndPush` intent (push-dialog branch)
|
|
- Wire `CommitAndCreatePr` intent (pr-dialog branch)
|
|
- Auto-generate commit message when left blank (AI integration)
|
|
- Per-file staging/unstaging in the changes panel
|
|
- Commit amend support
|