-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Expand file tree
/
Copy pathFontScaleManager.swift
More file actions
104 lines (84 loc) · 3.23 KB
/
FontScaleManager.swift
File metadata and controls
104 lines (84 loc) · 3.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import SwiftUI
import Combine
extension Notification.Name {
static let fontScaleDidChange = Notification
.Name("com.github.CopilotForXcode.FontScaleDidChange")
}
@MainActor
public class FontScaleManager: ObservableObject {
@AppStorage(\.fontScale) private var fontScale {
didSet {
// Only post notification if this change originated locally
postNotificationIfNeeded()
}
}
public static let shared: FontScaleManager = .init()
public static let maxScale: Double = 2.0
public static let minScale: Double = 0.8
public static let scaleStep: Double = 0.1
public static let defaultScale: Double = 1.0
private let processIdentifier = UUID().uuidString
private var lastReceivedNotificationId: String?
private init() {
// Listen for font scale changes from other processes
DistributedNotificationCenter.default().addObserver(
self,
selector: #selector(handleFontScaleChanged(_:)),
name: .fontScaleDidChange,
object: nil
)
}
deinit {
DistributedNotificationCenter.default().removeObserver(self)
}
private func postNotificationIfNeeded() {
// Don't post notification if we're processing an external notification
guard lastReceivedNotificationId == nil else { return }
let notificationId = UUID().uuidString
DistributedNotificationCenter.default().postNotificationName(
.fontScaleDidChange,
object: nil,
userInfo: [
"fontScale": fontScale,
"sourceProcess": processIdentifier,
"notificationId": notificationId
],
deliverImmediately: true
)
}
@objc private func handleFontScaleChanged(_ notification: Notification) {
guard let userInfo = notification.userInfo,
let scale = userInfo["fontScale"] as? Double,
let sourceProcess = userInfo["sourceProcess"] as? String,
let notificationId = userInfo["notificationId"] as? String else {
return
}
// Ignore notifications from this process
guard sourceProcess != processIdentifier else { return }
// Ignore duplicate notifications
guard notificationId != lastReceivedNotificationId else { return }
// Only update if the value actually changed (with epsilon for floating-point)
guard abs(fontScale - scale) > 0.001 else { return }
lastReceivedNotificationId = notificationId
fontScale = scale
lastReceivedNotificationId = nil
}
public func increaseFontScale() {
fontScale = min(fontScale + Self.scaleStep, Self.maxScale)
}
public func decreaseFontScale() {
fontScale = max(fontScale - Self.scaleStep, Self.minScale)
}
public func setFontScale(_ scale: Double) {
guard scale <= Self.maxScale && scale >= Self.minScale else {
return
}
fontScale = scale
}
public func resetFontScale() {
fontScale = Self.defaultScale
}
public var currentScale: Double {
fontScale
}
}