diff --git a/Frameworks/Resources/Localizable.xcstrings b/Frameworks/Resources/Localizable.xcstrings index 43e2c0d7..c20e4903 100644 --- a/Frameworks/Resources/Localizable.xcstrings +++ b/Frameworks/Resources/Localizable.xcstrings @@ -7897,6 +7897,29 @@ } } }, + "Close Transfers" : { + "extractionState" : "manual", + "localizations" : { + "ja" : { + "stringUnit" : { + "state" : "translated", + "value" : "転送を閉じる" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "关闭传输" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "關閉傳輸" + } + } + } + }, "Close Window" : { "extractionState" : "manual", "localizations" : { diff --git a/Frameworks/TermindPresentation/Strings/SFTP.swift b/Frameworks/TermindPresentation/Strings/SFTP.swift index 2d8f02c1..2835bca6 100644 --- a/Frameworks/TermindPresentation/Strings/SFTP.swift +++ b/Frameworks/TermindPresentation/Strings/SFTP.swift @@ -111,6 +111,10 @@ extension AppStrings { "Open Transfers" } + public static var closeTransfers: LocalizedStringResource { + "Close Transfers" + } + public static var octalPermissions: LocalizedStringResource { "Octal permissions" } diff --git a/TFM/App/TermindCommands.swift b/TFM/App/TermindCommands.swift index 1b384013..60129d68 100644 --- a/TFM/App/TermindCommands.swift +++ b/TFM/App/TermindCommands.swift @@ -24,7 +24,8 @@ struct TermindCommands: Commands { @FocusedValue(\.window) private var window private var closeShortcuts: WindowCloseShortcuts { - WindowCloseShortcuts(hasWorkspace: window?.selectedWorkspace != nil) + WindowCloseShortcuts( + hasWorkspace: !app.mainWindows.isTransfersWindowKey && window?.selectedWorkspace != nil) } var body: some Commands { @@ -164,21 +165,26 @@ struct TermindCommands: Commands { Divider() Button(AppStrings.Workspace.closeWindow.swiftUIKey, systemImage: MenuSymbol.closeWorkspace) { + if app.mainWindows.isTransfersWindowKey { + app.mainWindows.closeTransfers() + return + } guard let window else { return } app.mainWindows.closeWindow(in: window) } .termindShortcut(closeShortcuts.closeWindow) - .disabled(window == nil) + .disabled(window == nil && !app.mainWindows.isTransfersWindowKey) Button(AppStrings.Workspace.closeAllWindows.swiftUIKey) { app.mainWindows.closeAllWindows() } .termindShortcut(closeShortcuts.closeAllWindows) .disabled(window == nil) Button(AppStrings.Workspace.closeWorkspace.swiftUIKey) { + guard !app.mainWindows.isTransfersWindowKey else { return } window?.closeSelected() } .termindShortcut(closeShortcuts.closeWorkspace) - .disabled(window?.selectedWorkspace == nil) + .disabled(app.mainWindows.isTransfersWindowKey || window?.selectedWorkspace == nil) } @@ -206,8 +212,12 @@ struct TermindCommands: Commands { showsStatusBar.toggle() } - Button(AppStrings.SFTP.openTransfers.swiftUIKey, systemImage: "arrow.up.arrow.down") { - app.mainWindows.showTransfers() + Button( + (app.mainWindows.isTransfersWindowOpen + ? AppStrings.SFTP.closeTransfers : AppStrings.SFTP.openTransfers).swiftUIKey, + systemImage: "arrow.up.arrow.down" + ) { + app.mainWindows.toggleTransfers() } Divider() diff --git a/TFM/Features/SFTP/SFTPBrowserView.swift b/TFM/Features/SFTP/SFTPBrowserView.swift index dffed18d..1de0b517 100644 --- a/TFM/Features/SFTP/SFTPBrowserView.swift +++ b/TFM/Features/SFTP/SFTPBrowserView.swift @@ -522,8 +522,12 @@ struct SFTPBrowserView: View { } } .disabled(!window.canOpenCompanionSession(from: sftpChannel.id)) - Button(AppStrings.SFTP.openTransfers.swiftUIKey, systemImage: "arrow.up.arrow.down") { - app.mainWindows.showTransfers() + Button( + (app.mainWindows.isTransfersWindowOpen + ? AppStrings.SFTP.closeTransfers : AppStrings.SFTP.openTransfers).swiftUIKey, + systemImage: "arrow.up.arrow.down" + ) { + app.mainWindows.toggleTransfers() } Divider() if sftpChannel.showsHiddenFiles { diff --git a/TFM/Platform/MainWindowCoordinator.swift b/TFM/Platform/MainWindowCoordinator.swift index 2010af56..8e14a17f 100644 --- a/TFM/Platform/MainWindowCoordinator.swift +++ b/TFM/Platform/MainWindowCoordinator.swift @@ -76,9 +76,23 @@ final class MainWindowCoordinator { @ObservationIgnored var createScene: ((UUID) -> Void)? @ObservationIgnored private var isTerminating = false @ObservationIgnored private var transfersWindow: NSWindow? + private(set) var isTransfersWindowOpen = false + private(set) var isTransfersWindowKey = false private(set) var paywallOwnerID: ObjectIdentifier? private var fullScreenWindows: Set = [] + func toggleTransfers() { + if isTransfersWindowOpen { + closeTransfers() + } else { + showTransfers() + } + } + + func closeTransfers() { + transfersWindow?.performClose(nil) + } + func showTransfers() { guard !isTerminating, let app else { return } if let transfersWindow { @@ -98,6 +112,8 @@ final class MainWindowCoordinator { window.center() window.makeKeyAndOrderFront(nil) } + isTransfersWindowOpen = true + isTransfersWindowKey = transfersWindow?.isKeyWindow == true NSApp.activate(ignoringOtherApps: true) } @@ -116,7 +132,7 @@ final class MainWindowCoordinator { } }) for name in [ - NSWindow.willCloseNotification, NSWindow.didBecomeKeyNotification, + NSWindow.willCloseNotification, NSWindow.didBecomeKeyNotification, NSWindow.didResignKeyNotification, NSWindow.didResizeNotification, NSWindow.didEndLiveResizeNotification, NSWindow.willEnterFullScreenNotification, NSWindow.didEnterFullScreenNotification, NSWindow.willExitFullScreenNotification, NSWindow.didExitFullScreenNotification, @@ -133,6 +149,20 @@ final class MainWindowCoordinator { } private func handle(_ notification: Notification.Name, for native: NSWindow) { + if native === transfersWindow { + switch notification { + case NSWindow.willCloseNotification: + isTransfersWindowOpen = false + isTransfersWindowKey = false + case NSWindow.didBecomeKeyNotification: + isTransfersWindowKey = true + case NSWindow.didResignKeyNotification: + isTransfersWindowKey = false + default: + break + } + return + } guard let entry = entries.first(where: { $0.window === native }), let model = entry.model else { return } switch notification { case NSWindow.willCloseNotification: