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
1 change: 0 additions & 1 deletion apple/TablePro/Core/Events/AppCommands.swift
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,6 @@ final class AppCommands {
// MARK: - File / Connection Import-Export

let openSQLFiles = PassthroughSubject<[URL], Never>()
let exportQueryResults = PassthroughSubject<Void, Never>()

private init() {}
}
9 changes: 0 additions & 9 deletions apple/TablePro/Core/Events/KeyWindowCommandSubscription.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
// TablePro
//

import AppKit
import Combine
import Foundation

Expand All @@ -21,12 +20,4 @@ internal enum KeyWindowCommandSubscription {
handler(payload)
}
}

internal static func sink<Payload>(
_ publisher: PassthroughSubject<Payload, Never>,
whileKey window: @escaping @MainActor () -> NSWindow?,
perform handler: @escaping @MainActor (Payload) -> Void
) -> AnyCancellable {
sink(publisher, when: { window()?.isKeyWindow == true }, perform: handler)
}
}
4 changes: 3 additions & 1 deletion apple/TablePro/Core/Menu/FileMenuBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,9 @@ enum FileMenuBuilder {
),
MenuItemFactory.item(
String(localized: "Export Results…"),
action: #selector(MainSplitViewController.exportQueryResults(_:))
action: #selector(MainSplitViewController.exportQueryResults(_:)),
shortcut: .exportResults,
keyboard: keyboard
),
MenuItemFactory.item(
String(localized: "Export Data Dictionary…"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@ extension MainWindowToolbar {
label: String(localized: "Restore Previous Values"),
symbol: "clock.arrow.circlepath",
action: #selector(performRestorePreviousValues(_:)),
shortcut: .restorePreviousValues,
description: String(localized: "Restore the previous values of a save")
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,8 @@ internal enum ConnectionActionsMenuResolver {
entries.append(
ActionsMenuEntry(
title: String(localized: "Export Results…"),
selector: NSSelectorFromString("exportQueryResults:")
selector: NSSelectorFromString("exportQueryResults:"),
shortcut: .exportResults
)
)
}
Expand Down
7 changes: 5 additions & 2 deletions apple/TablePro/Models/UI/KeyboardShortcutModels.swift
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ enum ShortcutAction: String, Codable, CaseIterable, Identifiable {
case lastPage
case refresh
case export
case exportResults
case importData
case jumpToColumn

Expand Down Expand Up @@ -211,7 +212,7 @@ enum ShortcutAction: String, Codable, CaseIterable, Identifiable {
.setValueEmpty, .setValueNull, .setValueDefault, .generateUUIDv4, .generateUUIDv7, .setCellsToValue,
.restorePreviousValues,
.truncateTable, .toggleHeaderRow, .previewFKReference, .saveAsFavorite, .previousPage,
.nextPage, .firstPage, .lastPage, .refresh, .export, .importData, .jumpToColumn:
.nextPage, .firstPage, .lastPage, .refresh, .export, .exportResults, .importData, .jumpToColumn:
return .dataGrid
case .navigateBack, .navigateForward,
.newTab, .closeTab, .closeOtherTabs, .closeTabsForOtherDatabases, .closeAllTabs,
Expand Down Expand Up @@ -332,7 +333,8 @@ enum ShortcutAction: String, Codable, CaseIterable, Identifiable {
case .findNext: return String(localized: "Find Next")
case .findPrevious: return String(localized: "Find Previous")
case .useSelectionForFind: return String(localized: "Use Selection for Find")
case .export: return String(localized: "Export")
case .export: return String(localized: "Export Tables")
case .exportResults: return String(localized: "Export Results")
case .importData: return String(localized: "Import")
case .jumpToColumn: return String(localized: "Jump to Column")
case .quickSwitcher: return String(localized: "Open Quickly")
Expand Down Expand Up @@ -696,6 +698,7 @@ struct KeyboardSettings: Codable, Equatable {
.aiExplainQuery: .character("l", command: true),
.aiOptimizeQuery: .character("l", command: true, option: true),
.export: .character("e", command: true, shift: true),
.exportResults: .character("e", command: true, shift: true, option: true),
.importData: .character("i", command: true, shift: true),

// Data Grid
Expand Down
82 changes: 81 additions & 1 deletion apple/TablePro/Resources/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -78281,6 +78281,46 @@
}
}
},
"Export Results" : {
"localizations" : {
"fr" : {
"stringUnit" : {
"state" : "translated",
"value" : "Exporter les résultats"
}
},
"ko" : {
"stringUnit" : {
"state" : "translated",
"value" : "결과 내보내기"
}
},
"tr" : {
"stringUnit" : {
"state" : "translated",
"value" : "Sonuçları Dışa Aktar"
}
},
"vi" : {
"stringUnit" : {
"state" : "translated",
"value" : "Xuất kết quả"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "导出结果"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "匯出結果"
}
}
}
},
"Export Results…" : {
"localizations" : {
"fr" : {
Expand All @@ -78304,7 +78344,7 @@
"vi" : {
"stringUnit" : {
"state" : "translated",
"value" : "Export Kết Quả…"
"value" : "Xuất kết quả…"
}
},
"zh-Hans" : {
Expand Down Expand Up @@ -78361,6 +78401,46 @@
}
}
},
"Export Tables" : {
"localizations" : {
"fr" : {
"stringUnit" : {
"state" : "translated",
"value" : "Exporter les tables"
}
},
"ko" : {
"stringUnit" : {
"state" : "translated",
"value" : "테이블 내보내기"
}
},
"tr" : {
"stringUnit" : {
"state" : "translated",
"value" : "Tabloları Dışa Aktar"
}
},
"vi" : {
"stringUnit" : {
"state" : "translated",
"value" : "Xuất bảng"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "导出表"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "匯出資料表"
}
}
}
},
"Export Tables…" : {
"localizations" : {
"fr" : {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,6 @@ final class DataFileSplitViewController: NSSplitViewController {
addSplitViewItem(contentItem)
addSplitViewItem(inspectorItem)

KeyWindowCommandSubscription
.sink(AppCommands.shared.exportQueryResults, whileKey: { [weak self] in self?.view.window }) { [weak self] _ in
self?.presentExport()
}
.store(in: &cancellables)

controller.$isInspectorVisible
.removeDuplicates()
.sink { [weak self] visible in
Expand Down
3 changes: 2 additions & 1 deletion apple/TablePro/Views/Main/Child/DataTabGridAdapter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,8 @@ final class DataTabGridAdapter: DataGridDataSource, DataGridActions {
}

func gridExportResults() {
AppCommands.shared.exportQueryResults.send(())
guard ownsWindowState else { return }
coordinator?.commandActions?.exportQueryResults()
}

func gridClearResults() {
Expand Down
17 changes: 1 addition & 16 deletions apple/TablePro/Views/Main/MainContentCommandActions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -123,16 +123,6 @@ final class MainContentCommandActions: ObservableObject {
return host.workspaces.selected?.sessionState?.coordinator === coordinator
}

private func observeKeyWindowOnly(
_ name: Notification.Name,
handler: @escaping @MainActor (Notification) -> Void
) {
observe(name) { [weak self] notification in
guard self?.isVisibleInKeyWindow() == true else { return }
handler(notification)
}
}

private func observeKeyWindowOnly<Payload>(
_ publisher: PassthroughSubject<Payload, Never>,
handler: @escaping @MainActor (Payload) -> Void
Expand Down Expand Up @@ -170,17 +160,12 @@ final class MainContentCommandActions: ObservableObject {
// MARK: - Observer Setup

private func setupObservers() {
setupNonMenuNotificationObservers()
setupDataBroadcastObservers()
setupDatabaseBroadcastObservers()
setupWindowObservers()
setupFileOpenObservers()
}

private func setupNonMenuNotificationObservers() {
observeKeyWindowOnly(AppCommands.shared.exportQueryResults) { [weak self] _ in self?.exportQueryResults() }
}

// MARK: - Row Operations (Group A: Called Directly)

func addNewRow() {
Expand Down Expand Up @@ -473,7 +458,7 @@ final class MainContentCommandActions: ObservableObject {
}
}

// Save As and Export Results gate on this, not isConnected, which left them lit over a handler that did nothing.
// Save As gates on this, not isConnected, which left it lit over a handler that did nothing.
var isQueryTab: Bool {
coordinator?.tabManager.selectedTab?.tabType == .query
}
Expand Down
8 changes: 5 additions & 3 deletions apple/TablePro/Views/Sidebar/Menu/SidebarMenuShortcut.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@ internal protocol SidebarMenuShortcutProviding {

extension SidebarMenuCommand: SidebarMenuShortcutProviding {
/// Only the commands whose menu-bar twin actually carries a `ShortcutAction` today: Database >
/// Refresh, Database > Truncate Table, File > Import Data and File > Export. Drop is left out
/// Refresh, Database > Truncate Table, File > Import Data and File > Export Tables. Drop is left out
/// deliberately, because the menu bar's Delete is the data grid's row delete and pointing the
/// sidebar's object drop at it would show a shortcut that deletes something else.
/// sidebar's object drop at it would show a shortcut that deletes something else. A database or
/// schema's Export… is left out for the same reason: Export Tables… exports the selected tables,
/// so its key would open the dialog with nothing in that container chosen.
internal var shortcutAction: ShortcutAction? {
switch self {
case .refreshContainers, .refreshObjectKind, .refreshContainerObjectKind, .refreshHierarchicalSchema:
Expand All @@ -33,7 +35,7 @@ extension SidebarMenuCommand: SidebarMenuShortcutProviding {
return .truncateTable
case .importTables:
return .importData
case .exportTables, .exportContainers:
case .exportTables:
return .export
default:
return nil
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import AppKit
import Combine
import Foundation
@testable import TablePro
Expand Down Expand Up @@ -33,33 +32,4 @@ struct KeyWindowCommandSubscriptionTests {
backgroundSubscription.cancel()
frontmostSubscription.cancel()
}

@Test("A window that is not key does not run the command")
func windowThatIsNotKeyDoesNotRun() async throws {
let subject = PassthroughSubject<Void, Never>()
let window = NSWindow(
contentRect: NSRect(x: 0, y: 0, width: 10, height: 10),
styleMask: [.titled],
backing: .buffered,
defer: true
)
window.isReleasedWhenClosed = false
let received = Received()
let subscription = KeyWindowCommandSubscription.sink(subject, whileKey: { window }) { _ in
received.payloads.append(1)
}
// Subscribed after, so its delivery on the main run loop comes after the window's.
let control = Received()
let controlSubscription = KeyWindowCommandSubscription.sink(subject, when: { true }) { _ in
control.payloads.append(1)
}

subject.send(())
try await waitUntil { !control.payloads.isEmpty }

#expect(!window.isKeyWindow)
#expect(received.payloads.isEmpty)
subscription.cancel()
controlSubscription.cancel()
}
}
Loading
Loading