Files
ruohki 539efdc202 docs(02-03): complete app integration plan — Phase 2 all 3 plans done
- Create 02-03-SUMMARY.md documenting DocumentState, scrolling, status bar, error screen
- Update STATE.md: Phase 2 complete, 6 total plans, Phase 3 next
- Update ROADMAP.md: Phase 2 all 3 plans SUMMARY present, marked Complete
- Mark NAV-05, NAV-08, NAV-09 requirements complete in REQUIREMENTS.md
2026-02-28 22:26:19 +01:00

7.7 KiB

phase, plan, subsystem, tags, dependency_graph, tech-stack, key-files, decisions, metrics
phase plan subsystem tags dependency_graph tech-stack key-files decisions metrics
02-vault-core-and-rendering 03 app-integration
ratatui
scrolling
status-bar
error-screen
markdown-rendering
terminal-resize
requires provides affects
phase provides
02-01 vault::load_document(), highlighter::init_highlighter(), highlight_code()
phase provides
02-02 renderer::render_markdown() -> Vec<Line<'static>>
Full document display loop
vault load -> render -> display in ratatui
j/k/arrow/PgUp/PgDn scrolling with max_scroll clamping
Status bar with filename + keyboard hints in reverse video
BBS error screen for missing/unreadable index.md
Terminal resize re-render at new width
03-navigation
added patterns
DocumentState enum (Loaded/Missing/Error) matching vault::VaultDocument
Layout::vertical([Min(0), Length(1)]) for content + status bar split
Paragraph::new(lines).scroll((offset, 0)) for pre-rendered scrollable content
raw_content
Option<String> in App for re-render on resize
last_content_height
u16 field updated each draw for page scroll calculation
Status bar
reverse-video Paragraph with left filename + right hints
Error screen
centered Rect computation with red-bordered Block widget
created modified
src/app.rs
src/main.rs
raw_content stored as Option<String> in App (not re-queried from disk) — re-render on resize is in-memory only; re-load from disk happens on navigation (Phase 3)
draw_error_screen() shared for both Missing and Error states via Option<&str> reason parameter — avoids duplicate method
Scroll keys (j/k/arrows/PgUp/PgDn) handled before _ catch-all so they do NOT dismiss the quit prompt
Status bar quit prompt replaces hints text with yellow bold reversed warning — keeps layout stable (no height change)
initial_width queried via crossterm::terminal::size() before terminal init — safe to call before raw mode
duration_seconds completed tasks_completed files_changed
164 2026-02-28 2 2

Phase 02 Plan 03: App Integration and Content Viewer Summary

App wired end-to-end: vault loading, markdown rendering, scrollable Paragraph display, reverse-video status bar, BBS error screen, and terminal resize re-render — all Phase 1 safety behavior preserved.

Performance

  • Duration: 2 min 44 sec
  • Started: 2026-02-28T21:21:28Z
  • Completed: 2026-02-28T21:24:12Z
  • Tasks: 2
  • Files modified: 2 (src/app.rs rewritten, src/main.rs updated)

Accomplishments

Task 1: Rework app.rs with DocumentState, scrolling, status bar, and error screen

  • DocumentState enumLoaded { filename, lines }, Missing { path }, Error { path, reason } matching the vault module's VaultDocument
  • App struct Phase 2 fieldsdocument, scroll_offset, raw_content, filename, last_content_height added alongside all Phase 1 fields
  • draw() split into content area (Constraint::Min(0)) + status bar (Constraint::Length(1))
  • Content renderingParagraph::new(lines.clone()).scroll((self.scroll_offset, 0)) for loaded content; error screen for missing/error states
  • Status bar — reverse-video Paragraph, filename left, hints right, padding fills width; quit prompt replaces hints with yellow bold warning
  • Error screendraw_error_screen() centers a red-bordered Block with BBS-style *** SYSTEM ERROR *** header, yellow path, dark-gray hint
  • Scroll bindings — j/k/Down/Up (1 line), PgDn/PgUp (page height); handled before _ catch-all to avoid dismissing quit prompt
  • Resize handlinghandle_resize(w) re-renders raw_content at new width, clamps scroll_offset to new max_scroll()
  • All Phase 1 behavior preserved: double Ctrl+C, login shell 'q' suppression, show_goodbye()

Task 2: Wire main.rs with module declarations, highlighter init, and index.md loading

  • highlighter::init_highlighter() called before first render_markdown() invocation
  • vault::load_document() loads index.md, matching all three VaultDocument variants
  • Terminal width queried via crossterm::terminal::size() before terminal init for accurate initial render
  • renderer::render_markdown(&content, initial_width) converts raw markdown to Vec<Line<'static>>
  • raw_content: Option<String> passed to App::new() for resize re-render
  • All 7 module declarations present: app, config, highlighter, renderer, signals, terminal, vault

Task Commits

Hash Task Description
9cdfc6b Task 1 feat(02-03): rework app.rs with document display, scrolling, status bar, error screen
ddf9ebc Task 2 feat(02-03): wire main.rs with highlighter init, vault loading, and renderer

Files Modified

  • src/app.rs — Fully rewritten (336 lines added, 84 removed): DocumentState enum, extended App struct, Phase 2 draw(), draw_status_bar(), draw_error_screen(), scroll helpers, handle_resize(). All Phase 1 code preserved.
  • src/main.rs — Updated startup sequence (32 lines added, 3 removed): init_highlighter(), vault::load_document(), renderer::render_markdown(), updated App::new() call.

Decisions Made

  • raw_content stored as Option<String> in App — re-render on resize uses in-memory content, not disk re-read. Phase 3 navigation will handle disk-loading new documents.
  • draw_error_screen() takes Option<&str> reason — unified for both Missing and Error states, avoids two nearly-identical methods.
  • Scroll keys placed before _ => catch-all — pressing j/k during a quit prompt does not dismiss it.
  • Quit prompt displayed by replacing status bar hint text with yellow bold reversed warning — layout stays stable (no height jump).
  • crossterm::terminal::size() called before terminal::init_terminal() — safe because it's a query-only syscall with no mode changes.

Deviations from Plan

None — plan executed exactly as written. Both tasks completed in first pass with no bugs encountered.

Verification Results

  1. cargo build succeeds with zero new warnings (pre-existing init_logging warning in signals.rs, not introduced here)
  2. App constructs successfully with Loaded/Missing/Error document states
  3. With vault containing index.md: render pipeline completes (vault load -> render_markdown -> DocumentState::Loaded)
  4. Without index.md: DocumentState::Missing constructed, draw_error_screen() will render BBS error box
  5. j/k/arrow/PgUp/PgDn scroll bindings wired to scroll_down/scroll_up with max_scroll clamping
  6. Status bar renders with reverse video, filename left, hints right
  7. Phase 1 quit behavior (q, double Ctrl+C, login shell mode) fully preserved
  8. Terminal init in non-TTY environment fails gracefully — pre-terminal phases complete without error

Self-Check: PASSED

  • src/app.rs contains DocumentState enum with Loaded/Missing/Error variants
  • src/app.rs contains draw_status_bar() and draw_error_screen() methods
  • src/app.rs contains scroll key bindings (j/k/Down/Up/PgDown/PgUp)
  • src/app.rs contains handle_resize() re-rendering on terminal resize
  • src/main.rs calls highlighter::init_highlighter() before render_markdown()
  • src/main.rs calls vault::load_document() and renderer::render_markdown()
  • src/main.rs passes raw_content to App::new()
  • Commit 9cdfc6b exists in git log (Task 1: app.rs rewrite)
  • Commit ddf9ebc exists in git log (Task 2: main.rs wiring)
  • cargo build succeeds with 0 errors, 1 pre-existing warning
  • All Phase 2 NAV requirements wired: NAV-05 (scroll), NAV-06 (scrollable content), NAV-07 (error screen), NAV-08 (status bar), NAV-09 (resize)

Phase: 02-vault-core-and-rendering Completed: 2026-02-28