fix(workflows): pause carousel and video on hidden workflow pages#6913
Draft
facumenzella wants to merge 1 commit into
Draft
fix(workflows): pause carousel and video on hidden workflow pages#6913facumenzella wants to merge 1 commit into
facumenzella wants to merge 1 commit into
Conversation
Workflow keeps every visited step mounted off-screen (seenPages, #6889) so its state survives back-navigation. The downside MonikaMateska flagged on that PR: a hidden page's onDisappear never fires, so its carousel auto-advance timer keeps ticking and its video keeps playing at opacity 0, burning CPU/battery on a page the user can't see. Add an isPageActive flag to WorkflowPageTransitionContext (default true, so standalone paywalls are unaffected), set to true only for the current and outgoing pages. CarouselView and VideoComponentView read it and quiesce when inactive: the carousel stops/restarts its timer off the flag instead of onDisappear, and the video folds it into its existing playable state so a video in a carousel on a hidden page pauses for either reason. Behind -EnableWorkflowsEndpoint, internal-only. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.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.
Follow-up to #6889. Monika approved it but flagged a real downside: now that every visited workflow step stays mounted off-screen (so its state survives back-navigation), anything time-based on a hidden page keeps running invisibly at opacity 0. A hidden page's
onDisappearnever fires, so its carousel auto-advance timer keeps ticking and its video keeps playing, burning CPU/battery on a page the user can't see.This pauses that work while a page is off-screen.
What changed
WorkflowPageTransitionContextgets anisPageActiveflag (defaulttrue, so standalone paywalls are untouched). It'strueonly for the current and outgoing pages, computed from a newWorkflowPageTransitionState.isPageOnScreen(_:).CarouselViewreads the flag and drives its auto-advance timer off it: stop when the page goes off-screen, restart when the user comes back (theindexis preserved by@State, so it resumes where it was).onDisappearstill stops it for the non-workflow case.VideoComponentViewfolds the flag into its existingisActiveOrNeighborplayable check, so a video in a carousel on a hidden page pauses for either reason. When it becomes playable again the player is recreated and autoplays as before.The outgoing page keeps playing through the 0.25s slide and quiesces once the transition completes.
All behind
-EnableWorkflowsEndpoint, internal-only.Out of scope
Monika also mentioned animations. Declarative
repeatForever/TimelineViewanimations on hidden pages aren't gated here (opacity 0 doesn't stop them), and they don't run a timer/player so the cost is lower. Left as a follow-up so this PR stays focused on the two clear offenders.Verification
swift build --target RevenueCatUI: builds.swiftlinton the 6 changed files: 0 violations.swift test):isPageOnScreen(current/outgoing on-screen, hidden not) and the videoisPlayabletruth table pass; existingCarouselStateTests/VideoComponentViewTestsstill green.-EnableWorkflowsEndpoint, navigate forward then back on a step with an auto-advancing carousel / autoplay video) before merge.AI session context
Metadata
facu/workflow-pause-hidden-page-media(cut fromorigin/main@0b515353, the fix(workflows): preserve workflow page state across navigation #6889 merge)facumenzella)Goal
Act on the review feedback in #6889 (review) (MonikaMateska, APPROVED): hidden-but-mounted
seenPageskeep time-based components running at opacity 0, burning CPU/battery.First actionable instruction
"Check #6889#pullrequestreview-4427637013. Let's follow-up on that." Resolved to: implement a fix that pauses time-based work on hidden workflow pages.
Human decisions
repeatForever/TimelineView) explicitly out of scope as a follow-up.Agent contribution
seenPagesstay mounted, soonDisappear(where both Carousel and Video stop their work) never fires on navigation.isPageActivetoWorkflowPageTransitionContext(defaulttrue) +WorkflowPageTransitionState.isPageOnScreen(_:); wired inseenPageView.stopAutoPlay().isPlayable(isActiveOrNeighbor:isWorkflowPageActive:)helper.Files / symbols touched
RevenueCatUI/Modifiers/EnvironmentValues+Workflow.swift-WorkflowPageTransitionContext.isPageActive+ explicit init (the synthesized memberwise init drops a defaultedlet, hence the explicit init).RevenueCatUI/Templates/V2/WorkflowPaywallView.swift-WorkflowPageTransitionState.isPageOnScreen(_:)(where Page: Identifiable);seenPageViewpassesisPageActive.RevenueCatUI/Templates/V2/Components/Carousel/CarouselComponentView.swift-CarouselViewreadsworkflowRenderingContext, timer driven offisPageActive,stopAutoPlay().RevenueCatUI/Templates/V2/Components/Video/VideoComponentView.swift- readsworkflowRenderingContext,isPlayable(...)static,resolvePlayableState(), extraonChangeOf.Tests/RevenueCatUITests/PaywallsV2/WorkflowPaywallViewTests.swift-testOnlyCurrentAndOutgoingPagesAreOnScreen+IdentifiablePage; assertedisPageActivedefault in the identity test.Tests/RevenueCatUITests/PaywallsV2/VideoComponentViewTests.swift-testIsPlayableRequiresBothActiveCarouselPageAndActiveWorkflowPage.Key implementation decisions
carouselState.isActiveOrNeighborprecedent. Rejected: unmounting hidden pages (defeats the fix(workflows): preserve workflow page state across navigation #6889 state-preservation purpose).isPageActive = isPageOnScreen(current OR outgoing), so the outgoing page keeps playing through the slide. Rejected:= isCurrentonly (would pause the outgoing page mid-transition).isActiveOrNeighbor && isWorkflowPageActive) so it never overrides the carousel's own pausing.Validation
swift build --target RevenueCatUI: success.swiftlint(6 files): 0 violations.swift testtargeted: 3 new +CarouselStateTests(14) +VideoComponentViewTests(3) pass.Validation gaps
.onChangeOf(isPageActive)firing on the opacity-0 hidden subtree. Expected (the subtree stays live, which is what causes the original bug), but worth confirming on device.Review focus
.identity->isPageActive == true) byte-equivalent to the old video/carousel behavior?isPageActiveflip at the right moment (outgoing stays active untilcompleteTransition)?indexand the video recreate its player (playerRefreshToggle)?Out of scope
repeatForever/TimelineView) on hidden pages.