Skip to content

Commit 6a5284d

Browse files
committed
refactor: simplify TodoManager shortcut registration
1 parent 2c86f8c commit 6a5284d

2 files changed

Lines changed: 106 additions & 99 deletions

File tree

Rectangle/PrefsWindow/Config.swift

Lines changed: 30 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6,54 +6,55 @@ import MASShortcut
66
extension Defaults {
77
static func encoded() -> String? {
88
guard let version = Bundle.main.infoDictionary?["CFBundleVersion"] as? String else { return nil }
9-
9+
1010
var shortcuts = [String: Shortcut]()
1111
for action in WindowAction.active {
1212
if let masShortcut = ShortcutStore.shortcut(for: action) {
1313
shortcuts[action.name] = Shortcut(masShortcut: masShortcut)
1414
}
1515
}
1616
for defaultsKey in TodoManager.defaultsKeys {
17-
let fallback = defaultsKey == TodoManager.toggleDefaultsKey
18-
? MASShortcut(keyCode: kVK_ANSI_B, modifierFlags: [.control, .option])
19-
: MASShortcut(keyCode: kVK_ANSI_N, modifierFlags: [.control, .option])
20-
if let shortcut = ShortcutStore.shortcut(forKey: defaultsKey, fallback: fallback) {
21-
shortcuts[defaultsKey] = Shortcut(masShortcut: shortcut)
22-
}
17+
guard let masShortcut = ShortcutStore.shortcut(forKey: defaultsKey) else { continue }
18+
shortcuts[defaultsKey] = Shortcut(masShortcut: masShortcut)
2319
}
24-
20+
2521
var codableDefaults = [String: CodableDefault]()
2622
for exportableDefault in Defaults.array {
2723
codableDefaults[exportableDefault.key] = exportableDefault.toCodable()
2824
}
29-
25+
3026
let config = Config(bundleId: "com.knollsoft.Rectangle",
3127
version: version,
3228
shortcuts: shortcuts,
3329
defaults: codableDefaults)
34-
30+
3531
let encoder = JSONEncoder()
3632
encoder.outputFormatting = .prettyPrinted
3733
if #available(macOS 10.13, *) {
3834
encoder.outputFormatting.update(with: .sortedKeys)
3935
}
40-
return (try? encoder.encode(config)).flatMap { String(data: $0, encoding: .utf8) }
36+
if let encodedJson = try? encoder.encode(config) {
37+
if let jsonString = String(data: encodedJson, encoding: .utf8) {
38+
return jsonString
39+
}
40+
}
41+
return nil
4142
}
42-
43+
4344
static func convert(jsonString: String) -> Config? {
4445
guard let jsonData = jsonString.data(using: .utf8) else { return nil }
4546
let decoder = JSONDecoder()
4647
return try? decoder.decode(Config.self, from: jsonData)
4748
}
48-
49+
4950
static func load(fileUrl: URL) {
5051
// Size cap: legitimate configs are ~tens of KB; refuse anything that
5152
// looks abusive (defense against OOM via a giant config file).
5253
if let attrs = try? FileManager.default.attributesOfItem(atPath: fileUrl.path),
5354
let size = attrs[.size] as? NSNumber, size.intValue > 1_048_576 {
5455
return
5556
}
56-
57+
5758
guard let jsonString = try? String(contentsOf: fileUrl, encoding: .utf8),
5859
let config = convert(jsonString: jsonString) else { return }
5960

@@ -62,7 +63,7 @@ extension Defaults {
6263
availableDefault.load(from: codedDefault)
6364
}
6465
}
65-
66+
6667
for action in WindowAction.active {
6768
let importedShortcut = config.shortcuts[action.name] ?? action.aliasName.flatMap { config.shortcuts[$0] }
6869
if let shortcut = importedShortcut?.toMASSHortcut() {
@@ -74,19 +75,19 @@ extension Defaults {
7475
ShortcutStore.setShortcut(shortcut, forKey: defaultsKey)
7576
}
7677
}
77-
78+
7879
Notification.Name.configImported.post()
7980
Notification.Name.shortcutsChanged.post()
8081
}
81-
82+
8283
static func loadFromSupportDir() {
8384
if let rectangleSupportURL = getSupportDir()?
8485
.appendingPathComponent("Rectangle", isDirectory: true) {
85-
86+
8687
let configURL = rectangleSupportURL.appendingPathComponent("RectangleConfig.json")
87-
let fm = FileManager.default
88-
89-
if (try? configURL.checkResourceIsReachable()) == true {
88+
89+
let exists = try? configURL.checkResourceIsReachable()
90+
if exists == true {
9091
// Defense-in-depth: any process running as this user can drop
9192
// a RectangleConfig.json in Application Support and have it
9293
// silently applied on next launch, overwriting shortcuts and
@@ -95,8 +96,9 @@ extension Defaults {
9596
// We also refuse symlinks (could redirect reads elsewhere) and
9697
// any file with world-write permission (suggests tampering).
9798
let path = configURL.path
99+
let fm = FileManager.default
98100
var isSafe = true
99-
101+
100102
if let attrs = try? fm.attributesOfItem(atPath: path) {
101103
if (attrs[.type] as? FileAttributeType) == .typeSymbolicLink {
102104
isSafe = false
@@ -106,7 +108,7 @@ extension Defaults {
106108
isSafe = false
107109
}
108110
}
109-
111+
110112
guard isSafe else {
111113
AlertUtil.oneButtonAlert(
112114
question: "Refused to load RectangleConfig.json",
@@ -115,7 +117,7 @@ extension Defaults {
115117
try? fm.removeItem(at: configURL)
116118
return
117119
}
118-
120+
119121
let response = AlertUtil.twoButtonAlert(
120122
question: "Apply Rectangle configuration?",
121123
text: "A configuration file was found at \(path). Applying it will overwrite your current Rectangle shortcuts and preferences. Apply now?",
@@ -126,11 +128,11 @@ extension Defaults {
126128
try? fm.removeItem(at: configURL)
127129
return
128130
}
129-
131+
130132
load(fileUrl: configURL)
131133
do {
132134
let newFilename = "RectangleConfig\(timestamp()).json"
133-
135+
134136
try fm.moveItem(atPath: configURL.path, toPath: rectangleSupportURL.appendingPathComponent(newFilename).path)
135137
} catch {
136138
do {
@@ -142,11 +144,11 @@ extension Defaults {
142144
}
143145
}
144146
}
145-
147+
146148
private static func getSupportDir() -> URL? {
147149
FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask).first
148150
}
149-
151+
150152
private static func timestamp() -> String {
151153
let date = Date()
152154
let formatter = DateFormatter()

0 commit comments

Comments
 (0)