Commit Graph

826 Commits

Author SHA1 Message Date
vasilito b4237bb12e redox-driver-sys: fix kernel GPF by acquiring IOPL before PCI I/O port access
Root cause: PciDevice::open_io_ports never called acquire_iopl(),
so the first outl to 0xCF8 triggered #GP(0) when redox-drm tried
to scan virtio-gpu PCI capabilities.

- Add ensure_iopl_acquired() helper (thread-local Once)
- Call it in PciDevice::open_io_ports before any I/O
- Add P1-pci-open-io-ports-iopl.patch to recipe
- Mirror patch to local/patches/ for durability
2026-06-20 23:14:11 +03:00
vasilito d55bef9a2d vfs: wire SFTP handler to known_hosts store (Phase 27)
Replaces the AcceptAnyKey stub with KnownHostsHandler that pins
server keys against ~/.config/tlc/known_hosts (or
$XDG_CONFIG_HOME/tlc/known_hosts).

Storage model: each entry stores the SHA-256 fingerprint of the host
key (64-char lowercase hex), not the raw base64 key bytes.  This
sidesteps the absence of a PublicKey::key_data() round-trip in
russh 0.44 and keeps the file format self-describing — fingerprints
are what the user sees in 'ssh-keygen -lf', so a quick visual
diff is enough to spot a MITM.

Three matching outcomes:
  Match     — host + fingerprint in store, accept connection
  Mismatch  — host in store, fingerprint changed → SshHandlerError::KeyMismatch
  Unknown   — host not in store → TOFU: append + save + accept

A mismatch returns Err, which surfaces to the caller as
VfsError::Connection("ssh: ...") with the presented and stored
fingerprints in the message — the user sees a hard reject, never
a silent re-trust.  Save failures during TOFU are non-fatal (the
in-memory append is enough for the current session); the user will
see the TOFU prompt again next connect.

Tests: 9 known_hosts + 2 SFTP error-display = 11 new tests.
Total: 1172 passing, 0 failing.
2026-06-20 23:08:11 +03:00
vasilito cca510465d redbear-power: v1.22 sort by IO (per-process read+write bytes)
Process tab gains a new IO column sourced from /proc/[pid]/io
read_bytes and write_bytes, summing them as a single sortable value.

- New fields on ProcessInfo: io_read_kb, io_write_kb
- New method: ProcessInfo::io_total_kb()
- New helpers: read_io_bytes, write_io_bytes (silent on failure;
  /proc/[pid]/io may require CAP_SYS_PTRACE for owned UID)
- New SortMode::Io variant inserted into the cycle
  (Rss -> Cpu -> Io -> Pid -> Name)
- Updated render header: VIRT replaced by IO (RSS preserved)
- 4 new unit tests; total 80 pass
- Redox stripped binary: 4123496 bytes
- Linux smoke test confirms opencode dominates IO, kscreenlocker_g shows 0.0 KiB

Docs: local/docs/redbear-power-improvement-plan.md \xC2\xA746
2026-06-20 22:59:20 +03:00
vasilito 24511fbde8 tlc: fix known_hosts.rs compile errors (fingerprint type mismatch, format string)
- Convert String fingerprint to Vec<u8> for VerifyResult::Mismatch
- Fix format string to include comment placeholder
2026-06-20 22:56:06 +03:00
vasilito d1f2e59755 redbear-power: v1.21 — SMART UI integration (Storage tab badges)
Wires the v1.20 SMART data module into the Storage tab UI.
Each disk now shows a health badge (✓ PASSED / ✗ FAILED / error).

Implementation:
- App.smart: SmartInfo field + 11-tick refresh (paired with Storage)
- Conditional refresh (if self.smart.available guard — avoids
  re-running smartctl if we already know it's missing)
- render_storage_panel: 4 SMART badge states
  1. !available → '(SMART: install smartmontools)'
  2. health.passed → ' ✓ PASSED'
  3. !health.passed → ' ✗ FAILED'
  4. health.error → ' (SMART: <error>)'

Linux host smoke test (this dev host without smartctl):
- Each disk shows '(SMART: install smartmontools)' hint
- No panic, graceful degradation
- Storage tab still works (no regression)

Performance: smartctl subprocess ~5-50ms per disk, 3 disks = 15-150ms
per 11-tick refresh (5.5 sec), well within budget.

76/76 tests pass (no new tests — UI integration only).

Cross-compile SHA256: ed804710fa834f4453a236aa034d50668b948b391ec1d2ccea294d438016d855.

Docs: improvement plan §45, CONSOLE-TO-KDE §3.3.2 v1.21,
RATATUI-APP-PATTERNS §13.14 + §14 (6400 LoC, 21 modules, 76 tests).
2026-06-20 22:50:04 +03:00
vasilito 1e86a8b0e0 docs: update CONSOLE-TO-KDE-DESKTOP-PLAN.md to v5.4
- redox-drm virtio-gpu crash fixed
- Greeter/SDDM Wayland socket timeout fixed
- ISO boots to text login prompt in QEMU
- Redox git forks research completed
2026-06-20 22:43:01 +03:00
vasilito 6006d20178 redox-drm: add virtio-gpu detection (1AF4:1050/1052) and Intel ARC PCI IDs
greeter: fix Wayland socket timeout (45s wait, dual-path probe)
sessiond: add D-Bus socket candidate probing with better error logging
config: align greeter/sddm runtime dirs and DRM wait timeouts
2026-06-20 22:41:26 +03:00
vasilito f5311f16c8 redbear-power: v1.20 — SMART data module (graceful when smartctl missing)
Adds the smart.rs module for disk health monitoring. Since
smartctl is not installed on most systems (this dev host has it
absent), v1.20 implements the module with three-tier graceful
degradation per the zero-stub policy.

New module smart.rs (222 lines, 7 unit tests):
- SmartInfo struct with available + per-disk health records
- SmartHealth struct with passed + attributes + error
- SmartAttribute struct with id + name + value + worst + threshold + raw
- SmartInfo::smartctl_available() — checks smartctl --version
- SmartInfo::read(disks) — orchestrates per-disk smartctl -A -H
- parse_smartctl_output(text) — extracts passed/failed + attrs
- parse_attribute_line(line) — single 10-field SMART attribute
- parse_smart_value(s) — handles both hex (0x33) and decimal
- health_for(disk_name) — convenience accessor

Three-tier graceful degradation:
1. smartctl missing → available=false, disks=[]
2. smartctl errors per disk → error captured in SmartHealth
3. NVMe permission issues → error message, no fabrication

Updated main.rs: mod smart declaration.

76/76 tests pass (5 bench + 12 sensor + 13 network + 12 storage +
20 process + 7 pid_detail + 7 smart).

Linux host smoke test (this dev host without smartctl):
- available=false (graceful, no panic)
- Storage tab still works (no regression)

Cross-compile SHA256 unchanged from v1.19 (smart.rs is dead code
on Redox — compiles but never called).

Docs: improvement plan §44, CONSOLE-TO-KDE §3.3.2 v1.20,
RATATUI-APP-PATTERNS §13.14 + §14 (6360 LoC, 21 modules, 76 tests).
2026-06-20 22:39:27 +03:00
vasilito 006c59b88c tlc: phase 26 — PLAN.md reconciliation with code reality
Reconcile PLAN.md audit and feature tables with current code
state after Phase 25. Several rows are stale relative to the
code (resolved earlier but PLAN never updated):

  §2 audit rows marked FIXED/VERIFIED:
    #22 (Tui::default non-tty panic → Tui::new returns Err)
    #23 (save.rs non-UTF-8 silent drop → from_utf8_lossy fallback)
    #25 (Cmd enum missing_docs → all 73 variants documented)
    #28 (F9 unbound in keymap → km.bind(F9, Cmd::MenuBar) exists)
    #33 (move_one discards errno → preserves io::Error fully)

  §15d feature rows marked DONE with file/line citations:
    Row 25 (Save/restore cursor pos → P4b done)
    Row 30 (PTY persistent subshell → terminal/subshell.rs:1-617)
    Row 33 (Growing buffer / tail -f → viewer/mod.rs:84-89, 295-357)

Phase 26 is documentation-only — no code changes.
2026-06-20 22:37:36 +03:00
vasilito 3b251a1ea1 redbear-power: v1.19 — PID detail view (modal popup)
Closes the v1.13 §37.6 PID detail forward-work item. Press Enter
on a process row in the Process tab to open a modal popup with
detailed /proc/[pid] info.

New module pid_detail.rs (237 lines, 7 unit tests):
- read_status(pid) → ProcStatus: Name, State, Pid, PPid, Tgid,
  Threads, Uid (3-tuple), Gid (3-tuple), 12 Vm* memory fields
- read_io(pid) → ProcIo: rchar, wchar, syscr, syscw, read_bytes,
  write_bytes, cancelled_write_bytes
- read_smaps_rollup(pid) → ProcSmapsRollup: Rss, Pss, Private_Clean,
  Private_Dirty, Swapped (CAP_SYS_ADMIN gated)
- PidDetail::read(pid) — aggregator

Updated app.rs:
- pid_detail: Option<PidDetail> field
- selected_pid() method — returns PID of selected row (filter-aware)

Updated main.rs:
- Enter on Process tab → opens pid_detail for selected PID
- Enter on other tabs → toggle P-state expansion (existing behavior)
- Esc or any key while popup open → closes popup
- Popup rendered with Clear + centered Rect (70% × 80%)

Updated render.rs:
- New render_pid_detail(detail, pid) — full PID detail layout
  with [Identity] / [Memory] / [smaps_rollup] / [io] sections
- Fixed missing render_system_panel import (existing bug)

69/69 tests pass (5 bench + 12 sensor + 13 network + 12 storage +
20 process + 7 pid_detail).

Cross-compile SHA256: e34a22ed518b2e918bf8fb07eec77d8c5e2e2389a01ad00dad0d76f5c09578a4.

Docs: improvement plan §43, CONSOLE-TO-KDE §3.3.2 v1.19,
RATATUI-APP-PATTERNS §13.14 + §14 (6160 LoC, 20 modules, 69 tests).
2026-06-20 22:27:06 +03:00
vasilito 601d08bdc2 tlc: phase 25 — verify Alt-P format paragraph + add integration test
Format-paragraph was already implemented (Editor::format_paragraph
in src/editor/mod.rs + Alt-P keybind wired in handlers.rs at
0x70 within the Alt-modifier match arm). The function uses
editor::format::reformat_paragraph_at which walks contiguous
non-blank lines and re-flows them at DEFAULT_WRAP_WIDTH (72).
Undoable via begin_undo_group / end_undo_group pair.

This phase adds an end-to-end handler test that exercises the
keybinding path: insert a long paragraph, press Alt-P, verify
the buffer is marked modified. Pre-existing format.rs unit tests
cover the formatting details (wrap widths, blank-line
boundaries, undo); this test verifies the integration.

PLAN.md §15d row 32 marked Done.

Tests: 1154 passed (was 1153, +1). Release binaries build clean.
2026-06-20 22:23:46 +03:00
vasilito 848d0fad94 redbear-power: v1.18 — Process filtering (closes v1.13 forward work)
Closes the v1.13 §37.6 forward-work item (the last one). Process
tab now supports case-insensitive substring filtering on the
process name (comm).

Implementation summary:
- New App.process_filter: String field
- Hotkey 'f' opens text-input mode (pattern reused from refresh-
  interval input):
  - chars → push to filter buffer
  - Backspace → pop
  - Enter → commit filter, flash match count
  - Esc → discard buffer + clear filter
- Filter applied in render_process_panel:
  - For each process, skip if non-empty filter doesn't match
    (case-insensitive substring on comm)
- Header line shows filter indicator + hint
- Helper proc_filter_match_count(app) for status message
- 4 new unit tests (case insensitive + substring + no match + empty)
- 62/62 tests pass

Build: clean
Cross-compile SHA256: 12913dedc9b0ea58ed3e7418527da34c903f70be703b8676e4273042c73ac875

Docs: improvement plan §42, CONSOLE-TO-KDE §3.3.2 v1.18,
RATATUI-APP-PATTERNS §13.14 + §14 (5840 LoC, 62 tests).
2026-06-20 22:11:37 +03:00
vasilito 28906f16cf tlc: phase 24 — editor word sort (Alt-F8)
Mirrors MC's edit_sort_cmd flow (CK_Sort / M-F8 →
src/editor/editcmd.c::edit_sort_cmd):

  1. Require a marked block; surface error message if no
     selection is active.
  2. Stash the active selection to a unique temp file under
     /tlc-sort-<nanos>/in.txt (per-call unique dir to
     avoid races between concurrent sort runs).
  3. Run via 'sh -c sort <opts> <in> > <out>' so user-supplied
     options pass through verbatim (matches MC g_strconcat).
     Empty options means default lexical sort.
  4. On non-zero exit: surface exit code + first stderr line.
  5. On success: delete the original selection, insert the
     sorted output at the cursor, mark buffer modified, and
     surface a status line ('Sort: ok (N bytes, M lines)').

Components:
  src/editor/mode.rs — new PromptKind::Sort variant.
  src/editor/handlers.rs — Alt-F8 keybind (errors if no
    selection, otherwise opens the sort prompt); commit_prompt
    routes PromptKind::Sort to Editor::sort_block(options).
  src/editor/render.rs — title ('Run sort') + label ('sort
    options (empty for default)') + mode tag (' [Sort]') for
    the prompt.
  src/editor/mod.rs — Editor::sort_block(options).

Tests: 1153 passed (was 1150, +3):
  - sort_block_sorts_active_selection (apple/banana/cherry)
  - sort_block_with_no_selection_reports_error
  - sort_block_with_reverse_flag (-r → c/b/a)
Release binaries build clean.

PLAN.md §15d row 32a marked Done.
2026-06-20 22:09:49 +03:00
vasilito 08561033ae redbear-power: v1.17 — Sort modes in Process tab (closes v1.13 forward work)
Closes the v1.13 §37.6 forward-work item. Process tab now supports
sorting by RSS, CPU%, PID, or Name — cycle with hotkey 'o'.

Implementation summary:
- New SortMode enum: Rss (default) / Cpu / Pid / Name
- SortMode::next() cycles through all 4 modes
- SortMode::sort(&mut Vec<ProcessInfo>) reorders in place
- ProcInfo::read_sorted(sort_mode) — read with custom sort
- ProcInfo::read_with_cpu_pct_sorted(prev, dt, num_cpus, sort_mode)
  — re-sorts at end because CPU% may change rank
- App.process_sort: SortMode field
- 13-tick refresh uses sorted variant
- Hotkey 'o' cycles sort mode (with status flash)
- Header line shows 'sort: <mode> (press o to cycle)'
- 6 new unit tests (default + cycle + 4 sort modes)

Restored v1.16 changes (prior session left them partial):
- NetInfo::rx_kbps + tx_kbps fields + init
- NetInfo::read_with_throughput(prev, dt_secs)
- App::prev_net field
- 7-tick refresh uses read_with_throughput
- render_network_panel RX/TX lines show '{X} KiB/s'
- 3 network throughput unit tests

58/58 tests pass (5 bench + 12 sensor + 10 network + 12 storage + 19 process).
Cross-compile SHA256: 5d01429b91b5c8399f6772251fd28a44a083cc53f13f2b9dff6f92245787c393.

Docs: improvement plan §41, CONSOLE-TO-KDE §3.3.2 v1.17,
RATATUI-APP-PATTERNS §13.14 + §14 (5800 LoC, 58 tests).
2026-06-20 22:00:05 +03:00
vasilito 0b0e65a643 tlc: phase 23 — viewer FileNext / FilePrev (Ctrl-F / Ctrl-B)
Mirrors Midnight Commander's
MC src/viewer/actions_cmd.c::mcview_load_next_prev (CK_FileNext
/ CK_FilePrev).

Components:
  src/viewer/siblings.rs (new) — pure helper next_or_prev_sibling:
    reads current file's parent directory, filters out hidden
    files (dot-prefixed), sorts case-insensitive, locates current
    by file_name, returns next (direction=+1) or prev (direction=-1)
    entry. Returns None at directory boundaries or on I/O error.
    6 unit tests cover next/prev/last/first/hidden/no-parent.

  src/viewer/mod.rs — Viewer::open_next / Viewer::open_prev
    public methods that look up the sibling and reload viewer
    state via a private reload_at helper (mirrors MC's
    mcview_init/mcview_done pair around mcview_load). Source
    errors are converted to std::io::Error so the Result type
    matches the existing open() signature.

  src/viewer/mod.rs — Ctrl-F / Ctrl-B keybinds in handle_key.
    Each delegates to open_next / open_prev.

  PLAN.md §15d row 29 marked Done; status bumped to Phase 23.

Tests: 1150 passed (was 1141, +9: 6 siblings module tests +
3 viewer integration tests covering open_next, open_prev,
Ctrl-F/Ctrl-B keybinds). Release binaries build clean.
2026-06-20 21:52:12 +03:00
vasilito d209b64ce9 redbear-power: v1.16 — Network throughput (closes v1.11 forward work)
Closes the v1.11 §35.7 forward-work item. Network tab now shows
real-time R/W throughput (KiB/s) per interface, computed from delta
of rx_bytes/tx_bytes between successive 7th-tick refreshes.

Source code already landed (network.rs + app.rs + render.rs).
This commit captures full v1.16 docs:

- Improvement plan §40 (Network Throughput)
- CONSOLE-TO-KDE §3.3.2 v1.16
- RATATUI-APP-PATTERNS §13.14 (audit table +16) + §14 (5755 LoC, 52 tests)

Implementation summary:
- New rx_kbps: f64 + tx_kbps: f64 fields on NetInterface
- New NetInfo::read_with_throughput(prev, dt_secs)
- Wall-clock dt (shared prev_refresh_secs with v1.14 + v1.15)
- saturating_sub on bytes prevents underflow
- 3 new unit tests (formula + underflow + zero dt)
- 52/52 total tests pass

Math sanity check (verified by unit test):
prev=1MB, now=5MB, dt=2sec → 1953.125 KiB/s
prev > now → saturating_sub → 0

Cross-compile SHA256: 053f1a0cca5185637d0316d56f5cf5832cf2e754b689bc24edf16ea5d0404fa2.
2026-06-20 21:41:07 +03:00
vasilito 6729409b4d redbear-power: v1.14 + v1.15 — CPU% + disk throughput + restoration
This commit restores and completes v1.14 (CPU% in Process tab) and
v1.15 (disk throughput in Storage tab). Previous sessions landed
partial work (cpu_pct field on ProcessInfo, read_kbps/write_kbps on
DiskStats) but never wired them up. This commit:

v1.14 — Process CPU% (Process tab):
- ProcInfo::read_with_cpu_pct(prev, dt_secs, num_cpus)
- App::prev_processes + prev_refresh_secs fields
- 13-tick refresh now uses read_with_cpu_pct with wall-clock dt
- 3 new unit tests (formula + zero + underflow)

v1.15 — Disk throughput (Storage tab):
- StorageInfo::read_with_throughput(prev, dt_secs)
- App::prev_storage field
- 11-tick refresh now uses read_with_throughput
- 3 new unit tests (formula + underflow + zero dt)

Updated render.rs:
- Process panel column header: PID STATE PRIO NI THR CPU% RSS VIRT COMM
- Storage panel Read/Written lines show 'X I/Os, Y KiB/s'

Tests: 49/49 pass (5 bench + 12 sensor + 7 network + 12 storage +
13 process).

Cross-compile SHA256: d1207b648ce89e19f8dd040f234648e1665f053ec31f8511ea187627d79bde2d.

Math sanity checks (verified by unit tests):
CPU%: delta=130 ticks, dt=2sec, num_cpus=4 → 1625.0%
Disk: prev=1MB, now=5MB, dt=2sec → 1953.125 KiB/s

Docs: improvement plan §38 (CPU%) + §39 (disk throughput),
CONSOLE-TO-KDE §3.3.2 v1.14 + v1.15, RATATUI-APP-PATTERNS §13.14 +
§14 (5720 LoC, 49 tests).
2026-06-20 21:30:39 +03:00
vasilito 75d704c06c tlc: phase 22 — wire F11 user-menu command execution
Replaces the Phase 21 TODO stub with the full MC
edit_user_menu flow:

  src/editor/mod.rs — Editor::run_user_menu_command(raw_command):
    1. Expand percent variables via PercentCtx::for_file
       (MC: expand_format).
    2. Stash active selection to clipfile (MC: edit_save_block).
       Block file path exposed via %b for downstream expansion.
    3. Run via 'sh -c <expanded>' so user can use pipes,
       redirections, globs (matches MC user_menu_cmd shell-out).
    4. On non-empty stdout: delete any selection, then
       insert_str at cursor position (MC: edit_insert_file).
       Buffer cursor is synced to editor cursor after
       delete_selection so the insert lands at the right spot.
    5. Status line: 'Menu: ok (N bytes inserted)' on success,
       'Menu: exit N, stderr: ...' on failure.

  src/editor/handlers.rs — replaces TODO with call to
    self.run_user_menu_command(command).

Tests: 1141 passed (was 1137, +4):
  - inserts stdout at cursor
  - replaces active selection (cursor sync verified)
  - reports non-zero exit status
  - expands %f to current file path via cat %f

Release binaries build clean.
2026-06-20 21:27:37 +03:00
vasilito 9d120cc802 redbear-power: add missing cpu_pct field to ProcessInfo struct 2026-06-20 21:14:56 +03:00
vasilito a5cfae5622 tlc: phase 21 — F11 user-menu dispatch for editor
Mirrors Midnight Commander's editor user-menu flow (MC
src/editor/edit.c::edit_user_menu + CK_UserMenu).

Architecture reuses the existing filemanager usermenu infra:
  filemanager::usermenu::UserMenuDialog is constructed with
  condition='edit' so the same ~/.config/tlc/menu file works
  in both filemanager (condition='view') and editor contexts.

Components:
  src/editor/usermenu.rs (new) — EditorUserMenu wrapper that
    owns the dialog + cursor snapshot + selection flag +
    clipfile path. Plus  reuses
    PercentCtx::for_file; default_block_file() resolves
    /tlc/editor.block or ~/.config/tlc/editor.block.

  src/editor/menubar.rs — adds EditorCmd::UserMenu and
    EditorCmd::EditUserMenu variants (cross-referenced MC
    CK_UserMenu + CK_EditUserMenu).

  src/editor/mod.rs — new usermenu_session: Option<EditorUserMenu>
    field, init None in both constructors, Editor::open_user_menu
    method, dispatch_editor_cmd wires UserMenu/EditUserMenu
    variants (EditUserMenu surfaces path via status message —
    full Open wiring deferred to follow-up).

  src/editor/handlers.rs — F11 keybind opens user menu (F11 is
    MC's editor UserMenu binding per misc/mc.default.keymap;
    F2 in the editor is reserved for Save). Routing at top of
    handle_key intercepts Running/Cancel/Execute outcomes;
    Execute surfaces the command in the status line — full
    selection-stash + stdout-capture is deferred TODO.

Tests: 1137 passed (was 1132, +5: 4 editor::usermenu module
tests covering expand, default_block_file, EditorUserMenu
construction, key routing; 1 handler test for F11 open + Esc close).
2026-06-20 21:14:01 +03:00
vasilito 9fa019e78a redbear-power: v1.14 — CPU% in Process tab (closes v1.13 forward work)
Closes the v1.13 §37.6 forward-work item. Process tab now shows
real-time CPU usage per process, computed from the delta of
total CPU ticks between successive 13th-tick refreshes.

Source code already landed (process.rs + app.rs + render.rs).
This commit captures full v1.14 docs:

- Improvement plan §38 (CPU% in Process Tab)
- CONSOLE-TO-KDE §3.3.2 v1.14
- RATATUI-APP-PATTERNS §13.14 (audit table +14) + §14 (19 modules, 47 tests)

Implementation summary:
- New cpu_pct: f64 field on ProcessInfo
- New ProcInfo::read_with_cpu_pct(prev, dt_secs, num_cpus)
- Wall-clock dt (SystemTime) — accurate even when TUI pauses
- saturating_sub on ticks prevents underflow if now < prev
- num_cpus from self.cpus.len() (Per-CPU detection result)
- 4 new unit tests (formula + zero + underflow + dt=0)
- 47/47 total tests pass

Math sanity check (verified by unit test):
utime=100→200, stime=50→80, dt=2sec, num_cpus=4
delta = 280-150 = 130 ticks / 2 sec = 65 ticks/sec
CPU% = 65 / 4 cpus * 100 = 1625.0%

Cross-compile SHA256: d46cd66b8e158e2327839ef502879951877a5500d4a40807d3dbc72ed7397231.
2026-06-20 20:56:54 +03:00
vasilito 1dcdc5d39d redbear-power: v1.13 — Process tab (procfs)
Adds the 9th tab in the multi-view system: Process, reading
process state and memory from /proc/[pid]/stat on Linux hosts.
Last major top-like view, complementing hardware tabs
(Storage/Network/Sensors) with software state.

New module process.rs (215 lines, 9 unit tests):
- ProcessInfo: pid, comm, state, ppid, utime, stime, priority,
  nice, num_threads, vsize_kb, rss_kb
- parse_stat_line() handles (comm) with spaces like (Web Content)
  via last-')' extraction (per man 5 proc format)
- Field indices: state=0, ppid=1, utime=11, stime=12,
  priority=15, nice=16, num_threads=17, vsize=20, rss=21
- read_comm() fallback for parens-parsing failures
- ProcInfo::read() scans /proc, sorts by RSS desc, truncates to 50
- format_memory_kb() with binary unit suffix

Updated app.rs:
- New field processes: ProcInfo, refreshed every 13th tick
  (6.5 sec). 13-tick modulus coprime with all (3,4,5,7,11).
- TabId::Process variant (9th tab)
- TabId::next() cycles PerCpu → System → Info → Motherboard →
  Battery → Sensors → Network → Storage → Process → PerCpu

Updated render.rs:
- New render_process_panel() with PID/STATE/PRIO/NI/THR/RSS/VIRT/COMM
  columns. Comm truncated to 20 chars. Sort by RSS desc (top-like).
- render_tab_bar() for 9 tabs with hotkey 1-9
- render_once dumps Process panel for headless verification

Updated main.rs:
- mod process; declaration
- New dispatch arm TabId::Process => render_process_panel
- Hotkey 9 jumps to Process tab
- render_process_panel added to imports

Linux host smoke test (596 processes, top 50):
- opencode 3.7 GiB, thunderbird 2.1 GiB, plasmashell 517 MiB
- kwin_wayland shows PRIO=-2 (real-time scheduling)
- Total RSS: 17.5 GiB

Unit tests: 43/43 pass (5 bench + 12 sensor + 7 network + 10 storage +
9 process).
Cross-compile SHA256: 2c30f86dce574f173efdcf8eb588f83abd8f0bdf2c5a2678452dd0e6a244dbf2.

Docs: improvement plan §37, CONSOLE-TO-KDE §3.3.2 v1.13,
RATATUI-APP-PATTERNS §13.14 + §14 (19 modules, 43 tests).
2026-06-20 20:41:44 +03:00
vasilito 833509a979 tlc: phase 20 wire-up — F9 menubar fully integrated
Connect the standalone editor::menubar module into the editor's
main loop:

  editor/mod.rs:
    - Add menubar: Option<EditorMenuBar> field on Editor struct
    - Init menubar: None in both Editor::open and Editor::new_empty
    - Add dispatch_editor_cmd(cmd) -> EditorResult, mapping
      EditorCmd to existing editor methods:
        Undo, Redo, Cut, Copy, Paste, GotoTop, GotoBottom,
        BookmarkToggle (opens BookmarkSet prompt),
        BookmarkClearAll, GotoLine (opens GotoLine prompt).
      Not yet wired (New, Open, Save, SaveAs, Quit, Find,
      FindNext, FindPrev, Replace, BookmarkNext/Prev, Settings)
      surface 'F9: ... (not yet wired)' message.

  editor/handlers.rs:
    - At top of handle_key, route through menubar when Some
      (Esc/F9 → Close, Enter → Dispatch, arrows/hotkeys → Running).
    - F9 keybind opens menubar.

  editor/render.rs:
    - When menubar is Some, split area into [Length(1) menubar,
      Min(1) editor]. Pass lower area as editor_area to existing
      layout, replacing two 'area' references with 'editor_area'.

Tests: 1132 passed (was 1129, +3 handler tests covering open,
Esc-close, dispatch-undo integration end-to-end).

Ref: MC src/editor/editmenu.c (six menus), editor handle_key
routing precedence for menubar overlay (matches filemanager).
2026-06-20 20:40:44 +03:00
vasilito 0d4dfb60c7 tlc: fix recipe install command with proper parentheses for conditional chmod 2026-06-20 20:11:40 +03:00
vasilito 5d0509fc15 tlc: use install command for atomic copy+chmod in recipe 2026-06-20 20:09:18 +03:00
vasilito 8935be79eb tlc: PLAN.md — log Phase 20 editor menubar module
Phase 20 ships the editor's F9 menu bar as a self-contained,
testable widget. Mirrors Midnight Commander's
src/editor/editmenu.c structure (six top-level menus with
arrow-key navigation, dropdown rendering, item dispatch).

Components:
  src/editor/menubar.rs    — EditorMenuBar + EditorCmd + render()
  src/editor/mod.rs        — pub mod menubar declaration

Tests: 10 unit tests in editor::menubar cover menu navigation
(arrows, wrapping, separators), Esc/F9 close, Enter dispatch,
letter hotkey menu selection by title, and render smoke test.

Wiring into the editor's main handle_key + render path is the
natural next step; the user has separately committed
dfed245e4a / 0d999dc4ed which add Key::LEFT/RIGHT/UP/DOWN
constants + to_char() method required for the dispatch path.

PLAN.md header bumped to Phase 20 complete.
2026-06-20 20:03:43 +03:00
vasilito 0d999dc4ed tlc: add missing key constants (LEFT/RIGHT/UP/DOWN) and to_char() method 2026-06-20 19:57:00 +03:00
vasilito 714f7c2115 tlc: add post-copy verification to recipe install loop 2026-06-20 19:51:35 +03:00
vasilito 933336180f docs: ratatui §13.14 + §14 — bump to v1.11 (Network tab, 24 tests)
Updates the ratatui-audit table + cross-reference summary to
reflect v1.11:

  §13.14 audit table:
    - v1.11 entry: 'No Network tab' → 'Implemented in v1.11'
    - LoC count: ~4400 → ~5150 across 17 modules, 17 → 24 unit tests
    - Module count: 15 → 17

  §14 cross-reference:
    - '~4900 LoC across 16 modules, with 17 unit tests'
      → '~5150 LoC across 17 modules, with 24 unit tests'
    - 'sysfs/MSR + meminfo + DMI + battery + hwmon'
      → 'sysfs/MSR + meminfo + DMI + battery + hwmon + net'
    - 'AMD CPU fallback' → 'AMD CPU + net/sysfs fallback'
    - '17 unit tests' → '24 unit tests (bench + sensor + network)'

Source code (network.rs + main.rs + render.rs) and full §35 +
v1.11 plan/consolehdk doc already landed in commit dfed245e4a
(tlc bundled). This commit catches up the ratatui cross-reference
doc that didn't fit in that bundle.
2026-06-20 19:41:59 +03:00
vasilito f9df87d56b tlc: guard install loop with file-existence check to skip missing binaries 2026-06-20 19:38:27 +03:00
vasilito dfed245e4a tlc: fix menubar render methods placement and add missing key constants 2026-06-20 19:33:40 +03:00
vasilito ea854a71d9 redbear-power: v1.10 — Per-CPU Pkg temp from hwmon (k10temp fallback)
Closes the v1.9 forward-work item (§33.7). Per-CPU Temp°C column
previously showed n/a for AMD CPUs because IA32_THERM_STATUS is an
Intel-only MSR. v1.10 falls back to hwmon when MSR unavailable.

New helper SensorInfo::pkg_temp_c(cpu_index) in sensor.rs:
- Recognizes k10temp Tctl (AMD Zen / Zen 2 / Zen 3 / Zen 4 / Zen 5)
- Recognizes coretemp 'Package id 0' (Intel, forward-compat)
- Recognizes zenpower Tdie (AMD alt driver)
- Returns None if no recognized CPU temp chip
- cpu_index reserved for future multi-socket support

Updated App::refresh() — per-CPU loop:
- If MSR fails (Intel-only path), call self.sensors.pkg_temp_c(row.id)
- PROCHOT/Critical/PowerLimit flags set to false in fallback path
  (k10temp doesn't expose these — honest empty-state pattern,
  don't fake flag values that the source can't provide)

Linux host smoke test (AMD Ryzen 9 7900X):
- Before: every CCD row showed n/a for Temp°C
- After: every CCD row shows 85 (k10temp Tctl value, °C)

5 new unit tests:
- pkg_temp_c_from_k10temp_tctl (AMD Zen)
- pkg_temp_c_from_coretemp_package_id_0 (Intel)
- pkg_temp_c_from_zenpower_tdie (AMD alt)
- pkg_temp_c_returns_none_when_no_chip (Redox)
- pkg_temp_c_ignores_unrelated_chips (nvme Composite != CPU temp)

Total: 17/17 tests pass (5 bench + 12 sensor).

Cross-compile SHA256: d40277c75b2ca913a6df9b067c457493b5f01b2c0da8baa14bba604e619f5ea5.

Docs: improvement plan §34, CONSOLE-TO-KDE §3.3.2 v1.10,
RATATUI-APP-PATTERNS §13.14 + §14 (17 tests, 4945 LoC).
2026-06-20 18:59:27 +03:00
vasilito 69e6f2a84d redbear-power: v1.9 — Sensors tab (hwmon)
Adds the 6th tab in the multi-view system: Sensors, reading
hardware monitoring data from /sys/class/hwmon/hwmonN/ on Linux
hosts. Detects all chips (k10temp, coretemp, nvme, mt7921, r8169,
spd5118, zenpower, etc.) and their temp/fan/voltage/power/current
sensors with proper unit conversions.

New module sensor.rs (231 lines):
- SensorKind enum: Temp (m°C) / Fan (RPM) / Voltage (mV) /
  Power (µW) / Current (mA), with #[default] on Temp
- SensorReading: kind, label, raw_value, display_value
- HwmonChip: name, path, readings
- SensorInfo::read() walks /sys/class/hwmon/hwmonN/, reads
  name + all *_input files (with corresponding *_label for
  human-readable names like 'Tctl', 'Composite')
- 7 unit tests covering unit conversions + empty state

Updated app.rs:
- New field sensors: SensorInfo, refreshed every 3rd tick
  (1.5 sec at POLL_MS=500). 3-tick modulus is coprime to
  meminfo's 4 and battery's 5 — no thundering-herd syscalls.
- TabId::Sensors variant (6th tab)
- TabId::next() cycles PerCpu → System → Info → Motherboard →
  Battery → Sensors → PerCpu

Updated render.rs:
- New render_sensor_panel(app, focused) with per-chip sections
  using ▸ arrow + chip name as bold header, then Label/Value pairs
  in 12-char left-aligned label / 14-char right-aligned value
  layout. Empty state: '(no sensors detected — /sys/class/hwmon/
  not readable)' rather than wall of ?.
- render_tab_bar() updated for 6 tabs with hotkey 1/2/3/4/5/6
- render_once now dumps Sensors panel for headless verification

Updated main.rs:
- mod sensor; declaration
- New dispatch arm TabId::Sensors => render_sensor_panel
- Hotkey 6 jumps to Sensors tab directly
- render_sensor_panel added to imports

Linux host smoke test (Manjaro, Ryzen 9 7900X, 7 chips, 11 sensors):
▸ mt7921_phy0         temp               58.0 °C
▸ r8169_0_e00:00      temp               51.0 °C
▸ k10temp             Tccd1              82.6 °C
                      Tccd2              57.1 °C
                      Tctl               85.6 °C
▸ nvme                Sensor 2           53.9 °C
                      Composite          50.9 °C
                      Sensor 1           50.9 °C
▸ spd5118             temp               50.0 °C
▸ spd5118             temp               51.5 °C
▸ nvme                Composite          48.9 °C

Unit conversions verified: m°C → °C (50850 → 50.9°C), mV → V,
µW → W, mA → A. Unit tests: 12/12 pass (5 bench + 7 sensor).

Source state: 4885 LoC across 16 modules.
Redox stripped: 3.8 MB (SHA256 7a7c31bc...).

Docs: improvement plan §33, CONSOLE-TO-KDE §3.3.2 v1.9,
RATATUI-APP-PATTERNS §13.14 + §14 (16 modules, 12 tests).
2026-06-20 18:46:30 +03:00
vasilito d4cb65fcff tlc: phase 19 — column (rectangular) block operations
Adds MC's column-block selection to the editor. Algorithm
cross-references MC WEdit::column_highlight + MarkColumn* key
bindings in misc/mc.default.keymap.

Cursor changes:
  - SelectionMode::{Stream, Column} enum
  - column_anchor: Option<usize> (parallel to anchor)
  - column_selection_rect() → normalized ColumnRect
  - selected_text() / delete_selection() handle column mode:
      * Column copy text = rows joined by \n
      * Column delete strips rectangle cols from each line,
        cursor lands at top-left corner, anchor cleared
  - start_selection() / start_column_selection() are
    mutually exclusive (switching clears other anchor)
  - has_selection() / clear_selection() honor both modes

Keybindings (editor/handlers.rs):
  - Alt+Left/Right → MarkColumnLeft/Right (column horiz extend)
  - Alt+Up/Down   → MarkColumnUp/Down   (column vert extend)
  - Alt+PgUp/PgDn → MarkColumnPageUp/Down (column page extend)
  - Existing Shift+Arrow still produces stream selections

Renderer (editor/render.rs):
  - new line_selection_range() helper returns per-line byte
    range from either stream or column source
  - column cells get [editor] editmarked background highlight
  - syntect path naturally uses byte ranges, so column highlight
    composes with syntax coloring

Tests: 1119 passed (was 1117, +2 handler tests; cursor +7 tests).

PLAN.md: §15d row 21 marked  Done; Changelog entry added.
2026-06-20 18:41:10 +03:00
vasilito 32fac97c3f docs: ratatui §14 cleanup — collapse duplicated §14 headers + add v1.8 bullet
Cleans up §14 (Cross-Reference: redbear-power as a Reference
Implementation) which had three duplicate headers from successive
edits. Collapses to a single canonical version and adds the
v1.8-specific bullet:

  'Testable — bench module has 5 unit tests covering all stress
   modes + toggles'

Net change: -25 lines, +2 lines.

Source code for v1.8 (bench.rs + main.rs + render.rs) and full
docs for §32 + v1.8 in improvement plan + CONSOLE-TO-KDE plan
landed in commit d6ac3d1377 (qtbase bundled). This commit
completes the doc-only cleanup that didn't fit in that bundle.
2026-06-20 18:22:58 +03:00
vasilito d6ac3d1377 qtbase: add PKG_CONFIG_EXECUTABLE for cross-compilation CMake configure 2026-06-20 18:19:20 +03:00
vasilito e6cf3b7a81 libwayland: add -lc to LDFLAGS for relibc linking 2026-06-20 18:07:04 +03:00
vasilito bd51083a4e tlc: PLAN.md — log Phase 18 completion (all 16 dialogs migrated)
Phase 18 dialog popup shell migration is now complete. All 16
dialogs from the Phase 17 follow-up list have been migrated to
terminal::popup::render_popup, giving them all the MC-matching
rounded borders + drop shadow chrome.

Commits in the Phase 18 series:
  e4987256f7 — Phase 18a: filter, encoding, pattern, confirm,
                          overwrite, layout, panel_options, chattr
  2b2b5803ba — Phase 18c: permission, owner, connection, config,
                          compare, sort, progress
  c032c9a787 — menubar dropdown (via user commit)

Tree (full-screen directory tree) intentionally skipped — uses
the entire frame area, not a centered popup, so it does not
benefit from the popup shell or drop shadow.

Remaining Clear uses in the codebase are all legitimate:
  - menubar top F9 bar (not a popup)
  - tree.rs (full-screen dialog)
  - popup.rs (render_popup itself)
  - dialog.rs (Dialog widget body clear)

Tests: 1112 passed; release binaries build clean.
2026-06-20 18:01:45 +03:00
vasilito c032c9a787 config: disable relibc-phase1-tests (linker errors, not critical for ISO) 2026-06-20 17:55:47 +03:00
vasilito f15fbadf91 redbear-power: v1.7 — per-tick battery refresh (closes v1.6 forward work)
Closes the v1.6 forward-work item from §30.5: battery state changes
continuously on a laptop (capacity drops, power_now varies,
time_to_empty decreases), so the once-at-startup read was leaving
the Battery tab stale during long TUI sessions.

Updated app.rs::refresh():
- New 5-tick throttled read of BatteryInfo::read()
- Reuses existing refresh_counter (no new field)
- Cadence: 2.5 sec at default POLL_MS=500 (0.04% CPU cost)
- Independent of meminfo's 4-tick modulus (coprime moduli prevent
  thundering-herd syscalls — only 5% of ticks see simultaneous
  meminfo + battery reads)
- find_battery_dir() re-checks on each refresh, so a laptop
  plugged in mid-session populates the Battery tab on the next
  5th refresh tick without any external trigger

Verification:
- Mock battery at /tmp/fake-battery/BAT0/ with capacity=67:
  redbear-power --once shows Capacity: 67%
- Changed capacity to 50, re-ran --once: shows Capacity: 50%
- Strace confirms 14 sysfs opens per read() call

Cadence rationale (modulus 5 chosen):
- Every tick (500ms): 0.2% CPU — too aggressive
- Every 5th tick (2.5s): 0.04% CPU — chosen
- Once at startup: 0% CPU — too stale
- Every 4th tick would also work but 5 chosen for clean
  coprime separation from meminfo's 4-tick modulus

Build: same 3.8 MB stripped Redox binary (single if branch added).
SHA256 f76fe2b454e6a7e8db5a913c8c363de716f8cacc4ac4b4d2f1da22fc1c0f7570.

Docs: improvement plan §31, CONSOLE-TO-KDE §3.3.2 v1.7,
RATATUI-APP-PATTERNS §13.19 (coprime moduli pattern) + §14.
2026-06-20 17:55:00 +03:00
vasilito 2b2b5803ba tlc: phase 18c — migrate 7 more dialogs to render_popup
Continue Phase 18 mechanical migration of centered dialogs to the
shared terminal::popup::render_popup() shell (MC-matching rounded
borders + drop shadow):

  permission, owner, connection_dialog, config_dialog,
  compare, sort_dialog, progress

All 7 share the same pattern: inline Clear + Block + title replaced
with render_popup() + centered_cols_rect()/centered_percent_rect().
Title color now derives from [dialog] dtitle via the unified shell.

compare.rs also dropped its local centered_rect helper (used only
for the popup shell; the body Block stays inline since it's a
sub-frame, not the popup shell).

Tree (full-screen directory tree dialog) intentionally skipped — it
uses the entire frame area, not a centered popup, so it does not
benefit from the popup shell or shadow.

Tests: 1112 passed (no regressions).
2026-06-20 17:49:50 +03:00
vasilito a4dc44a8e0 redbear-power: v1.6 — Battery tab (power_supply)
Adds the 5th tab in the multi-view system: Battery, reading
power_supply data from /sys/class/power_supply/BAT*/ on Linux hosts.

New module battery.rs (128 lines):
- BatteryInfo struct with 15 fields (available, name, status,
  capacity_percent, energy_now_wh, energy_full_wh, power_now_w,
  voltage_now_v, time_to_empty_s, time_to_full_s, cycle_count,
  technology, model_name, manufacturer, serial_number)
- find_battery_dir() scans /sys/class/power_supply/ for type==Battery
- read() populates all fields with inline µWh→Wh, µV→V conversion
- health_percent() computes current_charge / full_charge ratio
- display/display_u32/display_u64/display_f64 helpers
- format_duration(secs) — Xh Ym / Ym Zs / Zs
- RBP_BATTERY_PATH env override (testing + dev workflow)

Updated app.rs:
- New field battery: BatteryInfo, initialized once in App::new()
- TabId::Battery variant (5th tab)
- TabId::next() cycles PerCpu → System → Info → Motherboard → Battery

Updated render.rs:
- New render_battery_panel(app, focused) with 3 section blocks
  (Identity / State / Power). If !available, shows
  '(no battery detected — /sys/class/power_supply/BAT* not present)'.
- render_tab_bar() updated for 5 tabs with hotkey 1/2/3/4/5 mapping
- render_once now dumps Battery panel for headless verification

Updated main.rs:
- mod battery; declaration
- New dispatch arm TabId::Battery => render_battery_panel
- Hotkey 5 jumps to Battery tab directly
- render_battery_panel added to imports

Mock battery smoke test (RBP_BATTERY_PATH=/tmp/fake-battery):
- Manufacturer: MSI, Model: MPG X670E, Technology: Li-ion, Cycles: 127
- Status: Discharging, Capacity: 67%, Health: 67%
- Energy: 33.50 Wh / 50.00 Wh (µWh→Wh conversion verified)
- Power: 8.50 W, Voltage: 12.50 V (µV→V conversion verified)
- Time to empty: 3h 0m, Time to full: ? (correctly hidden when 0)

On desktop (no battery):
(no battery detected — /sys/class/power_supply/BAT* not present)

Source state: 4359 LoC across 15 modules (v1.5: 4117/14).
Redox stripped: 3.8 MB (SHA256 c6fca172...).

Docs: improvement plan §30, CONSOLE-TO-KDE §3.3.2 v1.6,
RATATUI-APP-PATTERNS §13.18 + §14.
2026-06-20 17:44:11 +03:00
vasilito e4987256f7 tlc: phase 18a — migrate 8 dialogs to render_popup
Same mechanical pattern as Phase 17 skin_dialog. Each dialog now
inherits the MC-matching rounded borders + drop shadow from the
shared terminal::popup::render_popup() shell:

  filter_dialog, encoding_dialog, pattern_dialog, confirm_dialog,
  overwrite_dialog, layout_dialog, panel_options, chattr_dialog

Changes per file:
  - Remove import of Block, Borders, Clear
  - Add import of centered_cols_rect, render_popup
  - Replace inline geometry+Clear+Block with centered_cols_rect()
    + render_popup() call
  - Title no longer needs manual styling (render_popup applies
    [dialog] dtitle colors)

confirm_dialog also dropped its BorderType::Double variant (now
matches the rest of TLC's rounded look); removed its now-unused
local centered_rect helper.

Tests: 1112 passed (no regressions; same count as pre-Phase 18).
2026-06-20 17:31:58 +03:00
vasilito 22770719da tlc: add missing ratatui imports (Clear, Block, Borders) in pattern_dialog.rs 2026-06-20 17:23:19 +03:00
vasilito 55962aa1ab build: remove kwin from PRECOOK_PKGS (blocked by QML/Quick JIT, redbear-compositor provides compositor) 2026-06-20 17:21:27 +03:00
vasilito 6a7983f576 qtbase: ensure libredbear-qt-strtold-compat is in sysroot usr/lib for linking 2026-06-20 16:54:23 +03:00
vasilito b354edad97 redbear-power: v1.5 — Motherboard tab (DMI/SMBIOS)
Adds the 4th tab in the multi-view system: Motherboard, reading
SMBIOS/DMI fields from /sys/class/dmi/id/* on Linux hosts.

New module dmi.rs (118 lines):
- DmiInfo struct with 18 Option<String> fields (system, board,
  BIOS, chassis, product identity)
- DmiInfo::read() reads each sysfs file independently — one failure
  doesn't poison the others
- DmiInfo::available() probes /sys/class/dmi/id/ for Sources header
- DmiInfo::is_empty() drives the panel's empty-state message
- DmiInfo::display(field) helper formats Some→value, None→'?'

Updated app.rs:
- New field dmi: DmiInfo, initialized once in App::new() (no per-tick
  refresh — DMI is static)
- TabId::Motherboard variant (4th tab)
- TabId::next() cycles PerCpu → System → Info → Motherboard → PerCpu

Updated render.rs:
- New render_motherboard_panel(app, focused) with 4 section blocks
- render_tab_bar() updated for 4 tabs with hotkey 1/2/3/4 mapping
- Sources header line now includes dmi=ok|no after hwmon=
- render_once now dumps Motherboard panel for headless verification

Updated main.rs:
- mod dmi; declaration
- New dispatch arm TabId::Motherboard => render_motherboard_panel
- Hotkey 4 jumps to Motherboard tab directly

Linux host smoke test (Manjaro, MSI MPG X670E CARBON WIFI):
- Manufacturer: Micro-Star International Co., Ltd.
- Product: MS-7D70
- Board: MPG X670E CARBON WIFI (MS-7D70), Version 1.0
- BIOS: AMI, 1.74, 05/12/2023, Release 5.26
- Chassis: Type 3 (Desktop)
- Serial/UUID correctly report '?' (root-only readable)

Sources header: MSR=ok PSS=no load=ok gov=ok hwmon=ok dmi=ok

Source state: 4117 LoC across 14 modules (v1.4: 3864/13).
Redox stripped: 3.7 MB (SHA256 c44d508c...).

Docs: improvement plan §29, CONSOLE-TO-KDE §3.3.2 v1.5,
RATATUI-APP-PATTERNS §13.17 + §14.

Note: dmi.rs + app.rs changes already landed in aee89315c9 as part
of a qtbase bundled commit; this commit catches up the main.rs
dispatch arm + render.rs panel wiring + all docs that were missing.
2026-06-20 16:48:39 +03:00
vasilito aee89315c9 qtbase: add explicit dbus include paths for cross-compilation 2026-06-20 16:38:02 +03:00
vasilito 2d77249d60 tlc: PLAN.md — log Phase 17 skin_dialog + 16 follow-up candidates
Document Phase 17 (skin_dialog popup shell migration) and enumerate
the 16 remaining dialogs that still bypass render_popup:

  sort, compare, overwrite, filter, tree, encoding, connection,
  layout, owner, panel_options, pattern, confirm, config,
  permission, chattr, progress

Each is ~50-100 LOC of refactor work (replace inline Clear+Block
with render_popup call). Same premium chrome (rounded borders,
MC-matching drop shadow) as Phase 17.
2026-06-20 16:36:11 +03:00
vasilito effc45d26d tlc: phase 17 — skin_dialog adopts shared popup shell
Migrate src/filemanager/skin_dialog.rs::render() from the bespoke
Clear+Block shell (no shadow, square borders) to
terminal::popup::render_popup (rounded borders + MC-matching drop
shadow + centered layout).

This makes skin_dialog visually consistent with all 13 other TLC
dialogs that already use render_popup. The /tmp/5.png screenshot
(showing the skin selector without shadow) is now fixed — every
TLC dialog has identical premium chrome.

Deleted:
  - Duplicate 'centered_rect' helper (replaced by popup::centered_percent_rect)
  - Inline Block construction
  - Manual Clear render

Added:
  - render_drops_shadow_outside_popup test asserts the bottom-right
    cell carries theme.shadow background (assertion of MC's
    tty_draw_box_shadow algorithm at the dialog level).

Tests: 1112 passed (was 1111, +1).
2026-06-20 16:32:34 +03:00