Skip to content

Commit 90732f8

Browse files
committed
Fix 5 issues: logs, Set.insert, temp files, badge, last-resort reconnect
- Replace debug print() with Log.info/error() in NotificationManager - Fix Set.insert bug in registerCategoryFromMessage (filter before insert) - Delete temp PNG files after creating SF Symbol notification attachment - Clear badge count when user interacts with a notification - Replace permanent failure after max reconnect attempts with 5-min retry loop
1 parent a34e63e commit 90732f8

File tree

2 files changed

+23
-53
lines changed

2 files changed

+23
-53
lines changed

Sources/NotificationManager.swift

Lines changed: 16 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@ final class NotificationManager: NSObject, @unchecked Sendable {
2424
/// Clears all notification categories to remove stale actions
2525
func clearCategories() {
2626
center.setNotificationCategories([])
27-
print("Cleared notification categories")
28-
fflush(stdout)
27+
Log.info("Cleared notification categories")
2928
}
3029

3130
/// Sets the script runner - accepts protocol for DI/testing
@@ -98,18 +97,11 @@ final class NotificationManager: NSObject, @unchecked Sendable {
9897

9998
/// Displays a notification based on an ntfy message and topic configuration
10099
func showNotification(for message: NtfyMessage, topicConfig: TopicConfig?) {
101-
print("showNotification called for topic: \(message.topic)")
102-
fflush(stdout)
103-
104100
guard let topicConfig = topicConfig else {
105-
print("No topicConfig, using basic notification")
106-
fflush(stdout)
107101
showBasicNotification(for: message)
108102
return
109103
}
110104

111-
print("Using topicConfig for notification")
112-
113105
// Skip notification if silent mode is enabled
114106
if topicConfig.silent == true {
115107
print("Silent notification for topic \(message.topic) - skipping display")
@@ -137,16 +129,8 @@ final class NotificationManager: NSObject, @unchecked Sendable {
137129
}
138130
}
139131

140-
// Add icon attachment
141-
print("Creating icon attachment for topic config: iconPath=\(topicConfig.iconPath ?? "nil"), iconSymbol=\(topicConfig.iconSymbol ?? "nil")")
142-
fflush(stdout)
143132
if let attachment = createIconAttachment(from: topicConfig) {
144-
print("Attachment created, adding to notification")
145-
fflush(stdout)
146133
content.attachments = [attachment]
147-
} else {
148-
print("No attachment created")
149-
fflush(stdout)
150134
}
151135

152136
// Store message body and actions for handling
@@ -198,8 +182,7 @@ final class NotificationManager: NSObject, @unchecked Sendable {
198182
let categoryId = "topic-\(message.topic)-actions"
199183
registerCategory(categoryId: categoryId, actions: actions)
200184
content.categoryIdentifier = categoryId
201-
print("Using \(actions.count) actions from config (overriding message actions)")
202-
fflush(stdout)
185+
Log.info("Using \(actions.count) actions from config for topic \(message.topic)")
203186
} else if let messageActions = message.actions, !messageActions.isEmpty {
204187
// No config actions - use message actions
205188
let categoryId = "msg-\(message.id)-actions"
@@ -236,8 +219,7 @@ final class NotificationManager: NSObject, @unchecked Sendable {
236219
userInfo["actionUrls"] = actionUrls
237220
userInfo["actionTypes"] = actionTypes
238221
userInfo["actionDetailsJson"] = actionDetailsJson
239-
print("Registered \(messageActions.count) actions from message")
240-
fflush(stdout)
222+
Log.info("Using \(messageActions.count) actions from message for topic \(message.topic)")
241223
}
242224

243225
content.userInfo = userInfo
@@ -246,15 +228,10 @@ final class NotificationManager: NSObject, @unchecked Sendable {
246228
let identifier = UUID().uuidString
247229
let request = UNNotificationRequest(identifier: identifier, content: content, trigger: nil)
248230

249-
print("Adding notification to center...")
250-
fflush(stdout)
251231
center.add(request) { error in
252232
if let error = error {
253-
print("Failed to show notification: \(error)")
254-
} else {
255-
print("✅ Notification added successfully")
233+
Log.error("Failed to show notification: \(error)")
256234
}
257-
fflush(stdout)
258235
}
259236
}
260237

@@ -289,20 +266,12 @@ final class NotificationManager: NSObject, @unchecked Sendable {
289266

290267
// Try local file path
291268
if let iconPath = topicConfig.iconPath {
292-
print("Trying icon path: \(iconPath)")
293-
fflush(stdout)
294269
let url = URL(fileURLWithPath: iconPath)
295270
if FileManager.default.fileExists(atPath: iconPath) {
296-
print("Icon file exists")
297-
fflush(stdout)
298271
do {
299-
let attachment = try UNNotificationAttachment(identifier: UUID().uuidString, url: url, options: nil)
300-
print("Icon attachment created successfully")
301-
fflush(stdout)
302-
return attachment
272+
return try UNNotificationAttachment(identifier: UUID().uuidString, url: url, options: nil)
303273
} catch {
304-
print("Failed to create attachment: \(error)")
305-
fflush(stdout)
274+
Log.error("Failed to create icon attachment from path \(iconPath): \(error)")
306275
}
307276
}
308277
}
@@ -331,9 +300,12 @@ final class NotificationManager: NSObject, @unchecked Sendable {
331300

332301
do {
333302
try pngData.write(to: fileURL)
334-
return try UNNotificationAttachment(identifier: UUID().uuidString, url: fileURL, options: nil)
303+
let attachment = try UNNotificationAttachment(identifier: UUID().uuidString, url: fileURL, options: nil)
304+
try? FileManager.default.removeItem(at: fileURL)
305+
return attachment
335306
} catch {
336-
print("Failed to create attachment: \(error)")
307+
Log.error("Failed to write SF Symbol attachment: \(error)")
308+
try? FileManager.default.removeItem(at: fileURL)
337309
return nil
338310
}
339311
}
@@ -382,7 +354,7 @@ final class NotificationManager: NSObject, @unchecked Sendable {
382354
)
383355

384356
center.getNotificationCategories { existingCategories in
385-
var categories = existingCategories
357+
var categories = existingCategories.filter { $0.identifier != categoryId }
386358
categories.insert(category)
387359
self.center.setNotificationCategories(categories)
388360
}
@@ -458,9 +430,7 @@ final class NotificationManager: NSObject, @unchecked Sendable {
458430

459431
center.add(request) { error in
460432
if let error = error {
461-
print("Failed to show test notification: \(error)")
462-
} else {
463-
print("Test notification sent successfully")
433+
Log.error("Failed to show test notification: \(error)")
464434
}
465435
}
466436
}
@@ -491,6 +461,9 @@ extension NotificationManager: UNUserNotificationCenterDelegate {
491461
handleActionResponse(response, messageBody: messageBody, topic: topic)
492462
}
493463

464+
// Clear badge when user interacts with a notification
465+
center.setBadgeCount(0) { _ in }
466+
494467
completionHandler()
495468
}
496469

@@ -505,8 +478,6 @@ extension NotificationManager: UNUserNotificationCenterDelegate {
505478
// If custom URL, use it directly; otherwise append topic to server URL
506479
let webUrlString = isCustomClickUrl ? serverUrl : "\(serverUrl)/\(topic)"
507480
if let url = URL(string: webUrlString) {
508-
print("Opening notification in web: \(webUrlString)")
509-
fflush(stdout)
510481
openUrlSecurely(url, forTopic: topic)
511482
}
512483
}

Sources/NtfyClient.swift

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -264,14 +264,13 @@ final class NtfyClient: NSObject, @unchecked Sendable {
264264
}
265265
}
266266
} else {
267-
Log.error("Max reconnection attempts reached. Please restart the service.")
268-
let error = NSError(
269-
domain: "NtfyClient",
270-
code: -1,
271-
userInfo: [NSLocalizedDescriptionKey: "Max reconnection attempts reached"]
272-
)
273-
callDelegate { delegate in
274-
delegate.ntfyClient(self, didEncounterError: error)
267+
// Max attempts reached — schedule a last-resort retry every 5 minutes indefinitely
268+
Log.error("Max reconnection attempts reached. Retrying every 5 minutes...")
269+
reconnectAttempts = 0 // Reset so next success resets state correctly
270+
DispatchQueue.main.async { [weak self] in
271+
self?.reconnectTimer = Timer.scheduledTimer(withTimeInterval: 300.0, repeats: false) { [weak self] _ in
272+
self?.connect()
273+
}
275274
}
276275
}
277276
}

0 commit comments

Comments
 (0)