Skip to content

Feat: Onboarding - #3045

Merged
StylianosGakis merged 128 commits into
developfrom
feat/onboarding
Aug 12, 2026
Merged

Feat: Onboarding#3045
StylianosGakis merged 128 commits into
developfrom
feat/onboarding

Conversation

@StylianosGakis

Copy link
Copy Markdown
Member

Onboarding feature, all steps and asks for analytics consent, without adding any real analytics events there yet

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).
@StylianosGakis
StylianosGakis requested a review from a team as a code owner August 12, 2026 13:02
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
@StylianosGakis
StylianosGakis merged commit 9c28c96 into develop Aug 12, 2026
4 checks passed
@StylianosGakis
StylianosGakis deleted the feat/onboarding branch August 12, 2026 18:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant