Skip to content

Commit

Permalink
fix: unable to delete shortcut & menubar shortcut update & refactor u…
Browse files Browse the repository at this point in the history
…sing defaults bridge
  • Loading branch information
CanglongCl committed Jan 21, 2024
1 parent 17e264b commit f693368
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 66 deletions.
12 changes: 12 additions & 0 deletions Easydict.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,7 @@
DC3C643F2B187119008EEDD8 /* ChangeFontSizeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC3C643E2B187119008EEDD8 /* ChangeFontSizeView.swift */; };
DC6D9C872B352EBC0055EFFC /* FontSizeHintView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC6D9C862B352EBC0055EFFC /* FontSizeHintView.swift */; };
DC6D9C892B3969510055EFFC /* Appearance.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC6D9C882B3969510055EFFC /* Appearance.swift */; };
EA1013442B5DBDB1005E43F9 /* KeyCombo+Defaults.Serializable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA1013432B5DBDB1005E43F9 /* KeyCombo+Defaults.Serializable.swift */; };
EA3B81F92B5254AA004C0E8B /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA3B81F82B5254AA004C0E8B /* Configuration.swift */; };
EA3B81FC2B52555C004C0E8B /* Defaults in Frameworks */ = {isa = PBXBuildFile; productRef = EA3B81FB2B52555C004C0E8B /* Defaults */; };
EA9943E32B534C3300EE7B97 /* TTSServiceType.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA9943E22B534C3300EE7B97 /* TTSServiceType.swift */; };
Expand Down Expand Up @@ -769,6 +770,7 @@
DC3C643E2B187119008EEDD8 /* ChangeFontSizeView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChangeFontSizeView.swift; sourceTree = "<group>"; };
DC6D9C862B352EBC0055EFFC /* FontSizeHintView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FontSizeHintView.swift; sourceTree = "<group>"; };
DC6D9C882B3969510055EFFC /* Appearance.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Appearance.swift; sourceTree = "<group>"; };
EA1013432B5DBDB1005E43F9 /* KeyCombo+Defaults.Serializable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "KeyCombo+Defaults.Serializable.swift"; sourceTree = "<group>"; };
EA3B81F82B5254AA004C0E8B /* Configuration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Configuration.swift; sourceTree = "<group>"; };
EA9943E22B534C3300EE7B97 /* TTSServiceType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TTSServiceType.swift; sourceTree = "<group>"; };
EA9943E72B534D8900EE7B97 /* LanguageDetectOptimizeExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LanguageDetectOptimizeExtensions.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2256,6 +2258,14 @@
path = ChangeFontSizeView;
sourceTree = "<group>";
};
EA1013412B5DBDA5005E43F9 /* Defaults */ = {
isa = PBXGroup;
children = (
EA1013432B5DBDB1005E43F9 /* KeyCombo+Defaults.Serializable.swift */,
);
path = Defaults;
sourceTree = "<group>";
};
EA3B81F72B52549B004C0E8B /* Configuration */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -2284,6 +2294,7 @@
EA9943E62B534D7C00EE7B97 /* Extensions */ = {
isa = PBXGroup;
children = (
EA1013412B5DBDA5005E43F9 /* Defaults */,
EAED41F02B54B1A60005FE0A /* QueryService+ConfigurableService */,
EA9943E72B534D8900EE7B97 /* LanguageDetectOptimizeExtensions.swift */,
EA9943ED2B5353AB00EE7B97 /* WindowTypeExtensions.swift */,
Expand Down Expand Up @@ -2745,6 +2756,7 @@
03BB2DEB29F57DC000447EDD /* NSImage+EZSymbolmage.m in Sources */,
03B0230629231FA6001C7E63 /* EZLabel.m in Sources */,
03F25CB329327BC200E66A12 /* EZShortcut.m in Sources */,
EA1013442B5DBDB1005E43F9 /* KeyCombo+Defaults.Serializable.swift in Sources */,
033B7134293CE2430096E2DF /* EZWebViewTranslator.m in Sources */,
03CF88632B137F650030C199 /* Array+Convenience.swift in Sources */,
03B0231229231FA6001C7E63 /* NSObject+DarkMode.m in Sources */,
Expand Down
3 changes: 3 additions & 0 deletions Easydict/App/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -3412,6 +3412,9 @@
}
}
}
},
"xx" : {

},
"Youdao" : {
"extractionState" : "manual",
Expand Down
11 changes: 6 additions & 5 deletions Easydict/NewApp/Configuration/Configuration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import Defaults
import Foundation
import Magnet

// Setting
extension Defaults.Keys {
Expand Down Expand Up @@ -90,9 +91,9 @@ extension Defaults.Keys {

/// shortcut
extension Defaults.Keys {
static let selectionShortcutKey = Key<Data>("EZSelectionShortcutKey_keyHolder", default: Data())
static let snipShortcutKey = Key<Data>("EZSnipShortcutKey_keyHolder", default: Data())
static let inputShortcutKey = Key<Data>("EZInputShortcutKey_keyHolder", default: Data())
static let screenshotOCRShortcutKey = Key<Data>("EZScreenshotOCRShortcutKey_keyHolder", default: Data())
static let showMiniWindowShortcutKey = Key<Data>("EZShowMiniShortcutKey_keyHolder", default: Data())
static let selectionShortcut = Key<KeyCombo?>("EZSelectionShortcutKey_keyHolder", default: nil)
static let snipShortcut = Key<KeyCombo?>("EZSnipShortcutKey_keyHolder", default: nil)
static let inputShortcut = Key<KeyCombo?>("EZInputShortcutKey_keyHolder", default: nil)
static let screenshotOCRShortcut = Key<KeyCombo?>("EZScreenshotOCRShortcutKey_keyHolder", default: nil)
static let showMiniWindowShortcut = Key<KeyCombo?>("EZShowMiniShortcutKey_keyHolder", default: nil)
}
101 changes: 54 additions & 47 deletions Easydict/NewApp/Feature/Shortcut/Shortcut.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,57 +49,31 @@ class Shortcut: NSObject {
// restore shortcut
extension Shortcut {
func restoreShortcut() {
if let inputTranslateKeyCombo = restoreInputTranslate() {
if let inputTranslateKeyCombo = Defaults[.inputShortcut] {
bindingShortCut(keyCombo: inputTranslateKeyCombo, type: .inputTranslate)
}
if let snipShortcutKeyKeyCombo = restoreSnipShortcutKey() {
if let snipShortcutKeyKeyCombo = Defaults[.snipShortcut] {
bindingShortCut(keyCombo: snipShortcutKeyKeyCombo, type: .snipTranslate)
}
if let selectionShortcutKeyCombo = restoreSelectionShortcutKey() {
if let selectionShortcutKeyCombo = Defaults[.selectionShortcut] {
bindingShortCut(keyCombo: selectionShortcutKeyCombo, type: .selectTranslate)
}
if let screenshotOCRShortcutKeyCombo = restoreScreenshotOCRShortcutKey() {
if let screenshotOCRShortcutKeyCombo = Defaults[.screenshotOCRShortcut] {
bindingShortCut(keyCombo: screenshotOCRShortcutKeyCombo, type: .silentScreenshotOcr)
}
if let showMiniWindowShortcutKeyCombo = restoreShowMiniWindow() {
if let showMiniWindowShortcutKeyCombo = Defaults[.showMiniWindowShortcut] {
bindingShortCut(keyCombo: showMiniWindowShortcutKeyCombo, type: .showMiniWindow)
}
}

private func restoreInputTranslate() -> KeyCombo? {
let data = Defaults[.inputShortcutKey]
guard let keyCombo = try? JSONDecoder().decode(KeyCombo.self, from: data) else { return nil }
return keyCombo
}

private func restoreSnipShortcutKey() -> KeyCombo? {
let data = Defaults[.snipShortcutKey]
guard let keyCombo = try? JSONDecoder().decode(KeyCombo.self, from: data) else { return nil }
return keyCombo
}

private func restoreSelectionShortcutKey() -> KeyCombo? {
let data = Defaults[.selectionShortcutKey]
guard let keyCombo = try? JSONDecoder().decode(KeyCombo.self, from: data) else { return nil }
return keyCombo
}

private func restoreScreenshotOCRShortcutKey() -> KeyCombo? {
let data = Defaults[.screenshotOCRShortcutKey]
guard let keyCombo = try? JSONDecoder().decode(KeyCombo.self, from: data) else { return nil }
return keyCombo
}

private func restoreShowMiniWindow() -> KeyCombo? {
let data = Defaults[.showMiniWindowShortcutKey]
guard let keyCombo = try? JSONDecoder().decode(KeyCombo.self, from: data) else { return nil }
return keyCombo
}
}

// binding shortcut
extension Shortcut {
func bindingShortCut(keyCombo: KeyCombo, type: ShortcutType) {
func bindingShortCut(keyCombo: KeyCombo?, type: ShortcutType) {
guard let keyCombo else {
HotKeyCenter.shared.unregisterHotKey(with: type.rawValue)
return
}
var hotKey: HotKey
switch type {
case .inputTranslate:
Expand Down Expand Up @@ -160,30 +134,54 @@ extension Shortcut {
public func shortcutKeyCombo(_ type: ShortcutType) -> KeyCombo? {
switch type {
case .inputTranslate:
guard let keyCombo = restoreInputTranslate() else { return nil }
guard let keyCombo = Defaults[.inputShortcut] else { return nil }
return keyCombo
case .snipTranslate:
guard let keyCombo = restoreSnipShortcutKey() else { return nil }
guard let keyCombo = Defaults[.snipShortcut] else { return nil }
return keyCombo
case .selectTranslate:
guard let keyCombo = restoreSelectionShortcutKey() else { return nil }
guard let keyCombo = Defaults[.selectionShortcut] else { return nil }
return keyCombo
case .silentScreenshotOcr:
guard let keyCombo = restoreScreenshotOCRShortcutKey() else { return nil }
guard let keyCombo = Defaults[.screenshotOCRShortcut] else { return nil }
return keyCombo
case .showMiniWindow:
guard let keyCombo = restoreShowMiniWindow() else { return nil }
guard let keyCombo = Defaults[.showMiniWindowShortcut] else { return nil }
return keyCombo
}
}
}

/// can't using keyEquivalent and EventModifiers in SwiftUI MenuItemView direct, because item
/// keyboardShortcut not support double modifier key but can use ⌥ as character
extension View {
public func keyboardShortcut(_ type: ShortcutType) -> some View {
guard let keyCombo = Shortcut.shared.shortcutKeyCombo(type) else { return AnyView(self) }
return AnyView(keyboardShortcut(fetchShortcutKeyEquivalent(keyCombo), modifiers: fetchShortcutKeyEventModifiers(keyCombo)))
struct KeyboardShortcut: ViewModifier {
init(type: ShortcutType) {
let key: Defaults.Key<KeyCombo?> = switch type {
case .inputTranslate:
.inputShortcut
case .snipTranslate:
.snipShortcut
case .selectTranslate:
.selectionShortcut
case .silentScreenshotOcr:
.screenshotOCRShortcut
case .showMiniWindow:
.showMiniWindowShortcut
}

_shortcut = .init(key)
}

@Default var shortcut: KeyCombo?

func body(content: Content) -> some View {
if let shortcut {
content
.keyboardShortcut(
fetchShortcutKeyEquivalent(shortcut),
modifiers: fetchShortcutKeyEventModifiers(shortcut)
)
} else {
content
}
}

private func fetchShortcutKeyEquivalent(_ keyCombo: KeyCombo) -> KeyEquivalent {
Expand Down Expand Up @@ -216,3 +214,12 @@ extension View {
return modifiers
}
}

/// can't using keyEquivalent and EventModifiers in SwiftUI MenuItemView direct, because item
/// keyboardShortcut not support double modifier key but can use ⌥ as character
public extension View {
@ViewBuilder
func keyboardShortcut(_ type: ShortcutType) -> some View {
modifier(KeyboardShortcut(type: type))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//
// KeyCombo+Defaults.Serializable.swift
// Easydict
//
// Created by 戴藏龙 on 2024/1/21.
// Copyright © 2024 izual. All rights reserved.
//

import Defaults
import Foundation
import Magnet

extension KeyCombo: Defaults.Serializable {
public static var bridge = ShortcutBridge()

public struct ShortcutBridge: Defaults.Bridge {
public func serialize(_ value: Magnet.KeyCombo??) -> Data? {
guard let value else { return nil }
return try? JSONEncoder().encode(value)
}

public func deserialize(_ object: Data?) -> Magnet.KeyCombo?? {
guard let data = object else { return nil }
return try? JSONDecoder().decode(KeyCombo.self, from: data) as Magnet.KeyCombo?
}

public typealias Value = KeyCombo?

public typealias Serializable = Data
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,43 +56,40 @@ extension GeneralKeyHolderWrapper {

func recordView(_: RecordView, didChangeKeyCombo keyCombo: KeyCombo?) {
storeKeyCombo(with: keyCombo)
guard let keyCombo else { return }
Shortcut.shared.bindingShortCut(keyCombo: keyCombo, type: type)
}

func restoreKeyCombo(_ recordView: RecordView) {
var data: Data
var keyCombo: KeyCombo?
switch type {
case .inputTranslate:
data = Defaults[.inputShortcutKey]
keyCombo = Defaults[.inputShortcut]
case .snipTranslate:
data = Defaults[.snipShortcutKey]
keyCombo = Defaults[.snipShortcut]
case .selectTranslate:
data = Defaults[.selectionShortcutKey]
keyCombo = Defaults[.selectionShortcut]
case .silentScreenshotOcr:
data = Defaults[.screenshotOCRShortcutKey]
keyCombo = Defaults[.screenshotOCRShortcut]
case .showMiniWindow:
data = Defaults[.showMiniWindowShortcutKey]
keyCombo = Defaults[.showMiniWindowShortcut]
}
guard let keyCombo = try? JSONDecoder().decode(KeyCombo.self, from: data) else { return }
recordView.keyCombo = keyCombo
Shortcut.shared.bindingShortCut(keyCombo: keyCombo, type: type)
}

// shortcut
func storeKeyCombo(with keyCombo: KeyCombo?) {
let data = try? JSONEncoder().encode(keyCombo)
switch type {
case .inputTranslate:
Defaults[.inputShortcutKey] = data ?? Data()
Defaults[.inputShortcut] = keyCombo
case .snipTranslate:
Defaults[.snipShortcutKey] = data ?? Data()
Defaults[.snipShortcut] = keyCombo
case .selectTranslate:
Defaults[.selectionShortcutKey] = data ?? Data()
Defaults[.selectionShortcut] = keyCombo
case .silentScreenshotOcr:
Defaults[.screenshotOCRShortcutKey] = data ?? Data()
Defaults[.screenshotOCRShortcut] = keyCombo
case .showMiniWindow:
Defaults[.showMiniWindowShortcutKey] = data ?? Data()
Defaults[.showMiniWindowShortcut] = keyCombo
}
}
}
Expand Down

0 comments on commit f693368

Please sign in to comment.