Wire viewer-count presence heartbeat/leave into the player - #170
Open
dhinesh-kumar-m wants to merge 1 commit into
Open
Wire viewer-count presence heartbeat/leave into the player#170dhinesh-kumar-m wants to merge 1 commit into
dhinesh-kumar-m wants to merge 1 commit into
Conversation
Kept entirely internal to the player rather than exposed as new public API an app has to call: TPStreamPlayer starts the heartbeat loop when handlePlaybackStatusChange observes .playing and stops it (sending a best-effort leave) on .paused, playerDidFinishPlaying, and deinit — the same signal last-watched-position tracking already uses. PresenceHeartbeatManager mirrors the web presence-client's and Android SDK's loop (jittered first beat, server-driven cadence via next_heartbeat_in, Retry-After handling) so all three behave identically to the server. Resends the same persisted device id (PresenceViewerIdStore, Keychain-backed) on every heartbeat/leave call, matching the device-binding requirement flagged by senior review. On a 401 it calls back through the new TPStreamPlayerViewControllerDelegate.presenceTokenExpired(forVideo:completion:) rather than retrying the same token. Unlike Android, this SDK had no existing onAccessTokenExpired-shaped callback to mirror — there's no access-token-refresh mechanism on iOS at all yet — so this establishes the pattern rather than reusing one, matching the same "notify, then hand back a fresh value via callback" shape the todo asked for. Optional (default no-op via a protocol extension, matching didTapReplay's existing pattern): presence is still rollout-gated to a handful of organizations, and a required override would break every existing integrator for a feature almost none of them have enabled. The presence token itself travels through the same asset fetch that already returns playback URLs, nested under live_stream.presence in the API response, gated behind a new viewer_id query param BaseAPI.getAsset now sends via PresenceViewerIdStore whenever supportsPresence is true — without it the server mints a fresh anonymous id per request and the token could never pass device binding at all. StreamsAPI (TPStreams) only: the legacy TestpressAPI provider has no presence support to bind to. Scheduling and the URL session are both injected (PresenceScheduler, URLSession) so PresenceHeartbeatManager can be unit tested against MockURLProtocol without hitting the network, matching the existing plain XCTest setup this package already uses (no Quick/Nimble).
This was referenced Aug 18, 2026
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.
Full description in the branch commit message. Test plan: presence test suite added (MockURLProtocol-based), could not run swift test in this environment (no Xcode toolchain). Depends on testpress/streams#2507. Companion PRs: testpress/TPStreamsAndroidPlayer, testpress/flutter-player-sdk, testpress/react-native-tpstreams.