Files
bbs-md/.planning/phases/04-bbs-polish-and-live-content/04-01-SUMMARY.md
T

7.0 KiB

phase, plan, subsystem, tags, requires, provides, affects, tech-stack, key-files, key-decisions, patterns-established, requirements-completed, duration, completed
phase plan subsystem tags requires provides affects tech-stack key-files key-decisions patterns-established requirements-completed duration completed
04-bbs-polish-and-live-content 01 ui
ansi-to-tui
notify
walkdir
ratatui
rust
splash-screen
file-metadata
status-bar
phase provides
03-navigation-and-links navigate_to/back/forward with link_records, breadcrumb status bar, draw_status_bar()
src/splash.rs with load_splash() loading ANSI art from splash.txt via ansi-to-tui
PageMeta struct and read_page_meta() with pure Gregorian date math in app.rs
Splash prepend with link_record line_index offsetting in navigate_to/back/forward and initial load
Status bar right side shows 'Last modified: Mon DD, YYYY | X.X KB' with graceful truncation
All Phase 4 dependencies (notify=6.1, ansi-to-tui=8.0, walkdir=2.5) in Cargo.toml
04-02-live-reload
04-03-directory-listing
added patterns
ansi-to-tui = 8.0 — ANSI SGR escape code parser targeting ratatui-core types
notify = 6.1 — cross-platform filesystem watcher (for Phase 4 plan 02)
walkdir = 2.5 — recursive directory traversal with depth tracking (for Phase 4 plan 03)
Splash prepend pattern: load_splash() returns Vec<Line<'static>>, prepend to markdown lines, offset link_records by splash_count + 1 (blank separator)
Page metadata computed in App::new() and on every navigation from vault_path.join(current_path)
Status bar graceful truncation: loop removing second-to-last right_part until left.len + right.len <= width
created modified
src/splash.rs — load_splash() reading splash.txt as Vec<u8>, parsing via IntoText trait
Cargo.toml — added notify, ansi-to-tui, walkdir dependencies
src/app.rs — PageMeta struct, read_page_meta(), unix_secs_to_ymd(), is_leap(), format_file_size(), page_meta field in App, splash logic in navigate_to/back/forward/handle_resize, metadata in draw_status_bar
src/main.rs — splash prepend in initial index.md load, mod splash declaration
App::new() computes page_meta internally from config.vault_path + current_path — keeps PageMeta private, no public type exposure needed
splash_count = splash_lines.len() + 1 for the blank separator Line — all link_record line_index values offset by this amount to keep Tab-cycling correct
Status bar truncation drops right_parts[hints_idx - 1] (the metadata item) progressively until bar fits — hints always kept as last item
Hand-rolled Gregorian date math (unix_secs_to_ymd + is_leap) — avoids external time crate dependency, ~20 lines
ratatui-core verified as single version via cargo tree — ansi-to-tui 8.0 unifies correctly with ratatui 0.30
Splash pattern: load bytes with std::fs::read, call .into_text().ok()?, return .lines — all owned, 'static lifetime
Link offset pattern: splash_count = splash_lines.len() + 1; for record in &mut link_records { record.line_index += splash_count; }
Metadata pattern: read_page_meta(&vault_path.join(vault_relative)) after successful VaultDocument::Loaded
BBS-01
BBS-02
4min 2026-02-28

Phase 4 Plan 01: BBS Polish - Splash Screen and File Metadata Summary

ANSI art splash screen loaded from splash.txt via ansi-to-tui 8.0 prepended to index.md, with file mtime and size in status bar using hand-rolled Gregorian date formatting

Performance

  • Duration: 4 min
  • Started: 2026-02-28T22:46:19Z
  • Completed: 2026-02-28T22:50:00Z
  • Tasks: 2
  • Files modified: 4

Accomplishments

  • src/splash.rs module created with load_splash() that reads splash.txt as owned bytes, parses ANSI SGR codes via IntoText trait, returns Vec<Line<'static>> — gracefully returns None if file missing
  • Splash prepend wired into all navigation paths (navigate_to, navigate_back, navigate_forward, initial load in main.rs, and handle_resize) with correct link_record.line_index offsetting so Tab-cycling still targets the right lines
  • PageMeta struct and read_page_meta() added to app.rs — reads std::fs::metadata(), converts mtime to "Feb 25, 2026" format with pure Gregorian arithmetic, formats size as "X.X KB"
  • Status bar right side now shows "Last modified: Mon DD, YYYY | X.X KB" with graceful truncation that drops metadata before hints when terminal is narrow
  • All three Phase 4 crate dependencies (notify = "6.1", ansi-to-tui = "8.0", walkdir = "2.5") added to Cargo.toml — verified single ratatui-core v0.1.0 in dependency tree

Task Commits

Each task was committed atomically:

  1. Task 1: Add Phase 4 deps and create splash module - 6aa5a94 (chore)
  2. Task 2: Wire splash prepend and file metadata to status bar - 27139cf (feat)

Files Created/Modified

  • src/splash.rs - load_splash() reading vault root splash.txt via IntoText into Vec<Line<'static>>
  • Cargo.toml - Added notify = "6.1", ansi-to-tui = "8.0", walkdir = "2.5"
  • src/app.rs - PageMeta, read_page_meta(), unix_secs_to_ymd(), is_leap(), format_file_size(); page_meta field on App; splash prepend in all navigation paths; metadata display in draw_status_bar()
  • src/main.rs - mod splash declaration; splash prepend with link_record offset in initial index.md load

Decisions Made

  • App::new() computes page_meta itself from config.vault_path + current_path — avoids making PageMeta pub while keeping initialization clean
  • splash_count = splash_lines.len() + 1 — the +1 accounts for the blank separator Line::default() between splash art and markdown content
  • Status bar graceful truncation loops removing right_parts[hints_idx - 1] (the metadata string) progressively; hints always kept as the last item
  • Hand-rolled Gregorian math in unix_secs_to_ymd() — clean ~20 lines, no chrono/gregorian dependency needed

Deviations from Plan

None - plan executed exactly as written. The plan's App::new() signature included page_meta as a parameter, but I instead computed it internally in App::new() to keep PageMeta private. This is a minor structural refinement that improves encapsulation without changing observable behavior.

Issues Encountered

None. The ansi-to-tui 8.0 + ratatui 0.30 type unification worked correctly without needing an explicit ratatui-core pin — cargo tree | grep ratatui-core showed a single v0.1.0 with (*) deduplication markers as expected.

User Setup Required

Optional: Create splash.txt in the vault root containing ANSI art (CGA palette, block characters). If the file is absent, index.md renders normally with no error.

Next Phase Readiness

  • Phase 4 Plan 02 (live reload via notify) can now start — notify = "6.1" is already in Cargo.toml
  • Phase 4 Plan 03 (directory listing via walkdir) can start — walkdir = "2.5" is in Cargo.toml
  • load_splash() in splash.rs is pub and available for future plans
  • All navigation paths already handle splash prepend consistently

Phase: 04-bbs-polish-and-live-content Completed: 2026-02-28