-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Expand file tree
/
Copy pathRateLimitNotifier.swift
More file actions
106 lines (89 loc) · 3.2 KB
/
RateLimitNotifier.swift
File metadata and controls
106 lines (89 loc) · 3.2 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
105
106
import AppKit
import Combine
import Foundation
import Logger
import NotificationCenterCoordinator
import UserNotifications
public struct UsageRateLimit: Hashable, Codable {
public var entitlement: Int
public var percentRemaining: Double
public var resetDate: String
}
public struct RateLimitWarningParams: Hashable, Codable {
public var type: String // "weekly" or "session"
public var rateLimit: UsageRateLimit
public var message: String
}
public protocol RateLimitNotifier {
func handleRateLimitWarning(_ params: RateLimitWarningParams)
}
public class RateLimitNotifierImpl: NSObject, RateLimitNotifier, ObservableObject {
public static let shared = RateLimitNotifierImpl()
@Published public var currentWarning: RateLimitWarningParams?
private static let categoryIdentifier = "rateLimitWarningCategory"
private static let learnMoreActionIdentifier = "rateLimitLearnMoreAction"
private static let learnMoreURL = URL(
string: "https://aka.ms/github-copilot-rate-limit-error"
)!
private var isCategoryRegistered = false
private override init() {
super.init()
}
private func registerCategoryIfNeeded() {
guard !isCategoryRegistered else { return }
isCategoryRegistered = true
let learnMoreAction = UNNotificationAction(
identifier: Self.learnMoreActionIdentifier,
title: "Learn more",
options: [.foreground]
)
let category = UNNotificationCategory(
identifier: Self.categoryIdentifier,
actions: [learnMoreAction],
intentIdentifiers: [],
options: []
)
NotificationCenterCoordinator.shared.register(
category: category,
handler: { response in
if response.actionIdentifier == Self.learnMoreActionIdentifier {
NSWorkspace.shared.open(Self.learnMoreURL)
}
},
for: Self.categoryIdentifier
)
}
public func handleRateLimitWarning(_ params: RateLimitWarningParams) {
DispatchQueue.main.async { [weak self] in
self?.currentWarning = params
}
Task { @MainActor in
await NotificationCenterCoordinator.shared.setupIfNeeded()
self.registerCategoryIfNeeded()
await sendAppleNotification(params)
}
}
public func dismissWarning() {
DispatchQueue.main.async { [weak self] in
self?.currentWarning = nil
}
}
@MainActor
private func sendAppleNotification(_ params: RateLimitWarningParams) async {
let content = UNMutableNotificationContent()
content.title = "GitHub Copilot for Xcode"
content.body = params.message
content.sound = .default
content.categoryIdentifier = Self.categoryIdentifier
let request = UNNotificationRequest(
identifier: "rateLimitWarning-\(UUID().uuidString)",
content: content,
trigger: nil
)
do {
try await UNUserNotificationCenter.current().add(request)
} catch {
Logger.gitHubCopilot.error("Failed to show rate limit notification: \(error)")
}
}
}