fix: skip live claimable updates when tab is backgrounded - #1379
Open
omoh5 wants to merge 3 commits into
Open
Conversation
Replace npm install with npm ci in backend/Dockerfile (both builder and runner stages), render.yaml, and vercel.json to ensure deterministic, lockfile-pinned dependency installs in production builds. This eliminates the risk of dependency drift between CI-tested and deployed versions. Closes LabsCrypt#1256 🤖 Generated with Codebuff Co-Authored-By: Codebuff <noreply@codebuff.com>
The setInterval(updateClaimable, 1000) in stream-details-content.tsx was running every second regardless of whether the tab was visible, wasting CPU/battery on backgrounded tabs. This mirrors the approach already used by the useStreamingAmount hook (requestAnimationFrame + document.hidden guard) but keeps the bigint arithmetic intact. - Extract computeClaimable() so the value can be recalculated on demand - Guard the interval callback with document.hidden check - Add visibilitychange listener to resync immediately when tab returns to foreground (matching useStreamingAmount's resync behavior) - Add test verifying no state updates occur while document.hidden is true Closes LabsCrypt#1242 🤖 Generated with Codebuff Co-Authored-By: Codebuff <noreply@codebuff.com>
The backend Dockerfile uses npm ci (from PR LabsCrypt#1256) which requires a package-lock.json. Since this is an npm workspaces monorepo, the lockfile lived only at the root and wasn't available in the backend/ build context. Generated a standalone backend/package-lock.json so npm ci can resolve exact dependency versions in the Docker build. Also added a root .dockerignore for future-proofing. 🤖 Generated with Codebuff Co-Authored-By: Codebuff <noreply@codebuff.com>
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.
Summary
Stops the live "claimable amount" ticker from running every second while the browser tab is backgrounded, reducing unnecessary CPU/battery usage on a page users commonly leave open to "watch" a stream.
Problem
stream-details-content.tsx:155-181uses a plainsetInterval(updateClaimable, 1000)with nodocument.hiddenguard. This means the 1-second update loop runs continuously even when the tab is in the background — wasting CPU cycles and draining battery on mobile/laptop devices.The codebase already has a more efficient pattern in
useStreamingAmount(hooks/useStreamingAmount.ts:66-104), which usesrequestAnimationFrame+ explicitdocument.hiddenchecks. However, that hook usesnumbertypes while the stream details component usesBigIntarithmetic throughout (required byformatAmount), so a direct swap isn't possible without a broader refactor.Solution
Added the same visibility guard pattern from
useStreamingAmountdirectly to the inline interval:Extracted
computeClaimable()— a pure function that returns the current claimablebigintwithout side effects, so it can be called on demand from both the interval and the visibility change handler.Guarded
updateClaimable()withif (document.hidden) return;— the interval still fires every second for consistent timing, but skips the state update when the tab is backgrounded.Added
visibilitychangelistener — when the tab returns to the foreground,computeClaimable()is called immediately to resync the displayed value (matchinguseStreamingAmount's resync behavior), rather than waiting up to 1 second for the next interval tick.Proper cleanup — both
clearIntervalandremoveEventListenerare returned from the effect.Files Changed
frontend/src/app/streams/[id]/stream-details-content.tsxcomputeClaimable(), adddocument.hiddenguard, addvisibilitychangelistenerfrontend/src/app/streams/[id]/__tests__/stream-details-content.test.tsxTest
Added a test in the existing
stream-details-content.test.tsxtest file that:setIntervalcallbackdocument.hidden = true(simulating background tab)useStreamingAmount's approachWhy not replace with
useStreamingAmount?The
useStreamingAmounthook acceptsnumberparameters and returns anumber, butstream-details-content.tsxusesBigIntarithmetic (required byformatAmount(raw: bigint, decimals: number)). A full migration would require changing the type ofliveClaimablefrombiginttonumber, addingBigInt()conversion at everyformatAmountcall site, and auditing for precision loss on large token amounts. The visibility guard approach is the minimal, targeted fix the audit calls for.Closes #1242
🤖 Generated with Codebuff
Co-Authored-By: Codebuff noreply@codebuff.com