tui: global script progress + dashboard source/restore work

Opening a script from the dashboard did nothing visually: the tick driving the
line-by-line loader was only handled in the console case, and the Computing…
overlay was console-only. Move both to the global layer — ticks now process on
any screen (the dashboard updates live as the script loads) and the Computing…
box overlays whatever screen is active. Add an 'r' dashboard shortcut to
restore a snapshot via the file picker (open mode, like 'o'). Dashboard help
hints (loaded + empty state) updated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-03 19:02:13 +02:00
parent c70e767cf1
commit 29cb353d75
3 changed files with 38 additions and 16 deletions

View File

@@ -45,6 +45,7 @@ Component Tui::BuildDashboardScreen() {
Element early_help = RenderHelpPanel("dashboard", {
{"c", "console"},
{"o", "open/run a script"},
{"r", "restore a snapshot"},
{"a", "analyze"},
{"h", "help screen"},
{"q", "quit"},
@@ -57,8 +58,8 @@ Component Tui::BuildDashboardScreen() {
separator(),
hbox({
vbox({
text(" no system loaded — run 'new' or 'restore <file>'") | dim,
text(" (press 'o' to open a script, 'c' for the console, Ctrl-P for the palette)") | dim,
text(" no system loaded") | dim,
text(" (press 'o' open a script · 'r' restore a snapshot · 'c' console · Ctrl-P palette)") | dim,
filler(),
}) | flex,
separator(),
@@ -312,6 +313,7 @@ Component Tui::BuildDashboardScreen() {
{"x", "export"},
{"o", "open/run a script"},
{"s", "save system"},
{"r", "restore a snapshot"},
{"PgUp", "scroll up"},
{"PgDn", "scroll down"},
{"Home", "scroll top"},

View File

@@ -89,18 +89,8 @@ Component Tui::BuildMainScreen(ScreenInteractive &screen) {
}) | flex,
}) | border;
if (loading) {
int total = (int)loading_lines.size();
std::string progress = std::to_string(loading_executed) + " / "
+ std::to_string(total) + " lines";
auto modal = vbox({
text(" Computing… ") | bold | center,
separator(),
text(loading_filename) | center,
text(progress) | center,
}) | borderDouble | size(WIDTH, GREATER_THAN, 40);
return dbox({base, modal | center});
}
// The "Computing…" overlay is rendered globally in Run(), so it shows
// on whatever screen is active while a script loads.
return base;
});
}

View File

@@ -5,6 +5,7 @@
#include <ftxui/component/component.hpp>
#include <ftxui/component/event.hpp>
#include <ftxui/component/screen_interactive.hpp>
#include <ftxui/dom/elements.hpp>
using namespace ftxui;
@@ -58,7 +59,28 @@ void Tui::Run() {
auto with_error = with_confirm
| Modal(BuildErrorModal(), &error_open);
auto root = CatchEvent(with_error, [this](Event e) {
// Global "Computing…" overlay while a script loads — visible on any screen
// (not just the console), so opening a script from the dashboard shows
// progress instead of looking frozen.
auto with_loading = Renderer(with_error, [this, with_error] {
Element base = with_error->Render();
if (!loading) return base;
std::string progress = std::to_string(loading_executed) + " / "
+ std::to_string((int)loading_lines.size()) + " lines";
Element modal = vbox({
text(" Computing… ") | bold | center,
separator(),
text(loading_filename) | center,
text(progress) | center,
}) | borderDouble | size(WIDTH, GREATER_THAN, 40);
return dbox({base, modal | center});
});
auto root = CatchEvent(with_loading, [this](Event e) {
// Source ticks drive the line-by-line loader; handle them on ANY screen
// so `source` works from the dashboard, not only the console.
if (e == Event::Special("\x02tick")) { ProcessNextSourceLine(); return true; }
// Modals own their events while open. Error modal sits on top.
if (error_open || confirm_open || palette_open
|| sigtype_dialog_open || file_dialog.open) return false;
@@ -119,6 +141,15 @@ void Tui::Run() {
});
return true;
}
if (e == Event::Character("r")) { // restore a saved system
OpenFileDialog("Restore system — load a snapshot",
"dashboard.restore", "", {},
[this](const std::string &path) {
Dispatch("restore " + path);
},
/*confirm_overwrite=*/false); // opening, not saving
return true;
}
return false;
case 3: // explore
@@ -153,7 +184,6 @@ void Tui::Run() {
return false;
default: // 0: main (console / log view)
if (e == Event::Special("\x02tick")) { ProcessNextSourceLine(); return true; }
if (e == Event::Escape) {
if (!pending.empty()) { CancelPending(); return true; }
screen_idx = 4; return true;