Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed

- `Cmd+C` now copies the focused cell value when one row is selected and a cell has focus; with multiple rows selected, or when no cell is focused, it still copies row(s) as TSV. `Cmd+Shift+C` now always copies row(s) as TSV. "Copy with Headers" stays in the Edit menu and row context menu without a default shortcut (#1332)
- `Cmd+F` toggles the data-grid filter panel when the grid is focused; the SQL editor's Find panel still opens with `Cmd+F` when the editor is focused. The old `Cmd+Shift+F` shortcut for filters is removed
- `Cmd+F` toggles the filter panel when viewing a table, and opens the Find panel in the SQL editor. The old `Cmd+Shift+F` shortcut for filters is removed

### Fixed

Expand Down
1 change: 1 addition & 0 deletions TablePro/Models/UI/KeyboardShortcutModels.swift
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,7 @@ struct KeyboardSettings: Codable, Equatable {
// View
.toggleTableBrowser: KeyCombo(key: "0", command: true),
.toggleInspector: KeyCombo(key: "i", command: true, option: true),
.toggleFilters: KeyCombo(key: "f", command: true),
.toggleHistory: KeyCombo(key: "y", command: true),
.toggleResults: KeyCombo(key: "r", command: true, option: true),
.previousResultTab: KeyCombo(key: "[", command: true, option: true),
Expand Down
38 changes: 30 additions & 8 deletions TablePro/TableProApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,23 @@ struct PasteboardCommands: Commands {

// MARK: - App Menu Commands

/// Where `Cmd+F` resolves in the current context. The data-grid filter lives in
/// the View menu and the editor's Find lives in the Edit menu. Only the item
/// matching the current route binds `Cmd+F`; the other drops it. Two items
/// sharing one key equivalent makes SwiftUI dedupe the shortcut and AppKit bind
/// it to the disabled item, so the live owner must be unique.
enum CommandFRoute {
case inspectorFilter
case tableFilter
case editorFind

static func resolve(isInspector: Bool, isTableTab: Bool) -> CommandFRoute {
if isInspector { return .inspectorFilter }
if isTableTab { return .tableFilter }
return .editorFind
}
}

/// All menu commands extracted into a separate Commands struct so that AppState
/// changes only re-evaluate the menu items — NOT the Scene body / WindowGroups.
struct AppMenuCommands: Commands {
Expand Down Expand Up @@ -152,6 +169,10 @@ struct AppMenuCommands: Commands {
NSApp.keyWindow?.windowController is InspectorWindowController
}

private var commandFRoute: CommandFRoute {
CommandFRoute.resolve(isInspector: keyWindowIsInspector, isTableTab: actions?.isTableTab == true)
}

var body: some Commands {
// Custom About window + Check for Updates + MCP status
CommandGroup(replacing: .appInfo) {
Expand Down Expand Up @@ -468,16 +489,17 @@ struct AppMenuCommands: Commands {
Divider()

Button(String(localized: "Find...")) {
if keyWindowIsInspector {
switch commandFRoute {
case .inspectorFilter:
NSApp.sendAction(#selector(InspectorViewController.toggleInspectorFilter(_:)), to: nil, from: nil)
} else if NSApp.keyWindow?.firstResponder is KeyHandlingTableView,
actions?.isTableTab == true {
actions?.toggleFilterPanel()
} else {
case .editorFind:
EditorEventRouter.shared.showFindPanelForKeyWindow()
case .tableFilter:
break
}
}
.keyboardShortcut("f", modifiers: .command)
.optionalKeyboardShortcut(commandFRoute == .tableFilter ? nil : KeyboardShortcut("f", modifiers: .command))
.disabled(commandFRoute == .tableFilter)

Divider()

Expand Down Expand Up @@ -521,8 +543,8 @@ struct AppMenuCommands: Commands {
Button("Toggle Filters") {
actions?.toggleFilterPanel()
}
.optionalKeyboardShortcut(shortcut(for: .toggleFilters))
.disabled(!(actions?.isConnected ?? false) || !(actions?.isTableTab ?? false))
.optionalKeyboardShortcut(commandFRoute == .tableFilter ? shortcut(for: .toggleFilters) : nil)
.disabled(commandFRoute != .tableFilter || !(actions?.isConnected ?? false))

Button("Toggle History") {
actions?.toggleHistoryPanel()
Expand Down
29 changes: 29 additions & 0 deletions TableProTests/Views/CommandFRouteTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//
// CommandFRouteTests.swift
// TableProTests
//
// Tests for CommandFRoute, which decides where Cmd+F resolves so exactly one
// menu item owns the shortcut per context.
//

@testable import TablePro
import Testing

@Suite("CommandFRouteTests")
struct CommandFRouteTests {
@Test("Inspector window takes priority over tab type")
func inspectorWins() {
#expect(CommandFRoute.resolve(isInspector: true, isTableTab: true) == .inspectorFilter)
#expect(CommandFRoute.resolve(isInspector: true, isTableTab: false) == .inspectorFilter)
}

@Test("Table tab routes to the View-menu filter toggle")
func tableTabFilters() {
#expect(CommandFRoute.resolve(isInspector: false, isTableTab: true) == .tableFilter)
}

@Test("Everything else routes to the editor Find panel")
func otherwiseFinds() {
#expect(CommandFRoute.resolve(isInspector: false, isTableTab: false) == .editorFind)
}
}
2 changes: 1 addition & 1 deletion docs/features/filtering.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ description: Filter table data with 18 operators, raw SQL, and saved presets

# Filtering

Press `Cmd+F` with the data grid focused to open the filter panel. Type a raw SQL WHERE clause and press `Enter` to filter. Raw SQL is the default mode.
Press `Cmd+F` while viewing a table to open the filter panel. Type a raw SQL WHERE clause and press `Enter` to filter. Raw SQL is the default mode.

Each row has a column picker, operator, value field, and **+**/**−** buttons. Multiple rows combine with **AND** or **OR** (toggle in the header). Click **Apply** or press `Enter` to activate. Click **Unset** to clear all.

Expand Down
6 changes: 3 additions & 3 deletions docs/features/keyboard-shortcuts.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ TablePro is keyboard-driven. Most actions have shortcuts, and most menu shortcut

| Action | Shortcut |
|--------|----------|
| Find (SQL editor focused) | `Cmd+F` |
| Find (in SQL editor) | `Cmd+F` |
| Find and replace | `Cmd+Option+F` |
| Find next | `Cmd+G` |
| Find previous | `Cmd+Shift+G` |
Expand Down Expand Up @@ -151,7 +151,7 @@ Inherits the standard `NSDocument` shortcuts.
| Save | `Cmd+S` |
| Save As | `Cmd+Shift+S` |
| Revert to Saved | `Cmd+Option+S` |
| Toggle filter bar | `Cmd+F` |
| Toggle filter panel | `Cmd+F` |
| Copy selected rows as TSV | `Cmd+C` |
| Paste TSV as new rows | `Cmd+V` |
| Add secondary sort column | `Shift+Click` column header |
Expand Down Expand Up @@ -255,7 +255,7 @@ Vim keys only apply in the SQL editor. The data grid and other panels keep their

| Action | Shortcut |
|--------|----------|
| Toggle filter panel (data grid focused) | `Cmd+F` |
| Toggle filter panel (table tab) | `Cmd+F` |
| Apply filters | `Enter` (in value field) |

## Table Structure
Expand Down
Loading