diff --git a/crates/web/src/profile/controller.rs b/crates/web/src/profile/controller.rs index 6215b5b2..66dcc852 100644 --- a/crates/web/src/profile/controller.rs +++ b/crates/web/src/profile/controller.rs @@ -46,7 +46,7 @@ pub fn use_profile_controller() -> ( let write = use_context::().expect("AppWriteSignals in context"); let read_sig = app_state.profile.open; let write_sig = write.profile.set_open; - install_listeners_once(write_sig); + install_listeners_once(read_sig, write_sig); (read_sig, write_sig) } @@ -55,7 +55,10 @@ pub fn use_profile_controller() -> ( /// Idempotent — the helper tags `` /// so repeat calls are no-ops. In practice the root `` calls /// [`use_profile_controller`] once, which calls this helper once. -fn install_listeners_once(set_open: WriteSignal>) { +fn install_listeners_once( + open: ReadSignal>, + set_open: WriteSignal>, +) { let Some(win) = web_sys::window() else { return }; let body = match win.document().and_then(|d| d.body()) { Some(b) => b, @@ -110,10 +113,10 @@ fn install_listeners_once(set_open: WriteSignal>) { .ok(); on_close.forget(); - // ESCAPE — close on Escape anywhere. + // ESCAPE — close on Escape, but only when a profile is actually open. let on_esc = Closure::::new(move |ev: web_sys::Event| { if let Ok(ke) = ev.dyn_into::() { - if ke.key() == "Escape" { + if ke.key() == "Escape" && open.with(Option::is_some) { set_open.set(None); } } diff --git a/crates/worker/src/config.rs b/crates/worker/src/config.rs index b8bef856..7894ddff 100644 --- a/crates/worker/src/config.rs +++ b/crates/worker/src/config.rs @@ -17,6 +17,7 @@ pub struct WorkerConfig { impl WorkerConfig { /// Create a config for testing. + #[cfg(test)] pub fn test_config() -> Self { Self { identity_path: "/tmp/test-worker.key".to_string(),