diff --git a/Source/Modules/AppDelegate.swift b/Source/Modules/AppDelegate.swift index 56993a25..05e1c6f1 100644 --- a/Source/Modules/AppDelegate.swift +++ b/Source/Modules/AppDelegate.swift @@ -12,7 +12,7 @@ import Cocoa import InputMethodKit @objc(AppDelegate) -class AppDelegate: NSObject, NSApplicationDelegate, ctlNonModalAlertWindowDelegate, +class AppDelegate: NSObject, NSApplicationDelegate, FSEventStreamHelperDelegate, NSUserNotificationCenterDelegate { func helper(_: FSEventStreamHelper, didReceive _: [FSEventStreamHelper.Event]) { @@ -30,7 +30,6 @@ class AppDelegate: NSObject, NSApplicationDelegate, ctlNonModalAlertWindowDelega private var ctlPrefWindowInstance: ctlPrefWindow? private var ctlAboutWindowInstance: ctlAboutWindow? // New About Window private var checkTask: URLSessionTask? - private var updateNextStepURL: URL? public var fsStreamHelper = FSEventStreamHelper( path: mgrLangModel.dataFolderPath(isDefaultFolder: false), queue: DispatchQueue(label: "vChewing User Phrases") @@ -42,7 +41,6 @@ class AppDelegate: NSObject, NSApplicationDelegate, ctlNonModalAlertWindowDelega ctlPrefWindowInstance = nil ctlAboutWindowInstance = nil checkTask = nil - updateNextStepURL = nil fsStreamHelper.stop() fsStreamHelper.delegate = nil } @@ -137,7 +135,6 @@ class AppDelegate: NSObject, NSApplicationDelegate, ctlNonModalAlertWindowDelega case .success(let apiResult): switch apiResult { case .shouldUpdate(let report): - updateNextStepURL = report.siteUrl let content = String( format: NSLocalizedString( "You're currently using vChewing %@ (%@), a new version %@ (%@) is now available. Do you want to visit vChewing's website to download the version?%@", @@ -150,21 +147,17 @@ class AppDelegate: NSObject, NSApplicationDelegate, ctlNonModalAlertWindowDelega report.versionDescription ) IME.prtDebugIntel("vChewingDebug: \(content)") - currentAlertType = "Update" - ctlNonModalAlertWindow.shared.show( - title: NSLocalizedString( - "New Version Available", comment: "" - ), - content: content, - confirmButtonTitle: NSLocalizedString( - "Visit Website", comment: "" - ), - cancelButtonTitle: NSLocalizedString( - "Not Now", comment: "" - ), - cancelAsDefault: false, - delegate: self - ) + let alert = NSAlert() + alert.messageText = NSLocalizedString("New Version Available", comment: "") + alert.informativeText = content + alert.addButton(withTitle: NSLocalizedString("Visit Website", comment: "")) + alert.addButton(withTitle: NSLocalizedString("Not Now", comment: "")) + let result = alert.runModal() + if result == NSApplication.ModalResponse.alertFirstButtonReturn { + if let siteURL = report.siteUrl { + NSWorkspace.shared.open(siteURL) + } + } NSApp.setActivationPolicy(.accessory) case .noNeedToUpdate, .ignored: break @@ -172,9 +165,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, ctlNonModalAlertWindowDelega case .failure(let error): switch error { case VersionUpdateApiError.connectionError(let message): - let title = NSLocalizedString( - "Update Check Failed", comment: "" - ) + let title = NSLocalizedString("Update Check Failed", comment: "") let content = String( format: NSLocalizedString( "There may be no internet connection or the server failed to respond.\n\nError message: %@", @@ -183,13 +174,12 @@ class AppDelegate: NSObject, NSApplicationDelegate, ctlNonModalAlertWindowDelega ) let buttonTitle = NSLocalizedString("Dismiss", comment: "") IME.prtDebugIntel("vChewingDebug: \(content)") - currentAlertType = "Update" - ctlNonModalAlertWindow.shared.show( - title: title, content: content, - confirmButtonTitle: buttonTitle, - cancelButtonTitle: nil, - cancelAsDefault: false, delegate: nil - ) + + let alert = NSAlert() + alert.messageText = title + alert.informativeText = content + alert.addButton(withTitle: buttonTitle) + alert.runModal() NSApp.setActivationPolicy(.accessory) default: break @@ -205,41 +195,21 @@ class AppDelegate: NSObject, NSApplicationDelegate, ctlNonModalAlertWindowDelega "This will remove vChewing Input Method from this user account, requiring your confirmation.", comment: "" )) - ctlNonModalAlertWindow.shared.show( - title: NSLocalizedString("Uninstallation", comment: ""), content: content, - confirmButtonTitle: NSLocalizedString("OK", comment: ""), - cancelButtonTitle: NSLocalizedString("Not Now", comment: ""), cancelAsDefault: false, - delegate: self - ) + let alert = NSAlert() + alert.messageText = NSLocalizedString("Uninstallation", comment: "") + alert.informativeText = content + alert.addButton(withTitle: NSLocalizedString("OK", comment: "")) + alert.addButton(withTitle: NSLocalizedString("Not Now", comment: "")) + let result = alert.runModal() + if result == NSApplication.ModalResponse.alertFirstButtonReturn { + NSWorkspace.shared.openFile( + mgrLangModel.dataFolderPath(isDefaultFolder: true), withApplication: "Finder" + ) + IME.uninstall(isSudo: false, selfKill: true) + } NSApp.setActivationPolicy(.accessory) } - func ctlNonModalAlertWindowDidConfirm(_: ctlNonModalAlertWindow) { - switch currentAlertType { - case "Uninstall": - NSWorkspace.shared.openFile( - mgrLangModel.dataFolderPath(isDefaultFolder: true), withApplication: "Finder" - ) - IME.uninstall(isSudo: false, selfKill: true) - case "Update": - if let updateNextStepURL = updateNextStepURL { - NSWorkspace.shared.open(updateNextStepURL) - } - updateNextStepURL = nil - default: - break - } - } - - func ctlNonModalAlertWindowDidCancel(_: ctlNonModalAlertWindow) { - switch currentAlertType { - case "Update": - updateNextStepURL = nil - default: - break - } - } - // New About Window @IBAction func about(_: Any) { (NSApp.delegate as? AppDelegate)?.showAbout() diff --git a/Source/Modules/IMEModules/IME.swift b/Source/Modules/IMEModules/IME.swift index 42685365..9d800519 100644 --- a/Source/Modules/IMEModules/IME.swift +++ b/Source/Modules/IMEModules/IME.swift @@ -131,11 +131,11 @@ public enum IME { ), mgrLangModel.dataFolderPath(isDefaultFolder: false) ) - ctlNonModalAlertWindow.shared.show( - title: NSLocalizedString("Unable to create the user phrase file.", comment: ""), - content: content, confirmButtonTitle: NSLocalizedString("OK", comment: ""), - cancelButtonTitle: nil, cancelAsDefault: false, delegate: nil - ) + let alert = NSAlert() + alert.messageText = NSLocalizedString("Unable to create the user phrase file.", comment: "") + alert.informativeText = content + alert.addButton(withTitle: NSLocalizedString("OK", comment: "")) + alert.runModal() NSApp.setActivationPolicy(.accessory) return false } diff --git a/Source/WindowControllers/ctlNonModalAlertWindow.swift b/Source/WindowControllers/ctlNonModalAlertWindow.swift deleted file mode 100644 index e8c6c37c..00000000 --- a/Source/WindowControllers/ctlNonModalAlertWindow.swift +++ /dev/null @@ -1,114 +0,0 @@ -// (c) 2011 and onwards The OpenVanilla Project (MIT License). -// All possible vChewing-specific modifications are of: -// (c) 2021 and onwards The vChewing Project (MIT-NTL License). -// ==================== -// This code is released under the MIT license (SPDX-License-Identifier: MIT) -// ... with NTL restriction stating that: -// No trademark license is granted to use the trade names, trademarks, service -// marks, or product names of Contributor, except as required to fulfill notice -// requirements defined in MIT License. - -import Cocoa - -protocol ctlNonModalAlertWindowDelegate: AnyObject { - func ctlNonModalAlertWindowDidConfirm(_ controller: ctlNonModalAlertWindow) - func ctlNonModalAlertWindowDidCancel(_ controller: ctlNonModalAlertWindow) -} - -class ctlNonModalAlertWindow: NSWindowController { - static let shared = ctlNonModalAlertWindow(windowNibName: "frmNonModalAlertWindow") - - @IBOutlet var titleTextField: NSTextField! - @IBOutlet var contentTextField: NSTextField! - @IBOutlet var confirmButton: NSButton! - @IBOutlet var cancelButton: NSButton! - weak var delegate: ctlNonModalAlertWindowDelegate? - - func show( - title: String, content: String, confirmButtonTitle: String, cancelButtonTitle: String?, - cancelAsDefault: Bool, delegate: ctlNonModalAlertWindowDelegate? - ) { - guard let window = window else { return } - if window.isVisible == true { - self.delegate?.ctlNonModalAlertWindowDidCancel(self) - } - - self.delegate = delegate - - var oldFrame = confirmButton.frame - confirmButton.title = confirmButtonTitle - confirmButton.sizeToFit() - - var newFrame = confirmButton.frame - newFrame.size.width = max(90, newFrame.size.width + 10) - newFrame.origin.x += oldFrame.size.width - newFrame.size.width - confirmButton.frame = newFrame - - if let cancelButtonTitle = cancelButtonTitle { - cancelButton.title = cancelButtonTitle - cancelButton.sizeToFit() - var adjustFrame = cancelButton.frame - adjustFrame.size.width = max(90, adjustFrame.size.width + 10) - adjustFrame.origin.x = newFrame.origin.x - adjustFrame.size.width - confirmButton.frame = adjustFrame - cancelButton.isHidden = false - } else { - cancelButton.isHidden = true - } - - cancelButton.nextKeyView = confirmButton - confirmButton.nextKeyView = cancelButton - - if cancelButtonTitle != nil { - if cancelAsDefault { - window.defaultButtonCell = cancelButton.cell as? NSButtonCell - } else { - cancelButton.keyEquivalent = " " - window.defaultButtonCell = confirmButton.cell as? NSButtonCell - } - } else { - window.defaultButtonCell = confirmButton.cell as? NSButtonCell - } - - titleTextField.stringValue = title - - oldFrame = contentTextField.frame - contentTextField.stringValue = content - - var infiniteHeightFrame = oldFrame - infiniteHeightFrame.size.width -= 4.0 - infiniteHeightFrame.size.height = 10240 - newFrame = (content as NSString).boundingRect( - with: infiniteHeightFrame.size, options: [.usesLineFragmentOrigin], - attributes: [.font: contentTextField.font!] - ) - newFrame.size.width = max(newFrame.size.width, oldFrame.size.width) - newFrame.size.height += 4.0 - newFrame.origin = oldFrame.origin - newFrame.origin.y -= (newFrame.size.height - oldFrame.size.height) - contentTextField.frame = newFrame - - var windowFrame = window.frame - windowFrame.size.height += (newFrame.size.height - oldFrame.size.height) - window.level = NSWindow.Level(Int(CGShieldingWindowLevel()) + 1) - window.setFrame(windowFrame, display: true) - window.center() - window.makeKeyAndOrderFront(self) - NSApp.activate(ignoringOtherApps: true) - } - - @IBAction func confirmButtonAction(_: Any) { - delegate?.ctlNonModalAlertWindowDidConfirm(self) - window?.orderOut(self) - } - - @IBAction func cancelButtonAction(_ sender: Any) { - cancel(sender) - } - - func cancel(_: Any) { - delegate?.ctlNonModalAlertWindowDidCancel(self) - delegate = nil - window?.orderOut(self) - } -} diff --git a/Source/WindowNIBs/Base.lproj/frmNonModalAlertWindow.xib b/Source/WindowNIBs/Base.lproj/frmNonModalAlertWindow.xib deleted file mode 100644 index 20368443..00000000 --- a/Source/WindowNIBs/Base.lproj/frmNonModalAlertWindow.xib +++ /dev/null @@ -1,108 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vChewing.xcodeproj/project.pbxproj b/vChewing.xcodeproj/project.pbxproj index 3f11c3f0..98d49aa9 100644 --- a/vChewing.xcodeproj/project.pbxproj +++ b/vChewing.xcodeproj/project.pbxproj @@ -78,7 +78,6 @@ 5BB802DA27FABA8300CF1C19 /* ctlInputMethod_Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BB802D927FABA8300CF1C19 /* ctlInputMethod_Menu.swift */; }; 5BBBB75F27AED54C0023B93A /* Beep.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 5BBBB75D27AED54C0023B93A /* Beep.m4a */; }; 5BBBB76027AED54C0023B93A /* Fart.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 5BBBB75E27AED54C0023B93A /* Fart.m4a */; }; - 5BBBB76B27AED5DB0023B93A /* frmNonModalAlertWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5BBBB76527AED5DB0023B93A /* frmNonModalAlertWindow.xib */; }; 5BBBB76D27AED5DB0023B93A /* frmAboutWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5BBBB76927AED5DB0023B93A /* frmAboutWindow.xib */; }; 5BBBB77327AED70B0023B93A /* MenuIcon-TCVIM@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 5BBBB76F27AED70B0023B93A /* MenuIcon-TCVIM@2x.png */; }; 5BBBB77427AED70B0023B93A /* MenuIcon-SCVIM@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 5BBBB77027AED70B0023B93A /* MenuIcon-SCVIM@2x.png */; }; @@ -137,7 +136,6 @@ D427F76C278CA2B0004A2160 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D427F76B278CA1BA004A2160 /* AppDelegate.swift */; }; D47B92C027972AD100458394 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = D47B92BF27972AC800458394 /* main.swift */; }; D47F7DCE278BFB57002F9DD7 /* ctlPrefWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = D47F7DCD278BFB57002F9DD7 /* ctlPrefWindow.swift */; }; - D47F7DD0278C0897002F9DD7 /* ctlNonModalAlertWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = D47F7DCF278C0897002F9DD7 /* ctlNonModalAlertWindow.swift */; }; D4A13D5A27A59F0B003BE359 /* ctlInputMethod_Core.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4A13D5927A59D5C003BE359 /* ctlInputMethod_Core.swift */; }; D4E33D8A27A838CF006DB1CF /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = D4E33D8827A838CF006DB1CF /* Localizable.strings */; }; D4E33D8F27A838F0006DB1CF /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = D4E33D8D27A838F0006DB1CF /* InfoPlist.strings */; }; @@ -296,7 +294,6 @@ 5BB802D927FABA8300CF1C19 /* ctlInputMethod_Menu.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = ctlInputMethod_Menu.swift; sourceTree = ""; tabWidth = 2; usesTabs = 0; }; 5BBBB75D27AED54C0023B93A /* Beep.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = Beep.m4a; sourceTree = ""; }; 5BBBB75E27AED54C0023B93A /* Fart.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = Fart.m4a; sourceTree = ""; }; - 5BBBB76627AED5DB0023B93A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/frmNonModalAlertWindow.xib; sourceTree = ""; }; 5BBBB76A27AED5DB0023B93A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/frmAboutWindow.xib; sourceTree = ""; }; 5BBBB76F27AED70B0023B93A /* MenuIcon-TCVIM@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "MenuIcon-TCVIM@2x.png"; sourceTree = ""; }; 5BBBB77027AED70B0023B93A /* MenuIcon-SCVIM@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "MenuIcon-SCVIM@2x.png"; sourceTree = ""; }; @@ -369,7 +366,6 @@ D427F76B278CA1BA004A2160 /* AppDelegate.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = AppDelegate.swift; sourceTree = ""; tabWidth = 2; usesTabs = 0; }; D47B92BF27972AC800458394 /* main.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = main.swift; sourceTree = ""; tabWidth = 2; usesTabs = 0; }; D47F7DCD278BFB57002F9DD7 /* ctlPrefWindow.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = ctlPrefWindow.swift; sourceTree = ""; tabWidth = 2; usesTabs = 0; }; - D47F7DCF278C0897002F9DD7 /* ctlNonModalAlertWindow.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = ctlNonModalAlertWindow.swift; sourceTree = ""; tabWidth = 2; usesTabs = 0; }; D4A13D5927A59D5C003BE359 /* ctlInputMethod_Core.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = ctlInputMethod_Core.swift; sourceTree = ""; tabWidth = 2; usesTabs = 0; }; D4E33D8927A838CF006DB1CF /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/Localizable.strings; sourceTree = ""; }; D4E33D8E27A838F0006DB1CF /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/InfoPlist.strings; sourceTree = ""; }; @@ -586,7 +582,6 @@ isa = PBXGroup; children = ( 5B62A33C27AE7CC100A19448 /* ctlAboutWindow.swift */, - D47F7DCF278C0897002F9DD7 /* ctlNonModalAlertWindow.swift */, D47F7DCD278BFB57002F9DD7 /* ctlPrefWindow.swift */, ); path = WindowControllers; @@ -596,7 +591,6 @@ isa = PBXGroup; children = ( 5BBBB76927AED5DB0023B93A /* frmAboutWindow.xib */, - 5BBBB76527AED5DB0023B93A /* frmNonModalAlertWindow.xib */, 5B7BC4AE27AFFBE800F66C24 /* frmPrefWindow.xib */, 6A187E2816004C5900466B2E /* MainMenu.xib */, ); @@ -1070,7 +1064,6 @@ 5BBBB76027AED54C0023B93A /* Fart.m4a in Resources */, 6A2E40F6253A69DA00D1AE1D /* Images.xcassets in Resources */, D4E33D8F27A838F0006DB1CF /* InfoPlist.strings in Resources */, - 5BBBB76B27AED5DB0023B93A /* frmNonModalAlertWindow.xib in Resources */, 5BEDB723283B4C250078EB25 /* data-cht.plist in Resources */, 5BEDB721283B4C250078EB25 /* data-cns.plist in Resources */, 5BF9DA2D288427E000DBD48E /* template-associatedPhrases-cht.txt in Resources */, @@ -1217,7 +1210,6 @@ 5B84579F2871AD2200C93B01 /* HotenkaChineseConverter.swift in Sources */, 5B887F302826AEA400B6651E /* lmCoreEX.swift in Sources */, 5BA9FD4627FEF3C9002DE248 /* Container.swift in Sources */, - D47F7DD0278C0897002F9DD7 /* ctlNonModalAlertWindow.swift in Sources */, 5B2170E5289FACAD00BE7304 /* 6_Node.swift in Sources */, 5B949BD92816DC5400D87B5D /* LineReader.swift in Sources */, 5BA9FD1027FEDB6B002DE248 /* suiPrefPaneKeyboard.swift in Sources */, @@ -1344,14 +1336,6 @@ name = frmPrefWindow.xib; sourceTree = ""; }; - 5BBBB76527AED5DB0023B93A /* frmNonModalAlertWindow.xib */ = { - isa = PBXVariantGroup; - children = ( - 5BBBB76627AED5DB0023B93A /* Base */, - ); - name = frmNonModalAlertWindow.xib; - sourceTree = ""; - }; 5BBBB76927AED5DB0023B93A /* frmAboutWindow.xib */ = { isa = PBXVariantGroup; children = (