diff --git a/Packages/vChewing_MainAssembly/Sources/MainAssembly/AppDelegate.swift b/Packages/vChewing_MainAssembly/Sources/MainAssembly/AppDelegate.swift index 6955b9b5..dda57dc6 100644 --- a/Packages/vChewing_MainAssembly/Sources/MainAssembly/AppDelegate.swift +++ b/Packages/vChewing_MainAssembly/Sources/MainAssembly/AppDelegate.swift @@ -134,10 +134,7 @@ public extension AppDelegate { NSApp.popup() guard result == NSApplication.ModalResponse.alertFirstButtonReturn else { return } let url = URL(fileURLWithPath: LMMgr.dataFolderPath(isDefaultFolder: true)) - guard let finderURL = NSWorkspace.shared.urlForApplication(withBundleIdentifier: "com.apple.finder") else { return } - let configuration = NSWorkspace.OpenConfiguration() - configuration.promptsUserIfNeeded = true - NSWorkspace.shared.open([url], withApplicationAt: finderURL, configuration: configuration) + FileOpenMethod.finder.open(url: url) Uninstaller.uninstall( isSudo: false, selfKill: true, defaultDataFolderPath: LMMgr.dataFolderPath(isDefaultFolder: true) ) diff --git a/Packages/vChewing_MainAssembly/Sources/MainAssembly/LMMgr_PhraseEditorDelegate.swift b/Packages/vChewing_MainAssembly/Sources/MainAssembly/LMMgr_PhraseEditorDelegate.swift index 50ae9bdf..098dddb3 100644 --- a/Packages/vChewing_MainAssembly/Sources/MainAssembly/LMMgr_PhraseEditorDelegate.swift +++ b/Packages/vChewing_MainAssembly/Sources/MainAssembly/LMMgr_PhraseEditorDelegate.swift @@ -17,8 +17,8 @@ import Shared extension LMMgr: PhraseEditorDelegate { public var currentInputMode: Shared.InputMode { IMEApp.currentInputMode } - public func openPhraseFile(mode: Shared.InputMode, type: vChewingLM.ReplacableUserDataType, appIdentifier: String) { - Self.openPhraseFile(fromURL: Self.userDictDataURL(mode: mode, type: type), appIdentifier: appIdentifier) + public func openPhraseFile(mode: Shared.InputMode, type: vChewingLM.ReplacableUserDataType, using app: FileOpenMethod) { + Self.openPhraseFile(fromURL: Self.userDictDataURL(mode: mode, type: type), using: app) } public func consolidate(text strProcessed: inout String, pragma shouldCheckPragma: Bool) { diff --git a/Packages/vChewing_MainAssembly/Sources/MainAssembly/LMMgr_Utilities.swift b/Packages/vChewing_MainAssembly/Sources/MainAssembly/LMMgr_Utilities.swift index 2084f409..4c690f34 100644 --- a/Packages/vChewing_MainAssembly/Sources/MainAssembly/LMMgr_Utilities.swift +++ b/Packages/vChewing_MainAssembly/Sources/MainAssembly/LMMgr_Utilities.swift @@ -273,30 +273,20 @@ public extension LMMgr { } static func openUserDictFile(type: vChewingLM.ReplacableUserDataType, dual: Bool = false, alt: Bool) { - let appIdentifier: String = alt ? "com.apple.TextEdit" : "com.apple.finder" - openPhraseFile(fromURL: userDictDataURL(mode: IMEApp.currentInputMode, type: type), appIdentifier: appIdentifier) + let app: FileOpenMethod = alt ? .textEdit : .finder + openPhraseFile(fromURL: userDictDataURL(mode: IMEApp.currentInputMode, type: type), using: app) guard dual else { return } - openPhraseFile(fromURL: userDictDataURL(mode: IMEApp.currentInputMode.reversed, type: type), appIdentifier: appIdentifier) + openPhraseFile(fromURL: userDictDataURL(mode: IMEApp.currentInputMode.reversed, type: type), using: app) } /// 用指定應用開啟指定檔案。 - /// - Remark: 如果你的 App 有 Sandbox 處理過的話,請勿給 app 傳入 "vim" 參數,因為 Sandbox 會阻止之。 /// - Parameters: /// - url: 檔案 URL。 - /// - appIdentifier: 指定 App 應用的 bundle identifier 名稱。 - static func openPhraseFile(fromURL url: URL, appIdentifier: String = "") { + /// - FileOpenMethod: 指定 App 應用。 + static func openPhraseFile(fromURL url: URL, using app: FileOpenMethod) { if !Self.checkIfUserFilesExistBeforeOpening() { return } DispatchQueue.main.async { - switch appIdentifier { - case "Finder", "com.apple.finder": - NSWorkspace.shared.activateFileViewerSelecting([url]) - default: - guard let textEditURL = NSWorkspace.shared.urlForApplication(withBundleIdentifier: "com.apple.TextEdit") else { return } - let toolURL = NSWorkspace.shared.urlForApplication(withBundleIdentifier: appIdentifier) ?? textEditURL - let configuration = NSWorkspace.OpenConfiguration() - configuration.promptsUserIfNeeded = true - NSWorkspace.shared.open([url], withApplicationAt: toolURL, configuration: configuration) - } + app.open(url: url) } } diff --git a/Packages/vChewing_PhraseEditorUI/Sources/PhraseEditorUI/PhraseEditorDelegate.swift b/Packages/vChewing_PhraseEditorUI/Sources/PhraseEditorUI/PhraseEditorDelegate.swift index 30a9585f..67a578f0 100644 --- a/Packages/vChewing_PhraseEditorUI/Sources/PhraseEditorUI/PhraseEditorDelegate.swift +++ b/Packages/vChewing_PhraseEditorUI/Sources/PhraseEditorUI/PhraseEditorDelegate.swift @@ -17,6 +17,6 @@ public protocol PhraseEditorDelegate { -> String func checkIfPhrasePairExists(userPhrase: String, mode: Shared.InputMode, key unigramKey: String) -> Bool func consolidate(text strProcessed: inout String, pragma shouldCheckPragma: Bool) - func openPhraseFile(mode: Shared.InputMode, type: vChewingLM.ReplacableUserDataType, appIdentifier: String) + func openPhraseFile(mode: Shared.InputMode, type: vChewingLM.ReplacableUserDataType, using: FileOpenMethod) func tagOverrides(in strProcessed: inout String, mode: Shared.InputMode) } diff --git a/Packages/vChewing_PhraseEditorUI/Sources/PhraseEditorUI/PhraseEditorUI.swift b/Packages/vChewing_PhraseEditorUI/Sources/PhraseEditorUI/PhraseEditorUI.swift index bbe256f1..8111848d 100644 --- a/Packages/vChewing_PhraseEditorUI/Sources/PhraseEditorUI/PhraseEditorUI.swift +++ b/Packages/vChewing_PhraseEditorUI/Sources/PhraseEditorUI/PhraseEditorUI.swift @@ -186,8 +186,8 @@ public struct VwrPhraseEditorUI: View { } private func callExternalAppToOpenPhraseFile() { - let app: String = NSEvent.keyModifierFlags.contains(.option) ? "com.apple.TextEdit" : "com.apple.finder" - delegate?.openPhraseFile(mode: selInputMode, type: selUserDataType, appIdentifier: app) + let app: FileOpenMethod = NSEvent.keyModifierFlags.contains(.option) ? .textEdit : .finder + delegate?.openPhraseFile(mode: selInputMode, type: selUserDataType, using: app) } // MARK: - Main View. diff --git a/Packages/vChewing_Shared/Sources/Shared/Shared.swift b/Packages/vChewing_Shared/Sources/Shared/Shared.swift index 9cf07e67..866a01fa 100644 --- a/Packages/vChewing_Shared/Sources/Shared/Shared.swift +++ b/Packages/vChewing_Shared/Sources/Shared/Shared.swift @@ -6,6 +6,7 @@ // marks, or product names of Contributor, except as required to fulfill notice // requirements defined in MIT License. +import AppKit import Foundation import SwiftExtension @@ -257,3 +258,44 @@ public class FileObserveProject: ObservableObject, Equatable { id = UUID().uuidString } } + +// MARK: - File Open Method + +public enum FileOpenMethod: String { + case finder = "Finder" + case textEdit = "TextEdit" + case safari = "Safari" + + public var appName: String { + switch self { + case .finder: return "Finder" + case .textEdit: return "TextEdit" + case .safari: return "Safari" + } + } + + public var bundleIdentifier: String { + switch self { + case .finder: return "com.apple.finder" + case .textEdit: return "com.apple.TextEdit" + case .safari: return "com.apple.Safari" + } + } + + public func open(url: URL) { + switch self { + case .finder: NSWorkspace.shared.activateFileViewerSelecting([url]) + default: + if #unavailable(macOS 10.15) { + NSWorkspace.shared.openFile(url.path, withApplication: appName) + return + } else { + let textEditURL = NSWorkspace.shared.urlForApplication(withBundleIdentifier: bundleIdentifier) + guard let textEditURL = textEditURL else { return } + let configuration = NSWorkspace.OpenConfiguration() + configuration.promptsUserIfNeeded = true + NSWorkspace.shared.open([url], withApplicationAt: textEditURL, configuration: configuration) + } + } + } +} diff --git a/Source/Modules/WindowControllers/CtlPrefWindow_PhraseEditor.swift b/Source/Modules/WindowControllers/CtlPrefWindow_PhraseEditor.swift index 54e08798..1d6f54c9 100644 --- a/Source/Modules/WindowControllers/CtlPrefWindow_PhraseEditor.swift +++ b/Source/Modules/WindowControllers/CtlPrefWindow_PhraseEditor.swift @@ -197,8 +197,8 @@ extension CtlPrefWindow: NSTextViewDelegate, NSTextFieldDelegate { @IBAction func openExternallyPEButtonClicked(_: NSButton) { DispatchQueue.main.async { [weak self] in guard let self = self else { return } - let app: String = NSEvent.keyModifierFlags.contains(.option) ? "com.apple.TextEdit" : "com.apple.finder" - LMMgr.shared.openPhraseFile(mode: self.selInputMode, type: self.selUserDataType, appIdentifier: app) + let app: FileOpenMethod = NSEvent.keyModifierFlags.contains(.option) ? .textEdit : .finder + LMMgr.shared.openPhraseFile(mode: self.selInputMode, type: self.selUserDataType, using: app) } }