feat(desktop): show a welcome page when the server is unreachable #114

Merged
David merged 1 commit from feat/desktop-welcome-page into main 2026-05-15 03:34:17 +02:00
Owner

Summary

Fix the blank-window screenshot the user just hit: without a fallback, lets-chat-desktop opens, Wry tries to load LETS_CHAT_SERVER_URL (default http://localhost:8080), gets a connection-refused / DNS / TLS / timeout failure, and renders a blank window with no hint at what went wrong. Title bar says lets-chat v0.1.0 (unknown), the rest is empty.

Probe the configured URL at startup with a 3s ureq::get and choose what Wry loads:

  • Reachable (any HTTP response, 2xx through 5xx - the server answered so the webview will see the same response and is the right place to render it): build the webview with with_url(&url) exactly like before.
  • Transport failure (connect refused, DNS, TLS, timeout): build the webview with with_html(...) against a small embedded welcome page.

Welcome page

Single-card layout, system font, plain inline CSS, no external assets. Contents:

  • "lets-chat" heading + "Desktop client" subtitle.
  • Red-bordered alert showing the URL that failed and the underlying transport error string (HTML-escaped).
  • Three-step recovery list: server reachable -> set LETS_CHAT_SERVER_URL -> restart.
  • "Try again" button that re-navigates to the configured URL, so a server-not-yet-up case clears without restarting the binary.
  • Footer with lets-chat-desktop <version> · <git-hash> for support.

include_str!'d into the binary so the page works on a freshly-installed standalone .exe with no network. Every substituted value (URL, reason, version, git-hash) goes through a small html_escape so a hostile server URL can't inject markup.

Files

  • desktop/src/welcome.rs - probe + HTML render.
  • desktop/src/welcome.html - the page template.
  • desktop/src/main.rs - wire the probe between set_linux_gtk_env() and event_loop.run. CLI subcommands (--version, --check-update, --update) exit before the probe runs, so they are unaffected and don't pay the network cost.

Test plan

  • just check-desktop, just check-fmt, and ./dev/cargo-desktop clippy -p lets-chat-desktop -- -D warnings are all green; the only warnings are the pre-existing Cargo.toml: file /work/server/src/main.rs found to be present in multiple build targets from the workspace, untouched.
  • Release binary builds and --version still prints the banner.
  • Live: run with no server up (LETS_CHAT_SERVER_URL=http://localhost:55555 lets-chat-desktop) and confirm the welcome card renders with the failing URL and a connection-refused reason instead of a blank window.
  • Live: run with the server up (the normal happy path) and confirm the login page renders as before (no regression on the happy path).
  • Live: "Try again" button reloads against the configured URL after starting the server externally.
## Summary Fix the blank-window screenshot the user just hit: without a fallback, `lets-chat-desktop` opens, Wry tries to load `LETS_CHAT_SERVER_URL` (default `http://localhost:8080`), gets a connection-refused / DNS / TLS / timeout failure, and renders a blank window with no hint at what went wrong. Title bar says `lets-chat v0.1.0 (unknown)`, the rest is empty. Probe the configured URL at startup with a 3s `ureq::get` and choose what Wry loads: - **Reachable** (any HTTP response, 2xx through 5xx - the server answered so the webview will see the same response and is the right place to render it): build the webview with `with_url(&url)` exactly like before. - **Transport failure** (connect refused, DNS, TLS, timeout): build the webview with `with_html(...)` against a small embedded welcome page. ## Welcome page Single-card layout, system font, plain inline CSS, no external assets. Contents: - "lets-chat" heading + "Desktop client" subtitle. - Red-bordered alert showing the URL that failed and the underlying transport error string (HTML-escaped). - Three-step recovery list: server reachable -> set `LETS_CHAT_SERVER_URL` -> restart. - "Try again" button that re-navigates to the configured URL, so a server-not-yet-up case clears without restarting the binary. - Footer with `lets-chat-desktop <version> · <git-hash>` for support. `include_str!`'d into the binary so the page works on a freshly-installed standalone `.exe` with no network. Every substituted value (URL, reason, version, git-hash) goes through a small `html_escape` so a hostile server URL can't inject markup. ## Files - `desktop/src/welcome.rs` - probe + HTML render. - `desktop/src/welcome.html` - the page template. - `desktop/src/main.rs` - wire the probe between `set_linux_gtk_env()` and `event_loop.run`. CLI subcommands (`--version`, `--check-update`, `--update`) exit before the probe runs, so they are unaffected and don't pay the network cost. ## Test plan - [x] `just check-desktop`, `just check-fmt`, and `./dev/cargo-desktop clippy -p lets-chat-desktop -- -D warnings` are all green; the only warnings are the pre-existing `Cargo.toml: file /work/server/src/main.rs found to be present in multiple build targets` from the workspace, untouched. - [x] Release binary builds and `--version` still prints the banner. - [ ] Live: run with no server up (`LETS_CHAT_SERVER_URL=http://localhost:55555 lets-chat-desktop`) and confirm the welcome card renders with the failing URL and a connection-refused reason instead of a blank window. - [ ] Live: run with the server up (the normal happy path) and confirm the login page renders as before (no regression on the happy path). - [ ] Live: "Try again" button reloads against the configured URL after starting the server externally.
feat(desktop): show a welcome page when the server is unreachable
All checks were successful
Check / clippy + fmt + tests (pull_request) Successful in 1m6s
f96fc35792
Without this the lets-chat-desktop window opens, Wry tries to load LETS_CHAT_SERVER_URL (default `http://localhost:8080`), gets a connection refused / timeout / DNS failure, and renders a blank window with no hint at what went wrong. Screenshot from the user: title bar reads "lets-chat v0.1.0 (unknown)" and the rest of the window is empty.

Probe the configured URL at startup with a 3s `ureq::get` and choose what Wry loads based on the result:

- 2xx / 3xx response, or any 4xx/5xx (the server answered, so the webview will see the same response and is the right place to render it): build the webview with `with_url(&url)` exactly like before. No new latency on the happy path beyond the one extra HTTP request, which a healthy lets-chat server answers in milliseconds.
- Transport-layer failure (connect refused, DNS, TLS, timeout): build the webview with `with_html(...)` against a small embedded welcome page that tells the user which URL failed, the underlying error string, the three steps to recover (server reachable -> set `LETS_CHAT_SERVER_URL` -> restart), and the lets-chat-desktop version + git hash for support. The page has a single "Try again" button that re-navigates to the configured URL so a transient server-not-yet-up case clears without restarting the binary.

New files: `desktop/src/welcome.rs` (probe + HTML render, with `html_escape` on every substituted value so a maliciously-crafted server URL can't inject markup) and `desktop/src/welcome.html` (the page template, system-font, single-card layout, plain inline CSS, no external assets). The template is `include_str!`'d into the binary so the page works on a freshly-installed standalone .exe with no network.

Wired into `main.rs::main` between `set_linux_gtk_env()` and `event_loop.run`. The CLI subcommands (`--version`, `--check-update`, `--update`) exit before the probe runs, so they are unaffected and don't pay the network cost.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
David merged commit f1526a933b into main 2026-05-15 03:34:17 +02:00
David deleted branch feat/desktop-welcome-page 2026-05-15 03:34:17 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/lets-chat!114
No description provided.