Fix detached-window IPC scoping and pane-transfer session loss
- capabilities/default.json: extend window scope to "pane-window-*" so detached windows can invoke/listen (fixes blank panes B2-B5). - App.tsx: memoize the destructive take_pending_window_init read at module scope so React StrictMode's double mount-effect doesn't consume the transfer payload twice and lose the adopted PTY session. - lib.rs: add `use tauri::Manager;` for Window::app_handle() in on_window_event. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
681d15fdc3
commit
bea6cf2977
4 changed files with 54 additions and 2 deletions
31
memory.md
31
memory.md
|
|
@ -87,6 +87,37 @@ Two big features the user asked for in one session. Three commits on `main`: `1a
|
|||
|
||||
**Phase 2 verification needed** (user, on Windows host):
|
||||
1. `cd D:\dev\tiletopia\src-tauri && cargo check` — the Rust changes have to compile. **Note: `Cargo.toml` lives in `src-tauri/`, NOT the project root** (Tauri layout). I got this wrong in the original verification steps; user had to point it out. Added a preflight-checks rule to global `~/claude/CLAUDE.md`. Watch in the check output for: tauri 2 `WebviewWindowBuilder::new` signature, `on_window_event` handler closure types, my `Arc<Self>` method receiver style on WindowsState.
|
||||
|
||||
**Uncommitted local fix (as of 2026-05-28 wrap-up):**
|
||||
|
||||
`src-tauri/src/lib.rs` has an added `use tauri::Manager;` import — needed because `Window::app_handle()` is a trait method (Manager trait) used in the new `on_window_event` handler. Same pattern as the `Emitter` trait stumble in v0.3.0. Cargo check went clean after this. **Not committed yet** — user wanted to smoke-test the feature first, then found the bug list below. Commit this fix at the same time as the bug-fix commit.
|
||||
|
||||
**Detached-window bug list (deferred — user will resume):**
|
||||
|
||||
Smoke test on Windows revealed bugs specific to detached (non-main) windows. Main window is unaffected.
|
||||
|
||||
- **B1** — Drag-out has no ghost image during drag (cosmetic, user OK with deferring).
|
||||
- **B2** — Detached window: transferred pane is blank, "idle" within 5s. No input, no output.
|
||||
- **B3** — Detached window: shell-picker swap (Ubuntu → PowerShell → Ubuntu) doesn't spawn a working terminal. Fresh `spawn_pane` call from the detached window — toolbar updates but no PTY output.
|
||||
- **B4** — Detached window: new tab (Ctrl+T or + button) creates the tab but no terminal. Same blank/idle symptom.
|
||||
- **B5** — Right-click "Move to new window" produces the same broken detached window as drag-out. Confirms the bug is detached-window-scoped, not gesture-scoped.
|
||||
- **B6** (control) — Main window: new tab, new pane, normal ops all work.
|
||||
|
||||
**Strongest single hypothesis** for B2–B5: **Tauri 2's capability system gates `invoke` and `listen` per window-label.** Default capability config in `src-tauri/capabilities/default.json` (or similar) usually scopes to `"windows": ["main"]`. Newly-built `pane-window-*` labels match nothing → all IPC and events silently fail. One config fix (add wildcard window pattern, or programmatically attach a capability to each new window before `.build()`) would explain ALL of B2-B5 in one go.
|
||||
|
||||
**Where to look first when resuming:**
|
||||
1. `src-tauri/capabilities/*.json` — read the existing capability config to confirm scoping.
|
||||
2. Try `"windows": ["main", "pane-window-*"]` (Tauri 2 supports glob patterns in capability window targets).
|
||||
3. If that doesn't work: `AppHandle::add_capability(...)` on the new window before `.build()` in `commands.rs::create_pane_window`.
|
||||
4. Verify by re-testing B4 first (simplest: fresh new tab in a detached window — needs only `invoke("spawn_pane")` and `listen("pane://...")` to work).
|
||||
|
||||
**RESOLVED 2026-05-28 (resume session) — two root causes, both fixed:**
|
||||
|
||||
- **B2–B5 (blank/dead detached windows) = the capability hypothesis, confirmed.** `src-tauri/capabilities/default.json` had `"windows": ["main"]`; detached labels are `pane-window-<micros>` (commands.rs:122) → matched nothing → every `invoke`/`listen` silently denied. Fix: `"windows": ["main", "pane-window-*"]`. Tauri 2 glob pattern works; one line cleared all four. (App-defined commands aren't individually permission-gated — they're available to any window the capability is *applied* to, i.e. listed in `windows`.)
|
||||
- **Session-loss-on-adopt (surfaced after B2–B5 cleared) = destructive read × StrictMode.** Once IPC worked, drag-out still spawned a FRESH pty (new id, tab named "Default", status `alive` not `adopted`) instead of adopting. Cause: `take_pending_window_init` is a **destructive** backend read (`by_label.remove`); React StrictMode runs the mount effect twice in dev — pass 1 consumed the payload then bailed on the `cancelled` flag, pass 2 got `null` → fell back to `singletonEnvelope` (fresh "Default" + fresh spawn). The `cancelled`-flag pattern guards against *using* stale async results but cannot un-consume a destructive backend call. Fix: module-level memoized `consumePendingWindowInit()` in App.tsx so the take fires **exactly once per window** and both StrictMode passes share the payload. Dev-only symptom (prod StrictMode doesn't double-invoke effects) but fixed for robustness. **Lesson: any destructive/once-only backend read called from a mount effect must be memoized at module scope, not just guarded by `cancelled`.**
|
||||
- **Verified:** user confirmed adopt works (scrollback intact, same pane id, live input). `tsc -b` clean. B1 (drag ghost image) still deferred — cosmetic.
|
||||
- Committed together with the carried-over `use tauri::Manager;` lib.rs import.
|
||||
|
||||
2. `pnpm tauri dev` — smoke test:
|
||||
- Existing workspace loads as one tab named "Default" ✓ migrate
|
||||
- Ctrl+T spawns new tab with default-shell pane
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue