iOS: the icon's count follows the page's (#421)
Reported: the unread count on the icon only changed when the app was
opened. Two reasons:
- Items read in the page never reached it, since only the player's own
mark-read refreshed the badge.
- The background refresh that should bring new items runs when iOS
chooses, which for this app has been rarely.
The page now sends All Subscriptions' count ({t:"unread", n}) each time
its list is drawn with a new one, so reading, and new items arriving
over the event stream while the app is open, set it at once. While an
episode plays the app is awake with the screen locked, so the player's
tick also re-checks every quarter of an hour.
With the app closed and nothing playing, the count still waits on iOS's
refresh. Push (#433) is what makes that exact.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -38,6 +38,23 @@ enum Badge {
|
||||
UNUserNotificationCenter.current().requestAuthorization(options: [.badge]) { _, _ in }
|
||||
}
|
||||
|
||||
/// The page's own count, sent as its list changes (#421).
|
||||
@MainActor static func set(_ n: Int) {
|
||||
lastSet = Date()
|
||||
Task { try? await UNUserNotificationCenter.current().setBadgeCount(max(0, n)) }
|
||||
}
|
||||
|
||||
/// When the icon was last set from a count, by either way.
|
||||
@MainActor private static var lastSet = Date.distantPast
|
||||
|
||||
/// While an episode plays with the screen locked the app is awake, unlike the page: so new
|
||||
/// items reach the icon every quarter of an hour, which background refresh does not promise.
|
||||
@MainActor static func refreshIfStale() {
|
||||
guard Date().timeIntervalSince(lastSet) > 15 * 60 else { return }
|
||||
lastSet = Date()
|
||||
Task { await refresh() }
|
||||
}
|
||||
|
||||
/// Asks ipx and sets the icon. Left as it is when ipx cannot be reached or does not answer
|
||||
/// with a feed list: an old number is better than a wrong one.
|
||||
@discardableResult
|
||||
@@ -52,7 +69,7 @@ enum Badge {
|
||||
guard let (data, resp) = try? await URLSession(configuration: cfg).data(for: req),
|
||||
(resp as? HTTPURLResponse)?.statusCode == 200,
|
||||
let n = unread(inAll: data) else { return false }
|
||||
try? await UNUserNotificationCenter.current().setBadgeCount(n)
|
||||
await MainActor.run { set(n) }
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user