scythe/docs/superpowers/plans/2026-10-04-settings-ui-and-notifications-redesign.md

292 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Settings UI and Notification Engine Redesign Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Rebuild the Scythe settings UI into a clean, centered NVIDIA ShadowPlay-style split-panel modal with smooth direct numeric input fields and implement a zero-latency in-overlay toast animation system with graceful standalone toast handoff.
**Architecture:** Replace the legacy 3-column freestanding page stack in [src/overlay_egui.rs](file:///home/oiupoyt/my%20stuff%20yea/projects/scythe/src/overlay_egui.rs) with a unified `ShadowPlayView::Settings(SettingsTab)` modal. Implement numeric inputs with bounds clamping and inline stepper buttons. Replace external toast process killing with in-overlay egui animation banners and graceful window messaging.
**Tech Stack:** Rust 2024 edition, egui / eframe 0.31, Win32 DWM / Windows COM, Wayland layer-shell.
**Spec:** [`docs/superpowers/specs/2026-10-04-settings-ui-and-notifications-redesign.md`](file:///home/oiupoyt/my%20stuff%20yea/projects/scythe/docs/superpowers/specs/2026-10-04-settings-ui-and-notifications-redesign.md)
## Global Constraints
- Absolutely zero emojis across code, comments, logs, test outputs, and commits.
- Clickable markdown links formatted with the `file://` scheme.
- Complete conditional compilation safety across Linux and Windows.
- No blocking operations on UI rendering loops.
## Review Focus
1. Sub-1080p display clipping: Modal must adaptively scale below 850px viewport heights without overflowing the screen.
2. Direct numeric string parsing: Typing non-numeric characters in FPS, Bitrate, or Duration fields must not crash or corrupt settings state.
3. Rapid hotkey keycap binding: Entering key listener mode must capture multi-modifier shortcuts (`Ctrl+Shift+R`, `Alt+Z`) cleanly and allow cancellation with `Escape`.
4. Simultaneous in-overlay notifications: Multiple sequential alerts must reset duration or smoothly update without graphical popping.
5. Multi-monitor Windows geometry: Standalone toasts and modals must respect active monitor bounds when `monitor_x` is negative or non-zero.
---
### Task 1: Data Structures, Enums, and Numeric Input Component
**Files:**
- Modify: [`src/overlay_egui.rs`](file:///home/oiupoyt/my%20stuff%20yea/projects/scythe/src/overlay_egui.rs)
- Test: [`src/overlay_egui.rs`](file:///home/oiupoyt/my%20stuff%20yea/projects/scythe/src/overlay_egui.rs)
**Interfaces:**
- Produces:
- `pub enum SettingsTab { Video, Audio, Shortcuts, ReplayAndStorage, Livestream, AppearanceAndSystem }`
- `pub enum ShadowPlayView { MainHud, Settings(SettingsTab), Gallery }`
- `pub fn numeric_input_box(ui: &mut egui::Ui, value_str: &mut String, val: &mut u32, min: u32, max: u32, step: u32, unit: &str, accent: Color32) -> bool`
- `pub struct InOverlayToast { pub title: String, pub subtitle: String, pub icon: ToastIcon, pub created_at: Instant, pub duration: Duration }`
- [ ] **Step 1: Write unit tests for numeric input bounds and Tab enums**
In `src/overlay_egui.rs` tests module:
```rust
#[test]
fn test_numeric_input_clamping_and_validation() {
let mut val = 60u32;
let mut text = "60".to_string();
assert!((15..=360).contains(&val));
// Test text update
text = "144".to_string();
if let Ok(parsed) = text.trim().parse::<u32>() {
val = parsed.clamp(15, 360);
}
assert_eq!(val, 144);
// Test out of bounds clamping
text = "999".to_string();
if let Ok(parsed) = text.trim().parse::<u32>() {
val = parsed.clamp(15, 360);
}
assert_eq!(val, 360);
}
```
- [ ] **Step 2: Run test to verify it passes or fails**
Run: `cargo test --lib test_numeric_input_clamping_and_validation`
- [ ] **Step 3: Define `SettingsTab` and `numeric_input_box` in `src/overlay_egui.rs`**
Implement:
- `SettingsTab` enum with `Video`, `Audio`, `Shortcuts`, `ReplayAndStorage`, `Livestream`, `AppearanceAndSystem`.
- `numeric_input_box` rendering a dark input box with `[-]` and `[+]` stepper buttons and unit label.
- Add `active_tab: SettingsTab` and `in_overlay_toast: Option<InOverlayToast>` to `ScytheOverlayApp`.
- [ ] **Step 4: Verify compilation**
Run: `cargo check --all-targets`
- [ ] **Step 5: Commit**
```bash
git add src/overlay_egui.rs
git commit -m "feat(ui): add SettingsTab enum, InOverlayToast struct, and numeric input component"
```
---
### Task 2: Unified Centered ShadowPlay Settings Modal Layout
**Files:**
- Modify: [`src/overlay_egui.rs`](file:///home/oiupoyt/my%20stuff%20yea/projects/scythe/src/overlay_egui.rs)
- Test: [`src/overlay_egui.rs`](file:///home/oiupoyt/my%20stuff%20yea/projects/scythe/src/overlay_egui.rs)
**Interfaces:**
- Consumes: `SettingsTab`, `ScytheOverlayApp`, `accent_color()`.
- Produces: `render_settings_modal(&mut self, ctx: &egui::Context, ui: &mut egui::Ui)`.
- [ ] **Step 1: Write layout geometry test for settings modal**
In `src/overlay_egui.rs` tests module:
```rust
#[test]
fn test_settings_modal_geometry_bounds() {
for (screen_w, screen_h) in [(1280.0, 720.0), (1920.0, 1080.0), (2560.0, 1440.0), (3840.0, 2160.0)] {
let is_compact_h = screen_h < 850.0;
let modal_w = if screen_w < 1400.0 { 680.0 } else { 760.0 };
let modal_h = if is_compact_h { 450.0 } else { 520.0 };
let pos_x = (screen_w - modal_w) * 0.5;
let pos_y = (screen_h - modal_h) * 0.5;
assert!(pos_x >= 0.0);
assert!(pos_y >= 0.0);
assert!(pos_x + modal_w <= screen_w);
assert!(pos_y + modal_h <= screen_h);
}
}
```
- [ ] **Step 2: Run test to verify it passes**
Run: `cargo test --lib test_settings_modal_geometry_bounds`
- [ ] **Step 3: Implement `render_settings_modal`**
- Centered modal container (`modal_w x modal_h`) with obsidian glass fill `#101418` and top accent line.
- Left sidebar (`190px` width) with vertical tab buttons for `Video`, `Audio`, `Shortcuts`, `Replay & Storage`, `Livestream`, `Appearance & System`.
- Active tab highlight with accent pill border and crisp text.
- Compact "Reset to Defaults" button and version tag at sidebar footer.
- Close button (`X`) and "Done" button at top-right.
- Clicking outside or pressing Escape returns to `ShadowPlayView::MainHud`.
- [ ] **Step 4: Run compiler check**
Run: `cargo check --all-targets`
- [ ] **Step 5: Commit**
```bash
git add src/overlay_egui.rs
git commit -m "feat(ui): implement centered ShadowPlay settings modal with tab navigation"
```
---
### Task 3: Category Settings Panels Implementation
**Files:**
- Modify: [`src/overlay_egui.rs`](file:///home/oiupoyt/my%20stuff%20yea/projects/scythe/src/overlay_egui.rs)
**Interfaces:**
- Produces:
- `render_tab_video`
- `render_tab_audio`
- `render_tab_shortcuts`
- `render_tab_replay_storage`
- `render_tab_livestream`
- `render_tab_appearance_system`
- [ ] **Step 1: Implement `render_tab_video`**
- Numeric input box for Target Framerate (`15` to `360` FPS) with `[-]` and `[+]` steppers.
- Numeric input box for Recording Bitrate (`5` to `150` Mbps).
- Codec selector (`H.264`, `HEVC`, `AV1`).
- Toggle switch for "Record mouse cursor".
- [ ] **Step 2: Implement `render_tab_audio`**
- Source selector (`System Audio`, `Microphone`, `Both`, `Muted`).
- Sliders for System Volume (0-100%) and Mic Volume (0-100%).
- Live stereo VU meters with soft-limit indicators.
- [ ] **Step 3: Implement `render_tab_shortcuts`**
- Interactive cards for `Menu Overlay`, `Save Replay`, `Start/Stop Record`, `Toggle Cursor`.
- Click to listen for key combinations, with instant rebind and Esc to cancel.
- [ ] **Step 4: Implement `render_tab_replay_storage`**
- Numeric input box for Replay Buffer Duration (`5` to `1800` seconds).
- Calculated RAM footprint badge.
- Path input with "Browse" button (invoking native Windows COM `IFileOpenDialog` / Linux portal) and "Open Folder".
- [ ] **Step 5: Implement `render_tab_livestream` and `render_tab_appearance_system`**
- Service dropdown (`Twitch`, `YouTube`, `Kick`, `Custom RTMP`), URL, and masked stream key field.
- 8 accent color chips with instant preview.
- Startup toggles ("Start replay on login", "Open overlay on login").
- In-app version checker with "Check for Updates" button.
- [ ] **Step 6: Run verification and tests**
Run: `cargo check --all-targets && cargo test`
- [ ] **Step 7: Commit**
```bash
git add src/overlay_egui.rs
git commit -m "feat(ui): implement clean settings tab panels with numeric input boxes"
```
---
### Task 4: In-Overlay Notification Animation Engine & Standalone Toast Overhaul
**Files:**
- Modify: [`src/overlay_egui.rs`](file:///home/oiupoyt/my%20stuff%20yea/projects/scythe/src/overlay_egui.rs)
- Test: [`src/overlay_egui.rs`](file:///home/oiupoyt/my%20stuff%20yea/projects/scythe/src/overlay_egui.rs)
**Interfaces:**
- Produces:
- `ScytheOverlayApp::show_hud_notification` (queues in-process `InOverlayToast`)
- `render_in_overlay_toast(&mut self, ctx: &egui::Context, ui: &mut egui::Ui)`
- Overhauled `run_egui_toast` with cubic ease-out animation
- [ ] **Step 1: Write test for cubic ease-out calculation**
```rust
#[test]
fn test_cubic_ease_out_progress() {
let ease_out = |t: f32| -> f32 {
let inv = 1.0 - t.clamp(0.0, 1.0);
1.0 - inv * inv * inv
};
assert_eq!(ease_out(0.0), 0.0);
assert_eq!(ease_out(1.0), 1.0);
assert!(ease_out(0.5) > 0.5); // Fast start, gentle deceleration
}
```
- [ ] **Step 2: Run test to verify it passes**
Run: `cargo test --lib test_cubic_ease_out_progress`
- [ ] **Step 3: Implement `render_in_overlay_toast`**
- Paints floating notification banner in top-right corner of overlay.
- `0.0s – 0.22s`: Slide in from right viewport margin using cubic ease-out.
- `0.22s – 2.4s`: Fully visible with icon, bold title, subtitle, and discharging accent progress line.
- `2.4s – 2.7s`: Smooth alpha fade-out to zero.
- Renders directly in the egui viewport with zero process spawning overhead.
- [ ] **Step 4: Refactor `run_egui_toast` standalone window**
- Uses the same cubic ease-out curve and ShadowPlay aesthetic card.
- Positioned at `(active_mon_x + active_mon_w - 364, active_mon_y + 24)`.
- Clean automatic exit after 2.7s duration.
- [ ] **Step 5: Verify compiler and tests**
Run: `cargo check --all-targets && cargo test`
- [ ] **Step 6: Commit**
```bash
git add src/overlay_egui.rs
git commit -m "feat(ui): implement in-overlay toast animation engine and overhaul standalone toasts"
```
---
### Task 5: Integration, End-to-End Verification, and Build Deployment
**Files:**
- Modify: [`TODO_CHECKLIST.md`](file:///home/oiupoyt/my%20stuff%20yea/projects/scythe/TODO_CHECKLIST.md)
- Test: [`tests/e2e_test.sh`](file:///home/oiupoyt/my%20stuff%20yea/projects/scythe/tests/e2e_test.sh)
- [ ] **Step 1: Run clippy and check across all targets**
Run: `cargo clippy --all-targets -- -D warnings`
Expected: 0 warnings, 0 errors.
- [ ] **Step 2: Run full unit test suite**
Run: `cargo test`
Expected: All tests pass.
- [ ] **Step 3: Run end-to-end integration test**
Run: `bash tests/e2e_test.sh`
Expected: Recording and replay succeed without corruption.
- [ ] **Step 4: Compile release binaries and install locally**
Run: `cargo build --release && bash install.sh`
Expected: Fresh binaries deployed to `~/.local/bin/` and daemon restarted.
- [ ] **Step 5: Commit final changes**
```bash
git add TODO_CHECKLIST.md
git commit -m "chore: update maintainer checklist with settings modal and notification overhaul"
```