2.8.0 SP3 // NotifierUI optimization, etc. Merge PR #161 from upd/2.8.0sp3

This commit is contained in:
ShikiSuen 2022-10-01 12:43:57 +08:00 committed by GitHub
commit 2af9cdebe2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 57 additions and 35 deletions

View File

@ -6,13 +6,10 @@
TDK 選字窗以純 SwiftUI 構築,用以取代此前自上游繼承來的 Voltaire 選字窗。 TDK 選字窗以純 SwiftUI 構築,用以取代此前自上游繼承來的 Voltaire 選字窗。
然而,TDK 選字窗目前有下述侷限: TDK 選字窗同時支援橫排矩陣佈局與縱排矩陣佈局。然而,目前有下述侷限:
- 因 SwiftUI 自身特性所導致的嚴重的效能問題。基本上來講,如果您經常使用全字庫模式的話,請在偏好設定內啟用效能更高的 IMK 選字窗。 - 因 SwiftUI 自身特性所導致的嚴重的效能問題(可能只會在幾年前的老電腦上出現)。基本上來講,如果您經常使用全字庫模式的話,請在偏好設定內啟用效能更高的 IMK 選字窗。
- 同樣出於上述原因,為了讓田所選字窗至少處於可在生產力環境下正常使用的狀態,就犧牲了捲動檢視的功能。也就是說,每次只顯示三行,但顯示內容則隨著使用者的游標操作而更新。 - 同樣出於上述原因,為了讓田所選字窗至少處於可在生產力環境下正常使用的狀態,就犧牲了捲動檢視的功能。也就是說,每次只顯示三行/三列,但顯示內容則隨著使用者的游標操作而更新。
- TDK 選字窗目前僅完成了橫版矩陣陳列模式的實作,且尚未引入對縱排選字窗陳列佈局的支援。
因為這些問題恐怕需要很久才能全部解決,所以威注音會在這段時間內推薦使用者們優先使用 IMK 選字窗。
``` ```
// (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).

View File

@ -20,7 +20,7 @@ extension CandidateCellData {
VStack(spacing: 0) { VStack(spacing: 0) {
HStack(spacing: 4) { HStack(spacing: 4) {
if UserDefaults.standard.bool(forKey: UserDef.kHandleDefaultCandidateFontsByLangIdentifier.rawValue) { 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)) Text(AttributedString(attributedString))
} else { } else {
Text(key).font(.system(size: fontSizeKey).monospaced()) Text(key).font(.system(size: fontSizeKey).monospaced())

View File

@ -26,14 +26,14 @@ public class Notifier: NSWindowController {
// MARK: - Private Declarations // MARK: - Private Declarations
private static var instanceStack: [Notifier] = [] private static var instanceSet: NSMutableOrderedSet = .init()
private let blankValue = "" private let blankValue = ""
@discardableResult private init(_ message: String) { @discardableResult private init(_ message: String) {
currentMessage = message currentMessage = message
let rawMessage = message.replacingOccurrences(of: "\n", with: "") let rawMessage = message.replacingOccurrences(of: "\n", with: "")
let isDuplicated: Bool = { let isDuplicated: Bool = {
if let firstInstanceExisted = Self.instanceStack.first { if let firstInstanceExisted = Self.instanceSet.firstNotifier {
return message == firstInstanceExisted.currentMessage && firstInstanceExisted.isNew return message == firstInstanceExisted.currentMessage && firstInstanceExisted.isNew
} }
return false return false
@ -42,8 +42,16 @@ public class Notifier: NSWindowController {
super.init(window: nil) super.init(window: nil)
return return
} }
// Swift
while Self.instanceSet.count > 3 {
if let instanceToRemove = Self.instanceSet.lastNotifier {
instanceToRemove.close()
Self.instanceSet.remove(instanceToRemove)
}
}
// //
defer { // 0.3 false defer {
// 0.3 false
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
self.isNew = false self.isNew = false
} }
@ -137,8 +145,8 @@ public class Notifier: NSWindowController {
extension Notifier { extension Notifier {
private func shiftExistingWindowPositions() { private func shiftExistingWindowPositions() {
guard let window = window, !Self.instanceStack.isEmpty else { return } guard let window = window else { return }
for theInstanceWindow in Self.instanceStack.compactMap(\.window) { Self.instanceSet.arrayOfWindows.forEach { theInstanceWindow in
var theOrigin = theInstanceWindow.frame var theOrigin = theInstanceWindow.frame
theOrigin.origin.y -= (10 + window.frame.height) theOrigin.origin.y -= (10 + window.frame.height)
theInstanceWindow.setFrame(theOrigin, display: true) theInstanceWindow.setFrame(theOrigin, display: true)
@ -156,19 +164,30 @@ extension Notifier {
} }
private func display() { private func display() {
let existingInstanceArray = Self.instanceStack.compactMap(\.window) Self.instanceSet.arrayOfWindows.forEach {
if !existingInstanceArray.isEmpty { $0.alphaValue -= 0.1
existingInstanceArray.forEach { $0.contentView?.subviews.forEach { $0.alphaValue *= 0.5 }
$0.alphaValue -= 0.1
$0.contentView?.subviews.forEach { $0.alphaValue *= 0.5 }
}
} }
shiftExistingWindowPositions() shiftExistingWindowPositions()
fadeIn() fadeIn()
Self.instanceStack.insert(self, at: 0) Self.instanceSet.insert(self, at: 0)
DispatchQueue.main.asyncAfter(deadline: .now() + 2) { DispatchQueue.main.asyncAfter(deadline: .now() + 1.3) {
self.close() self.close()
Self.instanceStack.removeAll(where: { $0.window == nil }) 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
}
}

View File

@ -14,14 +14,14 @@ let package = Package(
], ],
dependencies: [ dependencies: [
.package(path: "../vChewing_CocoaExtension"), .package(path: "../vChewing_CocoaExtension"),
.package(path: "../vChewing_SwiftExtension") .package(path: "../vChewing_SwiftExtension"),
], ],
targets: [ targets: [
.target( .target(
name: "Shared", name: "Shared",
dependencies: [ dependencies: [
.product(name: "CocoaExtension", package: "vChewing_CocoaExtension"), .product(name: "CocoaExtension", package: "vChewing_CocoaExtension"),
.product(name: "SwiftExtension", package: "vChewing_SwiftExtension") .product(name: "SwiftExtension", package: "vChewing_SwiftExtension"),
] ]
) )
] ]

View File

@ -60,8 +60,14 @@ public class CandidateCellData: Hashable {
let paraStyle = NSMutableParagraphStyle() let paraStyle = NSMutableParagraphStyle()
paraStyle.setParagraphStyle(NSParagraphStyle.default) paraStyle.setParagraphStyle(NSParagraphStyle.default)
paraStyle.alignment = .natural 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] = [ var attrKey: [NSAttributedString.Key: AnyObject] = [
.font: NSFont.monospacedDigitSystemFont(ofSize: size * 0.7, weight: .regular), .font: theFontForCandidateKey,
.paragraphStyle: paraStyleKey, .paragraphStyle: paraStyleKey,
] ]
if isSelected { if isSelected {

View File

@ -43,8 +43,8 @@ extension SessionCtl {
if PrefMgr.shared.showNotificationsWhenTogglingCapsLock { if PrefMgr.shared.showNotificationsWhenTogglingCapsLock {
Notifier.notify( Notifier.notify(
message: isCapsLockTurnedOn message: isCapsLockTurnedOn
? "Caps Lock" + NSLocalizedString("Alphanumerical Input Mode", comment: "") + "\n" + status ? "Caps Lock" + NSLocalizedString("Alphanumerical Input Mode", comment: "") + "\n" + status
: NSLocalizedString("Chinese Input Mode", comment: "") + "\n" + status : NSLocalizedString("Chinese Input Mode", comment: "") + "\n" + status
) )
} }
self.isASCIIMode = isCapsLockTurnedOn self.isASCIIMode = isCapsLockTurnedOn

View File

@ -5,7 +5,7 @@
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>2.8.0</string> <string>2.8.0</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>2802</string> <string>2803</string>
<key>UpdateInfoEndpoint</key> <key>UpdateInfoEndpoint</key>
<string>https://gitee.com/vchewing/vChewing-macOS/raw/main/Update-Info.plist</string> <string>https://gitee.com/vchewing/vChewing-macOS/raw/main/Update-Info.plist</string>
<key>UpdateInfoSite</key> <key>UpdateInfoSite</key>

View File

@ -1262,7 +1262,7 @@
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2802; CURRENT_PROJECT_VERSION = 2803;
GCC_C_LANGUAGE_STANDARD = gnu11; GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO; GCC_DYNAMIC_NO_PIC = NO;
GCC_PREPROCESSOR_DEFINITIONS = ( GCC_PREPROCESSOR_DEFINITIONS = (
@ -1302,7 +1302,7 @@
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2802; CURRENT_PROJECT_VERSION = 2803;
ENABLE_NS_ASSERTIONS = NO; ENABLE_NS_ASSERTIONS = NO;
GCC_C_LANGUAGE_STANDARD = gnu11; GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
@ -1341,7 +1341,7 @@
CODE_SIGN_IDENTITY = "-"; CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 2802; CURRENT_PROJECT_VERSION = 2803;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
ENABLE_HARDENED_RUNTIME = YES; ENABLE_HARDENED_RUNTIME = YES;
GCC_C_LANGUAGE_STANDARD = gnu11; GCC_C_LANGUAGE_STANDARD = gnu11;
@ -1394,7 +1394,7 @@
CODE_SIGN_IDENTITY = "-"; CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 2802; CURRENT_PROJECT_VERSION = 2803;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
ENABLE_HARDENED_RUNTIME = YES; ENABLE_HARDENED_RUNTIME = YES;
ENABLE_NS_ASSERTIONS = NO; ENABLE_NS_ASSERTIONS = NO;
@ -1529,7 +1529,7 @@
CODE_SIGN_IDENTITY = "-"; CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 2802; CURRENT_PROJECT_VERSION = 2803;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = ""; DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = "";
@ -1590,7 +1590,7 @@
CODE_SIGN_IDENTITY = "-"; CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 2802; CURRENT_PROJECT_VERSION = 2803;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = ""; DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = "";
@ -1638,7 +1638,7 @@
CODE_SIGN_IDENTITY = "-"; CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 2802; CURRENT_PROJECT_VERSION = 2803;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = "";
ENABLE_HARDENED_RUNTIME = YES; ENABLE_HARDENED_RUNTIME = YES;
@ -1684,7 +1684,7 @@
CODE_SIGN_IDENTITY = "-"; CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 2802; CURRENT_PROJECT_VERSION = 2803;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = "";
ENABLE_HARDENED_RUNTIME = YES; ENABLE_HARDENED_RUNTIME = YES;