From 7f05ade43348de328f1842d999fb50f8ec007358 Mon Sep 17 00:00:00 2001 From: Madion Konig Date: Wed, 28 Aug 2024 11:11:46 -0700 Subject: [PATCH] Add "Duplicate current tab" keybind (#2679) * Implemented duplicating current tab * prettier fixes * Disable non-functional "New window" menu shortcut This was preventing "Duplicate current tab" from firing * use proper casing in RedirectPath type name * Revert locale changes from "Implemented duplicating current tab" This partially reverts commit a822f54569069a8f56415f41c51c4b4d5f33f99e. There were unrelated changes to locale files that should be scoped to their own PR. * SImplify new location definition * Remove accidentally committed change lol * Use cmd-shift-t for duplicate same tab * Remove navToSettings shortcut * remove references to now-missing navToSettings keybind --------- Co-authored-by: lynx <141365347+iLynxcat@users.noreply.github.com> --- apps/desktop/src-tauri/src/menu.rs | 19 ++++++------- apps/desktop/src/App.tsx | 27 ++++++++++++++++--- interface/TabsContext.tsx | 1 + .../Layout/Sidebar/SidebarLayout/Footer.tsx | 8 +++--- interface/app/$libraryId/TopBar/index.tsx | 7 ++++- .../settings/client/keybindings.tsx | 7 ++--- interface/hooks/useShortcut.ts | 13 ++++++--- 7 files changed, 56 insertions(+), 26 deletions(-) diff --git a/apps/desktop/src-tauri/src/menu.rs b/apps/desktop/src-tauri/src/menu.rs index 1073031f1..3c86e0fa2 100644 --- a/apps/desktop/src-tauri/src/menu.rs +++ b/apps/desktop/src-tauri/src/menu.rs @@ -78,11 +78,7 @@ pub fn setup_menu(app: &AppHandle) -> tauri::Result> { .build(), )) .separator() - .item( - &MenuItemBuilder::with_id(MenuEvent::NewLibrary, "New Library") - .accelerator("Cmd+Shift+T") - .build(app)?, - ) + .item(&MenuItemBuilder::with_id(MenuEvent::NewLibrary, "New Library").build(app)?) // .item( // &SubmenuBuilder::new(app, "Libraries") // // TODO: Implement this @@ -194,12 +190,13 @@ pub fn setup_menu(app: &AppHandle) -> tauri::Result> { let window_menu = SubmenuBuilder::new(app, "Window") .minimize() - .item( - &MenuItemBuilder::with_id(MenuEvent::NewWindow, "New Window") - .accelerator("CmdOrCtrl+Shift+N") - .build(app)?, - ) - .close_window() + // Disabling this fixes the new "Duplicate current tab" shortcut on macOS clients + // ...and at the time I'm committing this we don't support multi-window so... ¯\_(ツ)_/¯ + // .item( + // &MenuItemBuilder::with_id(MenuEvent::NewWindow, "New Window") + // .accelerator("CmdOrCtrl+Shift+N") + // .build(app)?, + // ) .fullscreen() .item( &MenuItemBuilder::with_id(MenuEvent::ReloadWebview, "Reload Webview") diff --git a/apps/desktop/src/App.tsx b/apps/desktop/src/App.tsx index b8309a53a..141458057 100644 --- a/apps/desktop/src/App.tsx +++ b/apps/desktop/src/App.tsx @@ -74,7 +74,7 @@ const TAB_CREATE_DELAY = 150; const routes = createRoutes(platform); -type redirect = { pathname: string; search: string | undefined }; +type RedirectPath = { pathname: string; search: string | undefined }; function AppInner() { const [tabs, setTabs] = useState(() => [createTab()]); @@ -82,7 +82,7 @@ function AppInner() { const selectedTab = tabs[selectedTabIndex]!; - function createTab(redirect?: redirect) { + function createTab(redirect?: RedirectPath) { const history = createMemoryHistory(); const router = createMemoryRouterWithHistory({ routes, history }); @@ -171,7 +171,7 @@ function AppInner() { tabIndex: selectedTabIndex, setTabIndex: setSelectedTabIndex, tabs: tabs.map(({ router, title }) => ({ router, title })), - createTab(redirect?: redirect) { + createTab(redirect?: RedirectPath) { createTabPromise.current = createTabPromise.current.then( () => new Promise((res) => { @@ -190,6 +190,27 @@ function AppInner() { }) ); }, + duplicateTab() { + createTabPromise.current = createTabPromise.current.then( + () => + new Promise((res) => { + startTransition(() => { + setTabs((tabs) => { + const { pathname, search } = + selectedTab.router.state.location; + const newTab = createTab({ pathname, search }); + const newTabs = [...tabs, newTab]; + + setSelectedTabIndex(newTabs.length - 1); + + return newTabs; + }); + }); + + setTimeout(res, TAB_CREATE_DELAY); + }) + ); + }, removeTab(index: number) { startTransition(() => { setTabs((tabs) => { diff --git a/interface/TabsContext.tsx b/interface/TabsContext.tsx index fa94629f9..0e0ac68a5 100644 --- a/interface/TabsContext.tsx +++ b/interface/TabsContext.tsx @@ -8,6 +8,7 @@ export const TabsContext = createContext<{ tabs: { router: Router; title: string }[]; createTab(redirect?: { pathname: string; search: string | undefined }): void; removeTab(index: number): void; + duplicateTab(): void; } | null>(null); export function useTabsContext() { diff --git a/interface/app/$libraryId/Layout/Sidebar/SidebarLayout/Footer.tsx b/interface/app/$libraryId/Layout/Sidebar/SidebarLayout/Footer.tsx index 58dcce2a2..2d7dc4835 100644 --- a/interface/app/$libraryId/Layout/Sidebar/SidebarLayout/Footer.tsx +++ b/interface/app/$libraryId/Layout/Sidebar/SidebarLayout/Footer.tsx @@ -24,10 +24,10 @@ export default () => { const navigate = useNavigate(); const symbols = useKeysMatcher(['Meta', 'Shift']); - useShortcut('navToSettings', (e) => { - e.stopPropagation(); - navigate('settings/client/general'); - }); + // useShortcut('navToSettings', (e) => { + // e.stopPropagation(); + // navigate('settings/client/general'); + // }); const updater = usePlatform().updater; const updaterState = updater?.useSnapshot(); diff --git a/interface/app/$libraryId/TopBar/index.tsx b/interface/app/$libraryId/TopBar/index.tsx index d84646775..076d9a421 100644 --- a/interface/app/$libraryId/TopBar/index.tsx +++ b/interface/app/$libraryId/TopBar/index.tsx @@ -181,10 +181,15 @@ function useTabKeybinds(props: { addTab(): void; removeTab(index: number): void useShortcut('newTab', (e) => { e.stopPropagation(); - if (e.shiftKey) return; //to prevent colliding with 'navToSettings' shortcut + if (e.shiftKey) return; //to prevent colliding with other shortcuts props.addTab(); }); + useShortcut('duplicateTab', (e) => { + e.stopPropagation(); + ctx.duplicateTab(); + }); + useShortcut('closeTab', (e) => { e.stopPropagation(); props.removeTab(ctx.tabIndex); diff --git a/interface/app/$libraryId/settings/client/keybindings.tsx b/interface/app/$libraryId/settings/client/keybindings.tsx index 6aae27a19..3b26ec631 100644 --- a/interface/app/$libraryId/settings/client/keybindings.tsx +++ b/interface/app/$libraryId/settings/client/keybindings.tsx @@ -30,7 +30,8 @@ export const Component = () => { { shortcut: 'closeTab', description: t('close_current_tab') }, { shortcut: 'newTab', description: t('switch_to_next_tab') }, { shortcut: 'previousTab', description: t('switch_to_previous_tab') }, - { shortcut: 'toggleSidebar', description: t('toggle_sidebar') } + { shortcut: 'toggleSidebar', description: t('toggle_sidebar') }, + { shortcut: 'duplicateTab', description: t('duplicate_current_tab') } ] }, { @@ -43,8 +44,8 @@ export const Component = () => { description: t('page_shortcut_description'), shortcuts: [ { shortcut: 'navBackwardHistory', description: t('navigate_backwards') }, - { shortcut: 'navForwardHistory', description: t('navigate_forwards') }, - { shortcut: 'navToSettings', description: t('navigate_to_settings_page') } + { shortcut: 'navForwardHistory', description: t('navigate_forwards') } + // { shortcut: 'navToSettings', description: t('navigate_to_settings_page') } ] }, { diff --git a/interface/hooks/useShortcut.ts b/interface/hooks/useShortcut.ts index 76a3f7194..63140538a 100644 --- a/interface/hooks/useShortcut.ts +++ b/interface/hooks/useShortcut.ts @@ -18,6 +18,10 @@ const shortcuts = { macOS: ['Meta', 'KeyW'], all: ['Control', 'KeyW'] }, + duplicateTab: { + macOS: ['Meta', 'Shift', 'KeyT'], + all: ['Control', 'Shift', 'KeyT'] + }, nextTab: { macOS: ['Meta', 'Alt', 'ArrowRight'], all: ['Control', 'Alt', 'ArrowRight'] @@ -49,10 +53,11 @@ const shortcuts = { macOS: ['Meta', ']'], all: ['Control', ']'] }, - navToSettings: { - macOS: ['Shift', 'Meta', 'KeyT'], - all: ['Shift', 'Control', 'KeyT'] - }, + // I plan to change this to the OS-standard cmd-comma later -ilynxcat + // navToSettings: { + // macOS: ['Shift', 'Meta', 'KeyT'], + // all: ['Shift', 'Control', 'KeyT'] + // }, gridView: { macOS: ['Meta', '1'], all: ['Control', '1']