diff --git a/apps/desktop/src/components/FileMenuAction.svelte b/apps/desktop/src/components/FileMenuAction.svelte index 5d0f5fe70f..f58b9c4208 100644 --- a/apps/desktop/src/components/FileMenuAction.svelte +++ b/apps/desktop/src/components/FileMenuAction.svelte @@ -22,6 +22,13 @@ }), shortcutService.on('clone-repo', async () => { goto(clonePath()); + }), + shortcutService.on('clone-window', async () => { + const url = new URL(window.location.href); + const currentProjectId = url.pathname.split('/')[1]; + if (currentProjectId) { + await projectsService.openProjectInNewWindow(currentProjectId); + } }) ) ); diff --git a/apps/desktop/src/lib/project/projectsService.ts b/apps/desktop/src/lib/project/projectsService.ts index ab11e514aa..d060149912 100644 --- a/apps/desktop/src/lib/project/projectsService.ts +++ b/apps/desktop/src/lib/project/projectsService.ts @@ -177,6 +177,10 @@ function injectEndpoints(api: ClientState['backendApi']) { openProjectInWindow: build.mutation({ extraOptions: { command: 'open_project_in_window' }, query: (args) => args + }), + getCurrentProjectId: build.query({ + extraOptions: { command: 'get_current_project_id' }, + query: () => undefined }) }) }); diff --git a/crates/gitbutler-tauri/src/main.rs b/crates/gitbutler-tauri/src/main.rs index 2a97b1dad5..01896dc003 100644 --- a/crates/gitbutler-tauri/src/main.rs +++ b/crates/gitbutler-tauri/src/main.rs @@ -230,6 +230,7 @@ fn main() { projects::list_projects, projects::set_project_active, projects::open_project_in_window, + projects::get_current_project_id, repo::git_get_local_config, repo::git_set_local_config, repo::check_signing_settings, diff --git a/crates/gitbutler-tauri/src/menu.rs b/crates/gitbutler-tauri/src/menu.rs index 6bab3e2062..2a05e93b6f 100644 --- a/crates/gitbutler-tauri/src/menu.rs +++ b/crates/gitbutler-tauri/src/menu.rs @@ -79,6 +79,10 @@ pub fn build( .accelerator("CmdOrCtrl+Shift+O") .build(handle)?, &PredefinedMenuItem::separator(handle)?, + &MenuItemBuilder::with_id("file/clone-window", "Clone Window") + .accelerator("CmdOrCtrl+Shift+N") + .build(handle)?, + &PredefinedMenuItem::separator(handle)?, ]) .build()?; @@ -265,6 +269,11 @@ pub fn handle_event( return; } + if event.id() == "file/clone-window" { + emit(webview, SHORTCUT_EVENT, "clone-window"); + return; + } + #[cfg(any(debug_assertions, feature = "devtools"))] { if event.id() == "view/devtools" { diff --git a/crates/gitbutler-tauri/src/projects.rs b/crates/gitbutler-tauri/src/projects.rs index ec21421f17..db4f5a53a3 100644 --- a/crates/gitbutler-tauri/src/projects.rs +++ b/crates/gitbutler-tauri/src/projects.rs @@ -114,6 +114,16 @@ pub fn open_project_in_window(handle: tauri::AppHandle, id: ProjectId) -> Result Ok(()) } +/// Get the current project ID for a window, if any. +#[tauri::command] +#[instrument(skip(window_state, window), err(Debug))] +pub fn get_current_project_id( + window_state: State<'_, WindowState>, + window: Window, +) -> Result, Error> { + Ok(window_state.get_project_for_window(window.label())) +} + #[derive(serde::Deserialize, serde::Serialize)] pub struct ProjectForFrontend { #[serde(flatten)] diff --git a/crates/gitbutler-tauri/src/window.rs b/crates/gitbutler-tauri/src/window.rs index 510ec594f1..0ac0e4067b 100644 --- a/crates/gitbutler-tauri/src/window.rs +++ b/crates/gitbutler-tauri/src/window.rs @@ -276,6 +276,12 @@ pub(crate) mod state { .map(|state| state.project_id) .collect() } + + /// Get the current project ID for a specific window, if any. + pub fn get_project_for_window(&self, window: &WindowLabelRef) -> Option { + let state_by_label = self.state.lock(); + state_by_label.get(window).map(|state| state.project_id) + } } }