feat(mobile): beacon task presence to suppress cross-device push fanout#2338
Draft
dmarticus wants to merge 1 commit into
Draft
feat(mobile): beacon task presence to suppress cross-device push fanout#2338dmarticus wants to merge 1 commit into
dmarticus wants to merge 1 commit into
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
After posthog/posthog#59313 (per-device presence beacon for push fanout), the server suppresses pushes about a task to any device with an active presence row for it. This PR is the mobile client half — it actually beacons.
Without this, the server-side filter has nothing to filter on and mobile keeps ringing for activity the user is already watching on another device.
Changes
registerPushToken(src/lib/api.ts) now parses theid(UserPushToken.idUUID) from the registration response. Defensive parse so older server versions don't crash.pushTokenStorepersists that UUID in SecureStore asdeviceIdalongside the existing token. Re-upload gate triggers whendeviceIdis missing, so existing users pull it on next foregrounding without re-registering.postTaskPresence/deleteTaskPresenceinsrc/features/tasks/api.tsagainstPOST/DELETE /api/projects/{team_id}/tasks/{task_id}/presence/with{ device_id }.useTaskPresence(taskId)hook insrc/features/tasks/hooks/useTaskPresence.tshandles the lifecycle:AppState === "active".pushTokenStore.hydrate()so cold-start mounts don't miss the device_id.app/task/[id].tsxcallsuseTaskPresence(taskId)once.Out of scope / not done / needs decision
Desktop (apps/code) beacon
Desktop uses Electron's native
NotificationAPI (seeapps/code/src/main/platform-adapters/electron-notifier.ts) — it never registers a push token with the server. So the server-side presence model, which keys onUserPushToken.id, has no row to write for a desktop session.This means the original "I'm on my Mac, stop ringing my phone" complaint isn't fully fixed yet. Options to discuss:
device_idon presence rows (decouple fromUserPushToken). Desktop generates a stable UUID once, persists it in Electron's userData dir, and beacons normally. Cleanest model — presence shouldn't be a child of push token; one of those concepts is broader.platform: \"electron\") that the server flags as presence-only. Smaller server diff than A, hackier shape.awaitingPingarming from external user messages, 30s dedup,awaiting_user_input-only per-turn pings) already cover most desktop-driven activity. The leftover case is mobile-initiated work that completes while the user has moved to desktop.My read is A is the right fix, but it's a server PR. Punting until we decide.
Inbox / new-task screens
/task(new task composer) isn't viewing a task → no presence to claim.