From 9ce8c9f302392e541aa11a423d150448fe22fc60 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Fri, 30 Sep 2022 14:39:47 +0800 Subject: [PATCH 1/6] TDKCandidates // Fix outdated README. --- Packages/vChewing_CandidateWindow/README.md | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/Packages/vChewing_CandidateWindow/README.md b/Packages/vChewing_CandidateWindow/README.md index f4370531..50791042 100644 --- a/Packages/vChewing_CandidateWindow/README.md +++ b/Packages/vChewing_CandidateWindow/README.md @@ -6,13 +6,10 @@ TDK 選字窗以純 SwiftUI 構築,用以取代此前自上游繼承來的 Voltaire 選字窗。 -然而,TDK 選字窗目前有下述侷限: +TDK 選字窗同時支援橫排矩陣佈局與縱排矩陣佈局。然而,目前有下述侷限: -- 因 SwiftUI 自身特性所導致的嚴重的效能問題。基本上來講,如果您經常使用全字庫模式的話,請在偏好設定內啟用效能更高的 IMK 選字窗。 -- 同樣出於上述原因,為了讓田所選字窗至少處於可在生產力環境下正常使用的狀態,就犧牲了捲動檢視的功能。也就是說,每次只顯示三行,但顯示內容則隨著使用者的游標操作而更新。 -- TDK 選字窗目前僅完成了橫版矩陣陳列模式的實作,且尚未引入對縱排選字窗陳列佈局的支援。 - -因為這些問題恐怕需要很久才能全部解決,所以威注音會在這段時間內推薦使用者們優先使用 IMK 選字窗。 +- 因 SwiftUI 自身特性所導致的嚴重的效能問題(可能只會在幾年前的老電腦上出現)。基本上來講,如果您經常使用全字庫模式的話,請在偏好設定內啟用效能更高的 IMK 選字窗。 +- 同樣出於上述原因,為了讓田所選字窗至少處於可在生產力環境下正常使用的狀態,就犧牲了捲動檢視的功能。也就是說,每次只顯示三行/三列,但顯示內容則隨著使用者的游標操作而更新。 ``` // (c) 2021 and onwards The vChewing Project (MIT-NTL License). From 4aba08cba97aeec20b215654bee56fd532236bb9 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Sat, 1 Oct 2022 09:33:16 +0800 Subject: [PATCH 2/6] Repo // Clang-format. --- Packages/vChewing_Shared/Package.swift | 4 ++-- Source/Modules/SessionCtl_HandleEvent.swift | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Packages/vChewing_Shared/Package.swift b/Packages/vChewing_Shared/Package.swift index 64cd0752..09b9cbf2 100644 --- a/Packages/vChewing_Shared/Package.swift +++ b/Packages/vChewing_Shared/Package.swift @@ -14,14 +14,14 @@ let package = Package( ], dependencies: [ .package(path: "../vChewing_CocoaExtension"), - .package(path: "../vChewing_SwiftExtension") + .package(path: "../vChewing_SwiftExtension"), ], targets: [ .target( name: "Shared", dependencies: [ .product(name: "CocoaExtension", package: "vChewing_CocoaExtension"), - .product(name: "SwiftExtension", package: "vChewing_SwiftExtension") + .product(name: "SwiftExtension", package: "vChewing_SwiftExtension"), ] ) ] diff --git a/Source/Modules/SessionCtl_HandleEvent.swift b/Source/Modules/SessionCtl_HandleEvent.swift index cebf4250..e9d6b01b 100644 --- a/Source/Modules/SessionCtl_HandleEvent.swift +++ b/Source/Modules/SessionCtl_HandleEvent.swift @@ -43,8 +43,8 @@ extension SessionCtl { if PrefMgr.shared.showNotificationsWhenTogglingCapsLock { Notifier.notify( message: isCapsLockTurnedOn - ? "Caps Lock" + NSLocalizedString("Alphanumerical Input Mode", comment: "") + "\n" + status - : NSLocalizedString("Chinese Input Mode", comment: "") + "\n" + status + ? "Caps Lock" + NSLocalizedString("Alphanumerical Input Mode", comment: "") + "\n" + status + : NSLocalizedString("Chinese Input Mode", comment: "") + "\n" + status ) } self.isASCIIMode = isCapsLockTurnedOn From 4443583fb6d218ee2bc8e2454096659a8657ef35 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Sat, 1 Oct 2022 09:05:32 +0800 Subject: [PATCH 3/6] NotifierUI // Fix memory and CPU issues by limiting instances. --- .../Sources/NotifierUI/NotifierUI.swift | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/Packages/vChewing_NotifierUI/Sources/NotifierUI/NotifierUI.swift b/Packages/vChewing_NotifierUI/Sources/NotifierUI/NotifierUI.swift index cbf7c9f5..24c48da2 100644 --- a/Packages/vChewing_NotifierUI/Sources/NotifierUI/NotifierUI.swift +++ b/Packages/vChewing_NotifierUI/Sources/NotifierUI/NotifierUI.swift @@ -42,8 +42,11 @@ public class Notifier: NSWindowController { super.init(window: nil) return } + // 剔除溢出的副本,讓 Swift 自動回收之。 + while Self.instanceStack.count > 3 { Self.instanceStack.removeLast().close() } // 正式進入處理環節。 - defer { // 先讓新通知標記自此開始過 0.3 秒自動變為 false。 + defer { + // 先讓新通知標記自此開始過 0.3 秒自動變為 false。 DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { self.isNew = false } @@ -137,8 +140,8 @@ public class Notifier: NSWindowController { extension Notifier { private func shiftExistingWindowPositions() { - guard let window = window, !Self.instanceStack.isEmpty else { return } - for theInstanceWindow in Self.instanceStack.compactMap(\.window) { + guard let window = window else { return } + Self.instanceStack.compactMap(\.window).forEach { theInstanceWindow in var theOrigin = theInstanceWindow.frame theOrigin.origin.y -= (10 + window.frame.height) theInstanceWindow.setFrame(theOrigin, display: true) @@ -156,19 +159,18 @@ extension Notifier { } private func display() { - let existingInstanceArray = Self.instanceStack.compactMap(\.window) - if !existingInstanceArray.isEmpty { - existingInstanceArray.forEach { - $0.alphaValue -= 0.1 - $0.contentView?.subviews.forEach { $0.alphaValue *= 0.5 } - } + Self.instanceStack.compactMap(\.window).forEach { + $0.alphaValue -= 0.1 + $0.contentView?.subviews.forEach { $0.alphaValue *= 0.5 } } shiftExistingWindowPositions() fadeIn() Self.instanceStack.insert(self, at: 0) - DispatchQueue.main.asyncAfter(deadline: .now() + 2) { + DispatchQueue.main.asyncAfter(deadline: .now() + 1.3) { self.close() - Self.instanceStack.removeAll(where: { $0.window == nil }) + if let idx = Self.instanceStack.firstIndex(where: { $0 === self }) { + Self.instanceStack.remove(at: idx) + } } } } From d2b99680fd9d9a5c3b113cf434a40c9e7a33350b Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Sat, 1 Oct 2022 10:42:53 +0800 Subject: [PATCH 4/6] NotifierUI // Use extended NSOrderedSet in lieu of array. --- .../Sources/NotifierUI/NotifierUI.swift | 35 ++++++++++++++----- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/Packages/vChewing_NotifierUI/Sources/NotifierUI/NotifierUI.swift b/Packages/vChewing_NotifierUI/Sources/NotifierUI/NotifierUI.swift index 24c48da2..36db02ce 100644 --- a/Packages/vChewing_NotifierUI/Sources/NotifierUI/NotifierUI.swift +++ b/Packages/vChewing_NotifierUI/Sources/NotifierUI/NotifierUI.swift @@ -26,14 +26,14 @@ public class Notifier: NSWindowController { // MARK: - Private Declarations - private static var instanceStack: [Notifier] = [] + private static var instanceSet: NSMutableOrderedSet = .init() private let blankValue = "" @discardableResult private init(_ message: String) { currentMessage = message let rawMessage = message.replacingOccurrences(of: "\n", with: "") let isDuplicated: Bool = { - if let firstInstanceExisted = Self.instanceStack.first { + if let firstInstanceExisted = Self.instanceSet.firstNotifier { return message == firstInstanceExisted.currentMessage && firstInstanceExisted.isNew } return false @@ -43,7 +43,12 @@ public class Notifier: NSWindowController { return } // 剔除溢出的副本,讓 Swift 自動回收之。 - while Self.instanceStack.count > 3 { Self.instanceStack.removeLast().close() } + while Self.instanceSet.count > 3 { + if let instanceToRemove = Self.instanceSet.lastNotifier { + instanceToRemove.close() + Self.instanceSet.remove(instanceToRemove) + } + } // 正式進入處理環節。 defer { // 先讓新通知標記自此開始過 0.3 秒自動變為 false。 @@ -141,7 +146,7 @@ public class Notifier: NSWindowController { extension Notifier { private func shiftExistingWindowPositions() { guard let window = window else { return } - Self.instanceStack.compactMap(\.window).forEach { theInstanceWindow in + Self.instanceSet.arrayOfWindows.forEach { theInstanceWindow in var theOrigin = theInstanceWindow.frame theOrigin.origin.y -= (10 + window.frame.height) theInstanceWindow.setFrame(theOrigin, display: true) @@ -159,18 +164,30 @@ extension Notifier { } private func display() { - Self.instanceStack.compactMap(\.window).forEach { + Self.instanceSet.arrayOfWindows.forEach { $0.alphaValue -= 0.1 $0.contentView?.subviews.forEach { $0.alphaValue *= 0.5 } } shiftExistingWindowPositions() fadeIn() - Self.instanceStack.insert(self, at: 0) + Self.instanceSet.insert(self, at: 0) DispatchQueue.main.asyncAfter(deadline: .now() + 1.3) { self.close() - if let idx = Self.instanceStack.firstIndex(where: { $0 === self }) { - Self.instanceStack.remove(at: idx) - } + Self.instanceSet.remove(self) } } } + +extension NSMutableOrderedSet { + fileprivate var arrayOfWindows: [NSWindow] { compactMap { ($0 as? Notifier)?.window } } + + fileprivate var firstNotifier: Notifier? { + for neta in self { if let result = neta as? Notifier { return result } } + return nil + } + + fileprivate var lastNotifier: Notifier? { + for neta in reversed { if let result = neta as? Notifier { return result } } + return nil + } +} From 2b66a81b18d3bdbb9669aed7dcc8ecb9b4c3a374 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Sat, 1 Oct 2022 12:17:34 +0800 Subject: [PATCH 5/6] TDKCandidates // Fix font clipping when lang identifier is enabled. --- .../CandidateWindow/CandidateCellDataExtension.swift | 2 +- .../Sources/Shared/CandidateBasicUnits.swift | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/CandidateCellDataExtension.swift b/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/CandidateCellDataExtension.swift index 4016374c..08417282 100644 --- a/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/CandidateCellDataExtension.swift +++ b/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/CandidateCellDataExtension.swift @@ -20,7 +20,7 @@ extension CandidateCellData { VStack(spacing: 0) { HStack(spacing: 4) { if UserDefaults.standard.bool(forKey: UserDef.kHandleDefaultCandidateFontsByLangIdentifier.rawValue) { - Text(AttributedString(attributedStringHeader)).frame(width: CandidateCellData.unifiedSize / 2) + Text(AttributedString(attributedStringHeader)).frame(width: CandidateCellData.unifiedSize * 2 / 3) Text(AttributedString(attributedString)) } else { Text(key).font(.system(size: fontSizeKey).monospaced()) diff --git a/Packages/vChewing_Shared/Sources/Shared/CandidateBasicUnits.swift b/Packages/vChewing_Shared/Sources/Shared/CandidateBasicUnits.swift index 6544a6bc..7428d86a 100644 --- a/Packages/vChewing_Shared/Sources/Shared/CandidateBasicUnits.swift +++ b/Packages/vChewing_Shared/Sources/Shared/CandidateBasicUnits.swift @@ -60,8 +60,14 @@ public class CandidateCellData: Hashable { let paraStyle = NSMutableParagraphStyle() paraStyle.setParagraphStyle(NSParagraphStyle.default) paraStyle.alignment = .natural + let theFontForCandidateKey: NSFont = { + if #available(macOS 10.15, *) { + return NSFont.monospacedSystemFont(ofSize: size * 0.7, weight: .regular) + } + return NSFont.monospacedDigitSystemFont(ofSize: size * 0.7, weight: .regular) + }() var attrKey: [NSAttributedString.Key: AnyObject] = [ - .font: NSFont.monospacedDigitSystemFont(ofSize: size * 0.7, weight: .regular), + .font: theFontForCandidateKey, .paragraphStyle: paraStyleKey, ] if isSelected { From 6b5059ac380b8a96baf2b6a39fc6bac187135667 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Sat, 1 Oct 2022 10:29:37 +0800 Subject: [PATCH 6/6] Bump version to 2.8.0 SP3 Build 2803. --- Update-Info.plist | 2 +- vChewing.xcodeproj/project.pbxproj | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Update-Info.plist b/Update-Info.plist index 7cefa8ed..edd59520 100644 --- a/Update-Info.plist +++ b/Update-Info.plist @@ -5,7 +5,7 @@ CFBundleShortVersionString 2.8.0 CFBundleVersion - 2802 + 2803 UpdateInfoEndpoint https://gitee.com/vchewing/vChewing-macOS/raw/main/Update-Info.plist UpdateInfoSite diff --git a/vChewing.xcodeproj/project.pbxproj b/vChewing.xcodeproj/project.pbxproj index c98266f6..46fbab46 100644 --- a/vChewing.xcodeproj/project.pbxproj +++ b/vChewing.xcodeproj/project.pbxproj @@ -1262,7 +1262,7 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 2802; + CURRENT_PROJECT_VERSION = 2803; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -1302,7 +1302,7 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 2802; + CURRENT_PROJECT_VERSION = 2803; ENABLE_NS_ASSERTIONS = NO; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; @@ -1341,7 +1341,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 2802; + CURRENT_PROJECT_VERSION = 2803; DEAD_CODE_STRIPPING = YES; ENABLE_HARDENED_RUNTIME = YES; GCC_C_LANGUAGE_STANDARD = gnu11; @@ -1394,7 +1394,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 2802; + CURRENT_PROJECT_VERSION = 2803; DEAD_CODE_STRIPPING = YES; ENABLE_HARDENED_RUNTIME = YES; ENABLE_NS_ASSERTIONS = NO; @@ -1529,7 +1529,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 2802; + CURRENT_PROJECT_VERSION = 2803; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_ASSET_PATHS = ""; DEVELOPMENT_TEAM = ""; @@ -1590,7 +1590,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 2802; + CURRENT_PROJECT_VERSION = 2803; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_ASSET_PATHS = ""; DEVELOPMENT_TEAM = ""; @@ -1638,7 +1638,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 2802; + CURRENT_PROJECT_VERSION = 2803; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = ""; ENABLE_HARDENED_RUNTIME = YES; @@ -1684,7 +1684,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 2802; + CURRENT_PROJECT_VERSION = 2803; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = ""; ENABLE_HARDENED_RUNTIME = YES;