Skip to content

Conversation

@dhairyashiil
Copy link
Member

@dhairyashiil dhairyashiil commented Jan 27, 2026

apps

Screen.Recording.2026-01-27.at.9.57.44.AM.mov

extension

Screen.Recording.2026-01-27.at.10.02.26.AM.mov

added success alert

Screen.Recording.2026-01-27.at.10.21.31.AM.mov

What does this PR do?

Adds a configurable landing page feature to the companion app, allowing users to choose which page the app opens to on launch. Users can select from Event Types, Bookings, or Bookings with a specific filter (Upcoming, Unconfirmed, Recurring, Past, Cancelled).

Changes:

  • New useUserPreferences hook for persistent storage of landing page preference using generalStorage
  • Tab index now redirects based on user preference instead of hardcoded event-types
  • Bookings pages accept initial filter from URL params
  • New "App Settings" section in More screen with landing page selector
  • Platform-specific LandingPagePicker components (Modal for Android/web, native ActionSheetIOS for iOS)
  • User preferences are cleared on logout for fresh state

Updates since last revision:

  • Fixed React Compiler compatibility by removing try-finally pattern in useUserPreferences hook (React Compiler doesn't support TryStatement with finalizer clause)

Link to Devin run: https://app.devin.ai/sessions/0d7cf7af9228410ba158026afd3e842d
Requested by: Dhairyashil Shinde (@dhairyashiil)

Mandatory Tasks (DO NOT REMOVE)

  • I have self-reviewed the code (A decent size PR without self-review might be rejected).
  • I have updated the developer docs in /docs if this PR makes changes that would require a documentation change. N/A - no docs changes needed.
  • I confirm automated tests are in place that prove my fix is effective or that my feature works.

How should this be tested?

  1. Open the companion app and navigate to More > App Settings > Default Landing Page
  2. Select different landing page options (Event Types, Bookings, Bookings with filters)
  3. Close and reopen the app - verify it opens to the selected page
  4. For bookings with filter options, verify the correct filter is pre-selected
  5. Log out and log back in - verify preferences are reset to default (Event Types)

Test on both iOS and Android to verify platform-specific picker implementations work correctly.

Checklist

  • My code follows the style guidelines of this project
  • I have checked if my changes generate no new warnings

Items for Human Review

  • Verify the type cast (filter as BookingFilter) in bookings index files is safe - an invalid URL param could cause issues
  • Verify iOS ActionSheetIOS behavior is acceptable (doesn't show current selection indicator like Android/web modal does)
  • Test logout flow properly clears preferences
  • Verify UI appearance on both iOS and Android platforms
  • Consider whether automated tests should be added for the useUserPreferences hook

- Add useUserPreferences hook for persistent storage of landing page preference
- Add LandingPagePicker component for both iOS and Android/web platforms
- Update tabs index to redirect based on user preference
- Update bookings index to accept initial filter from URL params
- Add App Settings section in More screen with landing page selector
- Clear user preferences on logout for fresh state
@devin-ai-integration
Copy link
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR that start with 'DevinAI' or '@devin'.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

Replace Redirect component with router.replace() to fix TypeScript
strict typing issue with expo-router's Href type for dynamic routes.
Use switch statement with literal route strings instead of dynamic
string variable to satisfy expo-router's strict Href type checking.
@Arc-a-it
Copy link

useUserPreferences is now influencing initial routing + landing behavior across platforms
That makes it a dependency-heavy decision point

One risk I’m thinking about
If this hook evolves again (new flags / conditions) it could quietly affect multiple entry paths without obvious PR level visibility

Not blocking i just curious
Is this intended to be a long term routing authority or should it stay narrow

@dhairyashiil dhairyashiil marked this pull request as ready for review January 27, 2026 04:34
@graphite-app graphite-app bot added the core area: core, team members only label Jan 27, 2026
@dhairyashiil
Copy link
Member Author

useUserPreferences is now influencing initial routing + landing behavior across platforms That makes it a dependency-heavy decision point

One risk I’m thinking about If this hook evolves again (new flags / conditions) it could quietly affect multiple entry paths without obvious PR level visibility

Not blocking i just curious Is this intended to be a long term routing authority or should it stay narrow

This hook is intended to stay narrow - it only handles user preferences like landing page selection. Routing logic in layout file only uses the landing page preference. If we add more routing-related logic in the future, we should evaluate whether it belongs here or in a dedicated routing hook

@dhairyashiil dhairyashiil enabled auto-merge (squash) January 27, 2026 04:36
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

10 issues found across 11 files

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="companion/app/(tabs)/(bookings)/index.tsx">

<violation number="1" location="companion/app/(tabs)/(bookings)/index.tsx:19">
P2: Validate the `filter` URL param before casting; an invalid value can produce an unsupported `activeFilter` and a `-1` `activeIndex`, which may break the filter UI or selection logic.</violation>
</file>

<file name="companion/components/LandingPagePicker.ios.tsx">

<violation number="1" location="companion/components/LandingPagePicker.ios.tsx:29">
P2: Localize the ActionSheetIOS title/message with t() and add the corresponding translation keys instead of hardcoded strings.</violation>
</file>

<file name="companion/app/(tabs)/(more)/index.ios.tsx">

<violation number="1" location="companion/app/(tabs)/(more)/index.ios.tsx:38">
P3: Localize newly added UI/alert text with `t()` instead of hardcoded strings so the labels and error message are translated consistently.</violation>
</file>

<file name="companion/hooks/useUserPreferences.ts">

<violation number="1" location="companion/hooks/useUserPreferences.ts:22">
P2: User-facing labels are hardcoded instead of using `t()` for localization. Please move these labels to translation keys and call `t()` here (and in the fallback).</violation>

<violation number="2" location="companion/hooks/useUserPreferences.ts:24">
P2: `LANDING_PAGE_OPTIONS` omits the `bookings:upcoming` option even though the type and routing support it, so users can’t select it and labels will fall back incorrectly. Add the missing option.</violation>
</file>

<file name="companion/app/(tabs)/(more)/index.tsx">

<violation number="1" location="companion/app/(tabs)/(more)/index.tsx:134">
P3: Localize the new App Settings and Default Landing Page labels with `t()` and add translation keys, instead of hardcoding text.</violation>
</file>

<file name="companion/components/LandingPagePicker.tsx">

<violation number="1" location="companion/components/LandingPagePicker.tsx:33">
P2: Hardcoded UI text should be localized via `t()`; add a translation key for this heading instead of embedding the English string directly.</violation>

<violation number="2" location="companion/components/LandingPagePicker.tsx:35">
P2: Localize this explanatory text using `t()` and a translation key instead of a hardcoded English sentence.</violation>

<violation number="3" location="companion/components/LandingPagePicker.tsx:68">
P3: Use the existing localized "cancel" string via `t("cancel")` rather than hardcoding the button label.</violation>
</file>

<file name="companion/app/(tabs)/_layout.tsx">

<violation number="1" location="companion/app/(tabs)/_layout.tsx:79">
P2: Localize this tab label via the i18n system (use `t()` with the appropriate translation key) instead of hardcoding the English string.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

@github-actions
Copy link
Contributor

Devin AI is addressing Cubic AI's review feedback

A Devin session has been created to address the issues identified by Cubic AI.

View Devin Session

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 2 files (changes from recent commits).

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="companion/app/(tabs)/(more)/index.ios.tsx">

<violation number="1" location="companion/app/(tabs)/(more)/index.ios.tsx:37">
P2: Localize the new success alert text with `t()` instead of hardcoded strings to follow the project’s localization requirement.</violation>
</file>

<file name="companion/app/(tabs)/(more)/index.tsx">

<violation number="1" location="companion/app/(tabs)/(more)/index.tsx:31">
P3: Localize the new success alert text via `t()` instead of hardcoded English strings so the message is translatable.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

@github-actions
Copy link
Contributor

Devin AI is addressing Cubic AI's review feedback

New feedback has been sent to the existing Devin session.

View Devin Session

@Arc-a-it
Copy link

@dhairyashiil That makes sense thanks for clarifying

The reason I asked is Ive been experimenting with a lightweight CI check that flags when a narrow hook starts accumulating architectural responsibility over time not to block changes but to force this exact conversation and leave a record if its consciously overridden

If it’s useful I can run it once on this PR and share what it would flag

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

core area: core, team members only size/L

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants