Withdraw a chat's push notices by thread (collapse-id ready) #1

Merged
fmodf merged 1 commit from fix/push-notification-withdraw into master 2026-10-19 17:03:27 +00:00
Owner

Push notices for a chat are now withdrawn by their thread, not by their identifier. This goes with the server-side push changes: anotherim-server feat/push-throttle and apushd feat/push-coalesce.

The bug. When a chat's read point moved, ChatNotificationWithdrawal removed delivered notices whose identifier started with <account>|<chat>. iOS names a pushed notification itself, either a random id or the push's apns-collapse-id, and the notification service extension cannot change it. So nothing was ever withdrawn.

The fix.

  • One shared helper. The new AnotherIMShared/AppPushThread.swift builds the thread id <account>|<chat>, lowercased. A room's private message joins its room's thread, as before.
  • Both sides use it. The extension sets it as threadIdentifier, and the withdrawal matches delivered notices by threadIdentifier.
  • Docs. The extension's header comment and the README's Push section are updated.

What the server changes mean for iOS.

  • Notices replace each other. A message push now carries an opaque per-chat tag as apns-collapse-id, so a chat's newer notice replaces the older one.
  • Bursts are throttled. The server sends a burst in one chat as one push, then one more after 20 s with the latest count. The extension already shows the summary's count as-is, so no change is needed there.
  • PushKit gets calls only. apushd now drops non-call pushes to VoIP modules, so registrations from older builds without apushCalls: only no longer receive messages over PushKit. Current master already registers correctly.

Tests. AnotherIMTests/PushThreadTests.swift checks the thread's form, and that only the chat's own thread is withdrawn. A longer domain or another account's thread is left alone.

Not compiled with Xcode. The pure parts, AppPushThread and the matching function, compile with swiftc 6.0 in Swift 6 mode and pass the same checks. swiftlint with the repo config reports nothing. Please build and run the tests in Xcode before merging.

🤖 Generated with Claude Code

Push notices for a chat are now withdrawn by their **thread**, not by their identifier. This goes with the server-side push changes: anotherim-server `feat/push-throttle` and apushd `feat/push-coalesce`. **The bug.** When a chat's read point moved, `ChatNotificationWithdrawal` removed delivered notices whose identifier started with `<account>|<chat>`. iOS names a pushed notification itself, either a random id or the push's `apns-collapse-id`, and the notification service extension cannot change it. So nothing was ever withdrawn. **The fix.** - **One shared helper.** The new `AnotherIMShared/AppPushThread.swift` builds the thread id `<account>|<chat>`, lowercased. A room's private message joins its room's thread, as before. - **Both sides use it.** The extension sets it as `threadIdentifier`, and the withdrawal matches delivered notices by `threadIdentifier`. - **Docs.** The extension's header comment and the README's Push section are updated. **What the server changes mean for iOS.** - **Notices replace each other.** A message push now carries an opaque per-chat tag as `apns-collapse-id`, so a chat's newer notice replaces the older one. - **Bursts are throttled.** The server sends a burst in one chat as one push, then one more after 20 s with the latest count. The extension already shows the summary's count as-is, so no change is needed there. - **PushKit gets calls only.** apushd now drops non-call pushes to VoIP modules, so registrations from older builds without `apushCalls: only` no longer receive messages over PushKit. Current master already registers correctly. **Tests.** `AnotherIMTests/PushThreadTests.swift` checks the thread's form, and that only the chat's own thread is withdrawn. A longer domain or another account's thread is left alone. **Not compiled with Xcode.** The pure parts, `AppPushThread` and the matching function, compile with swiftc 6.0 in Swift 6 mode and pass the same checks. swiftlint with the repo config reports nothing. Please build and run the tests in Xcode before merging. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
A chat's pushed notices are withdrawn by their thread, not by their identifier, and the thread is made in one place. The chat list's ChatNotificationWithdrawal removed delivered notifications whose identifier started with <account>|<chat>, but iOS names a pushed notification itself, a random id or the push's apns-collapse-id, and the notification service extension cannot change it, so nothing was ever withdrawn when a chat's read point moved; the extension already set the thread identifier to <account>|<chat>. With anotherim-server's feat/push-throttle and apushd's feat/push-coalesce a message push carries the chat's opaque tag as apns-collapse-id, so the identifier is now that tag, a chat's newer notice replaces the older one, and its count is the chat's latest rather than a sum, which the extension already shows. The new AnotherIMShared/AppPushThread.swift makes <account>|<chat> (lowercased, a room's private message joining its room, as the extension's own bareJID did, which moves there); the extension sets it and ChatNotificationWithdrawal matches the delivered notices' threadIdentifier against it, the match in identifiers(in:of:) so a test can reach it. The extension's header and the README's Push section say so. AnotherIMTests/PushThreadTests.swift: the thread's form, and that only the chat's own thread is withdrawn (not a longer domain, not another account's). Not compiled with Xcode, which this machine has not: AppPushThread and the matching code compiled with swiftc 6.0 (Swift 6 mode) in the swift:6.0 image and passed the same checks there, and swiftlint with the repo's .swiftlint.yml reports nothing on the changed files. e17bdd260b
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
fmodf merged commit 94c347e5d3 into master 2026-10-19 17:03:27 +00:00
fmodf deleted branch fix/push-notification-withdraw 2026-10-19 17:03:27 +00:00
Sign in to join this conversation.
No reviewers
No labels
done
fixed
returned
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
another-im/anotherim-swift!1
No description provided.