Feat: Onboarding - #3045
Merged
Merged
Conversation
Introduces a tri-state AnalyticsConsent enum (NOT_DECIDED, GRANTED, DENIED) to the SettingsDataStore for controlling product analytics consent. Includes setAnalyticsConsent and observeAnalyticsConsent methods with full test coverage.
Adds ConsentAwareEventTrackingClient which wraps FirebaseEventTrackingClient: NOT_DECIDED buffers up to 200 events in-memory, GRANTED flushes them (stamping buffered_at_epoch_ms) and forwards live, DENIED drops all. Identity calls (setUserId, setUserProperty) and setCollectionEnabled pass through unconditionally. Datadog is intentionally untouched. Removes @ContributesBinding from FirebaseEventTrackingClient and supplies the EventTrackingClient binding via a @ContributesTo @provides interface to avoid a self-loop in the DI graph.
Extends SettingsUiState and SettingsEvent with analytics consent, wires observeAnalyticsConsent/setAnalyticsConsent through the presenter, and adds a Product analytics HedvigBigCard row after the email subscription block. Also updates FakeSettingsDataStore to implement the new interface methods.
DataStore-backed store that remembers per member id whether onboarding was shown. Set when the member completes or dismisses the flow, ensuring onboarding never appears again for that member on this device.
OnboardingSessionStore caches fetched data plus the computed step path per-Activity (ActivityRetainedScope), refreshing data without reshuffling the path mid-flow. CompleteOnboardingUseCase marks the seen flag via OnboardingSeenStore for the logged-in member. OnboardingNavigator owns forward/exit movement: continueFrom pushes the next step key, falls back to exitOnboarding when the session is missing or the last step is done. Shared FakeOnboardingRepository and testOnboardingData test fixture added for later presenter tests.
Remove @serializable from NonOnboardingKey in OnboardingNavigatorTest so the navigation-keys KSP processor no longer picks it up and generates a @ContributesTo(AppScope::class) SerializersModule contributor for a test-only sentinel type. Tightened visibility to private since no generated cross-file reference exists without the annotation.
Implements the welcome screen (Task 10): OnboardingWelcomeViewModel, OnboardingWelcomePresenter, OnboardingWelcomeUiState/Event, and OnboardingWelcomeDestination. Adds testOptions.unitTests.isReturnDefaultValues so molecule presenter tests can run without Robolectric.
The two awaitItem() comments were swapped: the first consumed the UpdatePhoneNumber state change (not isSubmitting=true), the second consumed the isSubmitting=true state (not a navigation emission). Correct both comments so the test reads what it actually asserts.
When consent is DENIED, the wrapper now forces setCollectionEnabled(false) on the Firebase SDK (suppressing automatic events too), not only our custom-tracked events. Collection re-enables on GRANTED, subject to the demo-mode gate, by ANDing the demo flag with the consent state.
Remove the persisted connectedAnimationPlayed flag (and its event/state) so the connected check is derived purely from the live payinStatus; moving forward and back no longer carries any connection-adjacent state, it just reflects pending/active or not. Add a 'Do this later' skip on the not-yet-connected state so the payment step is always optional.
Seed the check as shown when in inspection mode, so the pending and active preview states render the connected graphic instead of looking like the not-connected one.
Remove the unused imports the ViewModel/Destination split left behind (ktlint no longer removes unused imports, so the full copied import blocks lingered), and the stale animation imports in the payment symbol. Unify the theme step's preview with the other screens (a UiState provider covering loading/error/content, non-null progressAnimation) and reword two comments that referenced the design process or a rejected alternative.
The chip-id completion used the presence of ChipIdKey to decide between popping back and going home. When a single contract is missing an ID the select screen auto-advances and pops ChipIdKey, so completion fell through to goHome and dropped the user on the Home tab. This broke the onboarding pet-ID step (return to the step) and the Insurances contract-detail entry (return to the contract) for the common single-pet case. Pop the flow's own entries so whatever launched it shows through, and keep goHome only when the flow is the stack root (a lone deep link with no in-app caller). Cover the branches with PopChipIdFlowOnSuccessTest.
Follow the Figma connect-payment design, which shows just [Connect payment] until a method is connected. Removing the skip outright would strand a member who opens the connect flow and returns without connecting, so reveal the [Do this later] secondary only once they have entered the connect flow at least once and come back still not connected. Connection is still derived from live payinStatus, never from the button press. Also document why terminate-insurance's onDone can pop plainly: the flow is collapsed to a single TerminationSuccessKey on success, so one pop returns to the caller.
The pet-ID and co-insured steps kept completed rows visible by remembering which contracts the step owns in the presenter. But MoleculeViewModel shares with WhileSubscribed(5s), so a >5s trip into the chip-id/edit flow disposes the presenter and re-pins from the now-empty missing-list, making the completed row vanish. Move the pin into OnboardingSession (held by the ActivityRetainedScope session store, captured at first load and preserved across refreshData) so completion keeps the row with its checkmark.
Emit a DEBUG line (tag AnalyticsConsentDebug) whenever consent is applied, so the consent gate can be verified with adb logcat instead of Firebase DebugView.
Long subtitles (common in English) wrapped to a second line, giving the bundle-discount cross-sell rows varying heights and uneven pillow spacing. Make the subtitle a single marquee line so it scrolls instead. Titles are left free to wrap. Inter-row spacing is unchanged.
Replace basicMarquee with a custom AutoScrollingText that scrolls a too-wide subtitle to its end, pauses, then scrolls back to the start and pauses again, looping. basicMarquee only loops one direction with an arbitrary gap before the text re-enters from the right; this reveals the whole line and returns, matching the iOS behaviour. Scroll duration scales with the hidden overflow so the speed stays constant. Subtitles that already fit do not move.
Repackage the ping-pong auto-scroll as Modifier.autoScrollingMarquee(), a LayoutModifierNode that measures its content unbounded, reports the container width, clips, and animates the placement offset. Applies directly to HedvigText like basicMarquee, dropping the wrapping Box and the style/color pass-through.
Promote Modifier.autoScrollingMarquee() from feature-onboarding to the shared design-system-hedvig commonMain so any surface can reuse it. Now public and KMP-common (available to iOS too).
Lay the cross-sell rows out with a small custom Layout that measures every row once and sizes them all to the tallest, centring each row's content in its cell. A single two-line title lifts every row to the same height, so the pillows and See price buttons keep an even vertical rhythm instead of drifting with each row's text. One measure pass, so heights are uniform on the first frame with no relayout. When no title wraps, the tallest equals the rest and nothing changes.
…ell-subtitle-marquee Chore: onboarding crosssell subtitle marquee
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.
Onboarding feature, all steps and asks for analytics consent, without adding any real analytics events there yet