From 505eafd48d95e9e42d27aba2ae035f7176a7c291 Mon Sep 17 00:00:00 2001 From: ramaID Date: Sat, 6 Sep 2025 12:36:02 +0700 Subject: [PATCH 1/2] chore: alternative Cmd+Shift+[ ] shortcuts for tab switching --- ora/Common/Constants/KeyboardShortcuts.swift | 4 ++ ora/Services/TabManager.swift | 42 ++++++++++++++++++++ ora/oraApp.swift | 32 +++++++++++++-- 3 files changed, 75 insertions(+), 3 deletions(-) diff --git a/ora/Common/Constants/KeyboardShortcuts.swift b/ora/Common/Constants/KeyboardShortcuts.swift index 9411ee96..6dc3019d 100644 --- a/ora/Common/Constants/KeyboardShortcuts.swift +++ b/ora/Common/Constants/KeyboardShortcuts.swift @@ -15,6 +15,8 @@ enum KeyboardShortcuts { static let reopenClosed = KeyboardShortcut("t", modifiers: [.command, .shift]) static let next = KeyboardShortcut(.tab, modifiers: [.control]) static let previous = KeyboardShortcut(.tab, modifiers: [.control, .shift]) + static let nextAlt = KeyboardShortcut("]", modifiers: [.command, .shift]) + static let previousAlt = KeyboardShortcut("[", modifiers: [.command, .shift]) static let moveRight = KeyboardShortcut(.rightArrow, modifiers: [.option, .command]) static let moveLeft = KeyboardShortcut(.leftArrow, modifiers: [.option, .command]) static let pin = KeyboardShortcut("d", modifiers: [.command]) @@ -89,6 +91,8 @@ extension KeyboardShortcuts { .init(category: "Tabs", name: "Reopen Closed", display: "⇧⌘T"), .init(category: "Tabs", name: "Next Tab", display: "^⇥"), .init(category: "Tabs", name: "Previous Tab", display: "^⇧⇥"), + .init(category: "Tabs", name: "Next Tab (Alt)", display: "⇧⌘]"), + .init(category: "Tabs", name: "Previous Tab (Alt)", display: "⇧⌘["), .init(category: "Tabs", name: "Move Tab Right", display: "⌥⌘→"), .init(category: "Tabs", name: "Move Tab Left", display: "⌥⌘←"), .init(category: "Tabs", name: "Pin Tab", display: "⌘D"), diff --git a/ora/Services/TabManager.swift b/ora/Services/TabManager.swift index 4e8dedd4..d74ef7d0 100644 --- a/ora/Services/TabManager.swift +++ b/ora/Services/TabManager.swift @@ -346,6 +346,48 @@ class TabManager: ObservableObject { try? modelContext.save() } + func switchToNextTab() { + guard let container = activeContainer else { return } + + // Get all available tabs, preferring ready ones but falling back to all + let readyTabs = container.tabs.filter(\.isWebViewReady) + let tabs = readyTabs.isEmpty ? Array(container.tabs) : readyTabs + + guard tabs.count > 1, let currentTab = activeTab else { return } + + // Sort by order for consistent navigation + let sortedTabs = tabs.sorted { $0.order < $1.order } + + if let currentIndex = sortedTabs.firstIndex(where: { $0.id == currentTab.id }) { + let nextIndex = (currentIndex + 1) % sortedTabs.count + activateTab(sortedTabs[nextIndex]) + } else { + // Current tab not found, activate first tab + activateTab(sortedTabs[0]) + } + } + + func switchToPreviousTab() { + guard let container = activeContainer else { return } + + // Get all available tabs, preferring ready ones but falling back to all + let readyTabs = container.tabs.filter(\.isWebViewReady) + let tabs = readyTabs.isEmpty ? Array(container.tabs) : readyTabs + + guard tabs.count > 1, let currentTab = activeTab else { return } + + // Sort by order for consistent navigation + let sortedTabs = tabs.sorted { $0.order < $1.order } + + if let currentIndex = sortedTabs.firstIndex(where: { $0.id == currentTab.id }) { + let previousIndex = (currentIndex - 1 + sortedTabs.count) % sortedTabs.count + activateTab(sortedTabs[previousIndex]) + } else { + // Current tab not found, activate last tab + activateTab(sortedTabs[sortedTabs.count - 1]) + } + } + private func fetchContainers() -> [TabContainer] { do { let descriptor = FetchDescriptor(sortBy: [SortDescriptor(\.lastAccessedAt, order: .reverse)]) diff --git a/ora/oraApp.swift b/ora/oraApp.swift index b46a5c5d..356f4b6f 100644 --- a/ora/oraApp.swift +++ b/ora/oraApp.swift @@ -101,8 +101,32 @@ struct OraApp: App { if event.keyCode == 48 { // Tab key if event.modifierFlags.contains(.control) { + if event.modifierFlags.contains(.shift) { + // Ctrl+Shift+Tab - Previous tab + DispatchQueue.main.async { + tabManager.switchToPreviousTab() + } + } else { + // Ctrl+Tab - Next tab + DispatchQueue.main.async { + tabManager.switchToNextTab() + } + } + return true + } + } else if event.keyCode == 33 { // ] key + if event.modifierFlags.contains([.command, .shift]) { + // Cmd+Shift+] - Next tab + DispatchQueue.main.async { + tabManager.switchToNextTab() + } + return true + } + } else if event.keyCode == 30 { // [ key + if event.modifierFlags.contains([.command, .shift]) { + // Cmd+Shift+[ - Previous tab DispatchQueue.main.async { - appState.isFloatingTabSwitchVisible = true + tabManager.switchToPreviousTab() } return true } @@ -222,12 +246,14 @@ struct OraApp: App { Divider() Button("Next Tab") { - appState.isFloatingTabSwitchVisible = true + tabManager.switchToNextTab() } + .keyboardShortcut(KeyboardShortcuts.Tabs.next) Button("Previous Tab") { - appState.isFloatingTabSwitchVisible = true + tabManager.switchToPreviousTab() } + .keyboardShortcut(KeyboardShortcuts.Tabs.previous) } } Settings { From 4084db34dff33f30b5a2fe791cdbb6cd3a149e86 Mon Sep 17 00:00:00 2001 From: ramaID Date: Sat, 6 Sep 2025 12:41:08 +0700 Subject: [PATCH 2/2] fix: missing alternative shortcuts for tab switching --- ora/oraApp.swift | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/ora/oraApp.swift b/ora/oraApp.swift index 356f4b6f..d20e8512 100644 --- a/ora/oraApp.swift +++ b/ora/oraApp.swift @@ -254,6 +254,19 @@ struct OraApp: App { tabManager.switchToPreviousTab() } .keyboardShortcut(KeyboardShortcuts.Tabs.previous) + + // Alternative shortcuts for tab switching + Button("") { + tabManager.switchToNextTab() + } + .keyboardShortcut(KeyboardShortcuts.Tabs.nextAlt) + .hidden() + + Button("") { + tabManager.switchToPreviousTab() + } + .keyboardShortcut(KeyboardShortcuts.Tabs.previousAlt) + .hidden() } } Settings {