feat: Quick Open with more transports

This commit is contained in:
Kaede Akino committed 2026-10-18 13:00:16 +08:00
1 parent 286045ab24
commit 58686b400b
4 files changed
+212 -20

No files matched your search

@@ -17349,6 +17349,88 @@
}
}
},
"Connect with Eternal Terminal · %@" : {
"extractionState" : "manual",
"localizations" : {
"de" : {
"stringUnit" : {
"state" : "translated",
"value" : "Mit Eternal Terminal verbinden · %@"
}
},
"fr" : {
"stringUnit" : {
"state" : "translated",
"value" : "Se connecter via Eternal Terminal · %@"
}
},
"ja" : {
"stringUnit" : {
"state" : "translated",
"value" : "Eternal Terminalで接続 · %@"
}
},
"ko" : {
"stringUnit" : {
"state" : "translated",
"value" : "Eternal Terminal로 연결 · %@"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "使用Eternal Terminal连接·%@"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "使用Eternal Terminal連線·%@"
}
}
}
},
"Connect with Mosh · %@" : {
"extractionState" : "manual",
"localizations" : {
"de" : {
"stringUnit" : {
"state" : "translated",
"value" : "Mit Mosh verbinden · %@"
}
},
"fr" : {
"stringUnit" : {
"state" : "translated",
"value" : "Se connecter via Mosh · %@"
}
},
"ja" : {
"stringUnit" : {
"state" : "translated",
"value" : "Moshで接続 · %@"
}
},
"ko" : {
"stringUnit" : {
"state" : "translated",
"value" : "Mosh로 연결 · %@"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "使用Mosh连接·%@"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "使用Mosh連線·%@"
}
}
}
},
"Connect with SSH · %@" : {
"extractionState" : "manual",
"localizations" : {
@@ -134,6 +134,12 @@ extension AppStrings {
public static func connectWithSsh(_ value: String) -> LocalizedStringResource {
"Connect with SSH · \(value)"
}
public static func connectWithMosh(_ value: String) -> LocalizedStringResource {
"Connect with Mosh · \(value)"
}
public static func connectWithEternalTerminal(_ value: String) -> LocalizedStringResource {
"Connect with Eternal Terminal · \(value)"
}
public static func connectWithTelnet(_ value: String) -> LocalizedStringResource {
"Connect with Telnet · \(value)"
}
@@ -192,18 +192,40 @@ final class AppCommandRegistry {
private func hostCommands(_ host: Host) -> [AppCommandDescriptor] {
let keywords = [host.host] + host.supportedTerminalProtocols.map { host.displayAddress(for: $0) } + host.tags
var commands: [AppCommandDescriptor] = []
var protocols = host.supportedTerminalProtocols
if let preferred = host.preferredTerminalProtocol {
protocols.removeAll { $0 == preferred }
protocols.insert(preferred, at: 0)
}
var commands = protocols.map { transport in
let address = host.displayAddress(for: transport)
let action: HostConnectAction
let subtitle: LocalizedStringResource
switch transport {
case .ssh:
action = .ssh
subtitle = AppStrings.Connections.connectWithSsh(address)
case .mosh:
action = .mosh
subtitle = AppStrings.Connections.connectWithMosh(address)
case .eternalTerminal:
action = .eternalTerminal
subtitle = AppStrings.Connections.connectWithEternalTerminal(address)
case .telnet:
action = .telnet
subtitle = AppStrings.Connections.connectWithTelnet(address)
}
return AppCommandDescriptor(
id: "host.\(transport.rawValue).\(host.id.uuidString)",
title: host.name,
subtitle: String(localized: subtitle),
symbol: action.symbol,
section: .hosts,
keywords: keywords + [transport.rawValue, transport.displayName],
target: .connectHost(host.id, action.target)
)
}
if host.sshEnabled {
commands.append(
AppCommandDescriptor(
id: "host.ssh.\(host.id.uuidString)",
title: host.name,
subtitle: String(localized: AppStrings.Connections.connectWithSsh(host.displayAddress(for: .ssh))),
symbol: "apple.terminal",
section: .hosts,
keywords: keywords + ["ssh"],
target: .connectHost(host.id, .sshSession)
))
commands.append(
AppCommandDescriptor(
id: "host.sftp.\(host.id.uuidString)",
@@ -215,15 +237,6 @@ final class AppCommandRegistry {
target: .connectHost(host.id, .sftpChannel)
))
}
if host.telnetEnabled {
commands.append(
AppCommandDescriptor(
id: "host.telnet.\(host.id.uuidString)", title: host.name,
subtitle: String(
localized: AppStrings.Connections.connectWithTelnet(host.displayAddress(for: .telnet))),
symbol: MenuSymbol.telnet, section: .hosts, keywords: keywords + ["telnet"],
target: .connectHost(host.id, .telnetSession)))
}
return commands
}
+91
View File
@@ -181,6 +181,97 @@ struct QuickOpenTests {
#expect(window.workspaces[0].panes.map(\.hostID) == [ssh.id, telnet.id])
}
@Test(arguments: [HostTerminalProtocol.ssh, .mosh, .eternalTerminal])
func quickOpenPrioritizesAndOpensTheDefaultTransport(transport: HostTerminalProtocol) throws {
var host = Host(name: "Production", host: "server.invalid")
host.terminalTransports.moshEnabled = true
host.terminalTransports.eternalTerminalEnabled = true
host.terminalTransports.defaultTransport = transport
let app = AppModel(hosts: HostLibraryModel(hosts: [host]))
defer { app.shutdownForTermination() }
let window = WindowModel()
let results = QuickOpenResults(commands: app.commands.commands(app: app, window: window), query: host.name)
let first = try #require(results.commands.first)
#expect(first.symbol == transport.symbol)
app.commands.perform(first.target, app: app, window: window)
let session = try #require(window.selectedWorkspace?.focusedPane.sshSession)
#expect(session.hostID == host.id)
#expect(session.transport == transport)
for (target, expected) in [
(HostOpenTarget.sshSession, HostTerminalProtocol.ssh),
(.moshSession, .mosh),
(.eternalTerminalSession, .eternalTerminal),
] {
let command = try #require(results.commands.first { $0.target == .connectHost(host.id, target) })
app.commands.perform(command.target, app: app, window: window)
#expect(window.selectedWorkspace?.focusedPane.sshSession?.transport == expected)
}
}
@Test(arguments: [false, true], [false, true])
func quickOpenListsOnlyEnabledResumableTransports(moshEnabled: Bool, eternalTerminalEnabled: Bool) throws {
var host = Host(name: "Production", host: "server.invalid", port: 2222, tags: ["critical"])
host.terminalTransports.moshEnabled = moshEnabled
host.terminalTransports.eternalTerminalEnabled = eternalTerminalEnabled
host.terminalTransports.eternalTerminalPort = 3022
let app = AppModel(hosts: HostLibraryModel(hosts: [host]))
defer { app.shutdownForTermination() }
let commands = app.commands.commands(app: app, window: WindowModel()).filter { $0.section == .hosts }
#expect(commands.contains { $0.target == .connectHost(host.id, .moshSession) } == moshEnabled)
#expect(
commands.contains { $0.target == .connectHost(host.id, .eternalTerminalSession) } == eternalTerminalEnabled)
#expect(commands.contains { $0.target == .connectHost(host.id, .sftpChannel) })
#expect(Set(commands.map(\.id)).count == commands.count)
#expect(commands.allSatisfy { $0.matches("critical") })
if moshEnabled {
let mosh = try #require(commands.first { $0.target == .connectHost(host.id, .moshSession) })
#expect(mosh.symbol == MenuSymbol.mosh)
#expect(mosh.matches("Mosh"))
#expect(mosh.subtitle == String(localized: AppStrings.Connections.connectWithMosh("server.invalid:2222")))
}
if eternalTerminalEnabled {
let et = try #require(commands.first { $0.target == .connectHost(host.id, .eternalTerminalSession) })
#expect(et.symbol == MenuSymbol.eternalTerminal)
#expect(et.matches("Eternal Terminal"))
#expect(
et.subtitle
== String(localized: AppStrings.Connections.connectWithEternalTerminal("server.invalid:3022")))
}
}
@Test
func quickOpenFallsBackWhenTheDefaultTransportIsUnavailable() {
func targets(for host: Host) -> [AppCommandTarget] {
let app = AppModel(hosts: HostLibraryModel(hosts: [host]))
defer { app.shutdownForTermination() }
return app.commands.commands(app: app, window: WindowModel())
.filter { $0.section == .hosts }.map(\.target)
}
var host = Host(name: "Production", host: "server.invalid")
host.terminalTransports.defaultTransport = .mosh
#expect(targets(for: host) == [.connectHost(host.id, .sshSession), .connectHost(host.id, .sftpChannel)])
host.terminalTransports.moshEnabled = true
host.terminalTransports.eternalTerminalEnabled = true
host.tailscale = .init(groupID: UUID(), stableNodeID: "quick-open-test")
#expect(
targets(for: host) == [
.connectHost(host.id, .sshSession), .connectHost(host.id, .eternalTerminalSession),
.connectHost(host.id, .sftpChannel),
])
host.sshEnabled = false
host.telnetEnabled = true
#expect(targets(for: host) == [.connectHost(host.id, .telnetSession)])
host.telnetEnabled = false
#expect(targets(for: host).isEmpty)
}
@Test
func registryCombinesManagementWorkspacesHostsAndActions() {
let host = Host(name: "Production", host: "prod.example", tags: ["critical"])