Commit Graph
6 Commits
Author SHA1 Message Date
ddidderr 9171560ad4 fix(launcher): authorize window destruction after close drains
A native WM_DELETE_WINDOW reproduction completed the frontend drain and then
failed with "window.destroy not allowed". All three windows lacked the destroy
permission used by Tauri's onCloseRequested wrapper. Removing the listener had
previously let a second click bypass that denied IPC; retaining the listener
made every click fail. The frontend was not stuck waiting on its own listener.

Grant window destruction to the three configured application windows. Keep the
existing frontend drains, early peer cancellation, and final runtime/task joins.
Test the application's actual generated RuntimeAuthority, including expanded
plugin defaults, instead of assuming a mocked successful destroy proves access.

Explicitly include generated capabilities and ACL manifests in the context
constructor's rustc dependencies. The configured compiler cache reused the old
library after a permission-only edit because Tauri's macro reads these files
without recording compiler dependencies. A remove/restore native probe now
rebuilds with the correct permission in both directions.

Document the complete ownership chain and failure evidence. Add a PID-checked
X11 WM_DELETE_WINDOW helper for repeatable close-button probes without killing
the process or bypassing the frontend boundary.

Test Plan:
- Native baseline: destroy denied and process remained alive after one request.
- Resolved-ACL regression failed before the permission fix and passes afterward.
- Native main/companion close probes: one request per window; normal process exit.
- Permission-only rebuild with compiler cache: normal exit in 197 ms.
- Production executable: normal exit in 43 ms; QUIC port released and rebound.
- just test: 797 passed on unchanged rerun after one initial subprocess fixture
  startup-marker timeout, before that test exercised cancellation.
- just frontend-test: 99 passed.
- just fmt, just clippy, just build, and git diff --cached --check: passed.
- Native helper compiled with -Wall -Wextra -Werror.
- Native probes ran on Linux X11/XWayland; Windows/macOS were not measured.
2026-09-12 21:36:06 +02:00
ddidderr 0ed04f64e9 fix(tauri): remove unused frontend shell-open authority
The main webview retained `shell:allow-open` even though the frontend never
uses the shell plugin directly. File-manager opening already flows through the
`open_game_files` command, which checks catalog membership and containment.

Remove only the frontend permission. The Rust shell plugin and dependency stay
available for the checked backend open operation and bundled unrar sidecar.

Test Plan:
- `just build-fixture` -- passed, including the frontend build and Tauri
  capability validation.
- `git diff --cached --check` -- passed.
2026-09-12 12:16:00 +02:00
ddidderr 9d14e63613 fix: harden application log viewer
Add an Application Logs window backed by a bounded persistent main log file.
The viewer loads history from lanspread.log, subscribes to live INFO/WARN/ERROR
log events, supports filtering/copy/pause controls, and keeps the menu/window
routing separate from the unpack log viewer.

The backend sink now owns serialized access to the log file. History reads and
append-time trimming use the same sink lock, so opening the logs window cannot
race with a concurrent write and rewrite away a freshly appended line. The sink
also keeps a persistent file handle instead of reopening the file for each
captured event.

Live log events carry sink-local sequence ids. The frontend uses the history
watermark plus returned history line counts to suppress live events that were
already included in the history response, while preserving buffered rows that
were trimmed out of the history file. Auto-scroll now follows the last visible
row identity, so it continues following after the in-memory cap keeps the row
count stable.

No timestamp code change was needed. On the Linux dev host, a temporary probe
showed time::OffsetDateTime::now_local() returning +02:00 while UTC was +00:00,
matching the host CEST offset.

Test Plan:
- just fmt
- just frontend-test
- just test
- just clippy
- just build
- git diff --cached --check
- temporary Linux probe of OffsetDateTime::now_local() showed local +02:00

Refs: none
2026-06-07 18:59:05 +02:00
ddidderrandClaude Opus 4.7 b35755f4e6 feat(tauri): add unpack logs viewer for unrar attempts
Captures stdout, stderr, exit status and start/finish timestamps for every
unrar sidecar invocation and exposes them through a dedicated "Unpack Logs"
window. Triggered by the need to debug why a particular game's archive
failed to extract -- previously the only artifact of a failed unpack was a
log line in the Tauri process stdout, which is awkward to inspect on an
end-user machine.

Implementation:

* `LanSpreadState` gains an in-memory ring buffer (`unpack_logs`) capped at
  `MAX_UNPACK_LOGS` (100). The previous monolithic `do_unrar` is split into
  `prepare_unrar_paths` and `run_unrar_sidecar` so every failure path (mkdir
  failure, canonicalize failure, non-UTF-8 destination, sidecar spawn error,
  non-zero exit) records an `UnpackLogEntry` before bailing.
* A `get_unpack_logs` Tauri command returns the current snapshot; an
  `unpack-logs-updated` event is emitted after every write so the viewer can
  refresh without polling.
* The React `App` component now routes on `?view=unpack-logs` and renders a
  dedicated `UnpackLogsWindow`. The main window opens the viewer via
  `WebviewWindow` with label `unpack-logs`; an existing window is focused
  instead of being recreated.

Capability scoping: the new window is given its own capability file
(`capabilities/unpack-logs.json`) granting only `core:default`. The main
capability is unchanged in window scope and only gains the two permissions
the main window itself needs (`core:window:allow-set-focus` to focus an
existing log window, `core:webview:allow-create-webview-window` to spawn
it). Splitting the capability keeps the log window from inheriting
`shell:allow-open`, `dialog:default` and `store:default`, which it has no
reason to use.

Known limitations (intentionally out of scope here):

* Logs are process-local; they vanish on app restart. Persistence can be
  added later if it turns out users want to inspect failures across runs.
* Entries are presented as a flat chronological list identified by archive
  path. No per-game grouping or filtering yet -- the archive filename is
  usually enough to identify the game in practice.
* The `unpack-logs-updated` event carries no payload; the viewer re-fetches
  the full snapshot on every notification. Acceptable given the 100-entry
  cap, but a payload-bearing event would be cheaper if the cap grows.

Test plan:

* `just clippy` and `just build` are clean.
* Manual: start the GUI, point it at a games directory containing at least
  one peer-hosted game, trigger an install, then click "Unpack Logs". The
  window should show one entry per unrar invocation with stdout, stderr,
  status code and timestamps; stderr/error lines render in the warning
  color. Triggering further unpacks should update the open window live via
  the `unpack-logs-updated` event without manual refresh.
* Negative path: rename or remove the archive between handshake and
  extraction to force a canonicalize failure; confirm a failed entry with
  the corresponding stderr appears in the viewer.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-19 17:27:59 +02:00
ddidderr 942eb8003e [improve] set game dir on client -> updates Play/Install button based on games existing 2024-11-14 19:41:55 +01:00
ddidderr 5d45c4ce4b [ui] change framework from Tauri Leptos to Tauri Vanilla (Typescript) and React 2024-11-13 22:15:04 +01:00