From e1eb16f90d89d57b6c0a1003cb2a9468c121c530 Mon Sep 17 00:00:00 2001 From: clover caruso Date: Fri, 2 Oct 2026 21:17:44 -0700 Subject: [PATCH] fix: Open Shared Notebook sits in the sidebar's footer and beside Open Existing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With a notebook open, Open Shared Notebook was only in the File menu and the command palette (⌘⇧P), both of which work, but people looked where Open Existing is. The sidebar's footer now offers Open Shared… between Open Existing and Options, and the welcome screen lists it straight after Open Existing. Assisted-by: claude-opus-5.5 --- crates/snowbound/src/sidebar.rs | 23 ++++++++++++++++------ crates/snowbound/tests/replay.rs | 33 ++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 6 deletions(-) diff --git a/crates/snowbound/src/sidebar.rs b/crates/snowbound/src/sidebar.rs index 53d25b69159c81672f93e2eea935bd39acaf0ada..21bb2c4299646f946b182c018a09f3545741dfa2 100644 --- a/crates/snowbound/src/sidebar.rs +++ b/crates/snowbound/src/sidebar.rs @@ -39,6 +39,8 @@ pub enum Action { Fold(String), NewNotebook, OpenNotebook, + #[cfg(feature = "live")] + OpenShared, /// Signs in again to the notebook opened from its server at this location. SignIn(String), Options, @@ -273,6 +275,13 @@ fn sidebar( "Open Existing", Action::OpenNotebook, ), + #[cfg(feature = "live")] + ( + "shared", + Leading::Icon(art::LINK), + "Open Shared…", + Action::OpenShared, + ), ( "options", Leading::Icon(art::OPTIONS), @@ -843,6 +852,8 @@ impl crate::State { Some(Action::Renamed(keep)) => self.finish_renaming(keep), Some(Action::NewNotebook) => self.commands.push(crate::Command::NewNotebook), Some(Action::OpenNotebook) => self.commands.push(crate::Command::OpenNotebook), + #[cfg(feature = "live")] + Some(Action::OpenShared) => self.open_shared(), Some(Action::SignIn(location)) => self .commands .push(crate::Command::OpenFromServer(Some(location))), @@ -1252,12 +1263,6 @@ impl crate::State { "Open Existing", crate::Command::OpenNotebook, ), - ( - "server", - Leading::Icon(art::SERVER), - "Open Notebook from Server…", - crate::Command::OpenFromServer(None), - ), #[cfg(feature = "live")] ( "shared", @@ -1265,6 +1270,12 @@ impl crate::State { "Open Shared Notebook…", crate::Command::OpenShared, ), + ( + "server", + Leading::Icon(art::SERVER), + "Open Notebook from Server…", + crate::Command::OpenFromServer(None), + ), ] .into_iter() .chain(crate::guide::OFFERED.then_some(( diff --git a/crates/snowbound/tests/replay.rs b/crates/snowbound/tests/replay.rs index 151f02b0b4cde9eabedc913015e9515fdab01722..d756ac71451bb32acf1d80db881fa6a5da8748b4 100644 --- a/crates/snowbound/tests/replay.rs +++ b/crates/snowbound/tests/replay.rs @@ -549,3 +549,36 @@ fn stop_sharing_ends_the_share() { let kept = std::fs::read_to_string(kept).unwrap_or_default(); assert!(!kept.contains("code"), "still kept: {kept}"); } + +/// Open Shared Notebook is where people look with notebooks open: in the sidebar's footer, +/// and in the palette, which opens it. +#[cfg(feature = "live")] +#[test] +fn open_shared_notebook_is_offered_with_notebooks_open() { + let scratch = Scratch::new("open-shared"); + std::fs::write( + scratch.0.join("settings.json"), + r#"{"user_name": "Snowbound Test", "sidebar": true}"#, + ) + .unwrap(); + let notebook = + Path::new(env!("CARGO_MANIFEST_DIR")).join("../../corpus/cross-container/candidate"); + let mut steps = vec!["accessibility sidebar", "modifiers command shift", "key p"]; + steps.extend([ + "modifiers", + "settle", + "type Open Shared", + "settle", + "key Enter", + ]); + steps.extend(["settle", "accessibility dialog"]); + let variables = [("SNOWBOUND_LIVE", "off"), ("SNOWBOUND_LIVE_RELAY", "off")]; + let [sidebar, dialog] = replay_with(&scratch, Some(¬ebook), &steps, &variables) + .try_into() + .unwrap(); + assert!(sidebar.contains(r#""Open Shared…""#), "{sidebar}"); + assert!( + dialog.contains(r#"Dialog "Open Shared Notebook""#), + "{dialog}" + ); +} -- 2.54.0