Conversation
WalkthroughIntroduces a nested Settings stack with a new Settings screen, licenses list/detail routes, and a cross-platform ScrollView UI component. Removes the previous placeholder Settings screen. Adjusts main layout to hide the Settings header. Adds AsyncStorage-backed Sentry consent toggle and DevSettings-based app reload. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor User
participant Settings as Settings Screen
participant Storage as AsyncStorage
participant Dev as DevSettings
participant Router as Expo Router
User->>Settings: Open Settings
activate Settings
Settings->>Storage: getItem("sentryConsent")
Storage-->>Settings: "1" | "0" | null
Settings-->>User: Render toggle (on/off)
User->>Settings: Tap "Licenses"
Settings->>Router: navigate("/main/settings/licenses")
deactivate Settings
sequenceDiagram
autonumber
actor User
participant List as Licenses List
participant Detail as License Detail
participant Data as licenses.json
participant Router as Expo Router
User->>List: Open Licenses
List->>Data: import licenses
Data-->>List: licenses[]
User->>List: Tap package row (pkg)
List->>Router: navigate("/.../licenses/[pkg]", { pkg })
Router-->>Detail: params.pkg
Detail->>Data: find license by pkg
Data-->>Detail: license | undefined
Detail-->>User: Render text or "License not found"
sequenceDiagram
autonumber
actor User
participant Settings as Settings Screen
participant Storage as AsyncStorage
participant Dev as DevSettings
User->>Settings: Toggle Sentry
Settings->>Storage: setItem("sentryConsent", "1"/"0")
Storage-->>Settings: Promise resolved
Settings->>Dev: reload()
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Pre-merge checks (2 passed, 1 warning)❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
Poem
Tip 👮 Agentic pre-merge checks are now available in preview!Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.
Example: reviews:
pre_merge_checks:
custom_checks:
- name: "Undocumented Breaking Changes"
mode: "warning"
instructions: |
Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).Please share your feedback with us on this Discord post. ✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (6)
app/app/main/_layout.tsx (1)
60-66: Redundant headerShown override on Settings tabYou already set
headerShown: falsein the parentscreenOptions. This per-screen override is unnecessary.options={{ title: "Settings", tabBarIcon: getTabBarIcon("Settings", "cog"), - headerShown: false, }}app/app/main/settings/licenses/index.tsx (2)
5-5: Verify import path for licenses.json (alias vs relative path)
import licenses from "@/licenses.json";assumes@resolves to the directory containinglicenses.json. If the file actually lives next to this module (e.g.,app/app/main/settings/licenses/licenses.json), the alias will fail on native/web builds. Prefer a relative import to make it location-agnostic.- import licenses from "@/licenses.json"; + import licenses from "./licenses.json";
10-26: Minor UX: make rows accessible and deterministic order
- Add accessibility roles/states for better a11y.
- Consider sorting by package name for stable list order.
- <ScrollView className="flex-1 p-4"> - {licenses.map((pkg) => ( - <Pressable + <ScrollView className="flex-1 p-4"> + {licenses + .slice() + .sort((a, b) => a.name.localeCompare(b.name)) + .map((pkg) => ( + <Pressable key={pkg.name} className="py-2 border-b border-gray-200" - onPress={() => + accessibilityRole="button" + onPress={() => router.push({ pathname: "/main/settings/licenses/[pkg]", params: { pkg: pkg.name }, }) } >app/app/main/settings/licenses/[pkg].tsx (2)
4-4: Verify licenses.json import path here as wellMatch the approach used in the list screen to avoid alias resolution issues.
- import licenses from "@/licenses.json"; + import licenses from "./licenses.json";
14-16: Preserve formatting across platforms and improve readability
whitespace-pre-wraponly affects web. For RN, newlines are respected but multiple spaces may collapse. Consider making the text selectable and using a monospace font to improve license readability.- <Text className="whitespace-pre-wrap"> + <Text selectable className="whitespace-pre-wrap font-mono"> {info?.text || "License not found"} </Text>app/app/main/settings/index.tsx (1)
35-50: A11y: mark the custom switch as a real switchExpose correct accessibility metadata so screen readers announce state changes.
- <Pressable onPress={toggleSentry}> + <Pressable + onPress={toggleSentry} + accessibilityRole="switch" + accessibilityState={{ checked: sentryEnabled }} + aria-checked={sentryEnabled} + >
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
app/app/main/_layout.tsx(1 hunks)app/app/main/settings.tsx(0 hunks)app/app/main/settings/_layout.tsx(1 hunks)app/app/main/settings/index.tsx(1 hunks)app/app/main/settings/licenses/[pkg].tsx(1 hunks)app/app/main/settings/licenses/index.tsx(1 hunks)app/components/ui/scroll-view/index.tsx(1 hunks)app/components/ui/scroll-view/index.web.tsx(1 hunks)app/components/ui/scroll-view/styles.tsx(1 hunks)
💤 Files with no reviewable changes (1)
- app/app/main/settings.tsx
🧰 Additional context used
🧬 Code graph analysis (8)
app/components/ui/scroll-view/styles.tsx (4)
app/components/ui/gluestack-ui-provider/index.web.tsx (3)
window(68-81)GluestackUIProvider(22-96)mode(48-57)app/components/ui/hstack/index.web.tsx (1)
HStack(9-17)app/components/ui/box/index.tsx (1)
Box(11-15)app/components/ui/center/index.web.tsx (1)
Center(9-16)
app/app/main/settings/index.tsx (3)
app/app/main/settings/licenses/[pkg].tsx (1)
options(21-23)app/app/main/settings/licenses/index.tsx (1)
options(30-32)app/app/_layout.tsx (5)
Layout(15-124)setPrivacyConsent(105-110)setPrivacyConsent(94-99)AsyncStorage(21-26)sentryConsent(28-63)
app/app/main/settings/licenses/[pkg].tsx (4)
app/components/ui/scroll-view/index.tsx (1)
ScrollView(23-23)app/components/ui/scroll-view/index.web.tsx (1)
ScrollView(15-15)app/app/main/settings/index.tsx (1)
options(55-57)app/app/main/settings/licenses/index.tsx (1)
options(30-32)
app/app/main/settings/_layout.tsx (2)
app/app/(tabs)/settings.tsx (1)
Settings(3-5)app/app/(tabs)/_layout.tsx (1)
TabLayout(35-72)
app/components/ui/scroll-view/index.web.tsx (2)
app/components/ui/scroll-view/styles.tsx (1)
scrollViewStyle(8-10)app/hooks/use-scroll-ref.tsx (1)
ScrollRefProvider(18-23)
app/app/main/settings/licenses/index.tsx (5)
app/components/ui/scroll-view/index.tsx (1)
ScrollView(23-23)app/components/ui/scroll-view/index.web.tsx (1)
ScrollView(15-15)app/components/ui/pressable/index.tsx (1)
Pressable(39-39)app/app/main/settings/index.tsx (1)
options(55-57)app/app/main/settings/licenses/[pkg].tsx (1)
options(21-23)
app/app/main/_layout.tsx (1)
app/app/(tabs)/settings.tsx (1)
Settings(3-5)
app/components/ui/scroll-view/index.tsx (3)
app/components/ui/scroll-view/styles.tsx (1)
scrollViewStyle(8-10)app/hooks/use-scroll-ref.tsx (2)
ScrollRefProvider(18-23)useContext(25-25)app/components/render-node.tsx (1)
scrollRef(239-242)
🪛 GitHub Actions: Lint App
app/components/ui/scroll-view/index.web.tsx
[warning] 1-1: Prettier formatting issue detected in this file. Run 'prettier --write' to fix.
🔇 Additional comments (3)
app/app/main/settings/_layout.tsx (1)
1-5: LGTM: minimal nested Stack layoutSimple and correct for hosting the nested Settings routes.
app/components/ui/scroll-view/styles.tsx (1)
1-10: LGTM: web-only base class applicationUsing
isWebto scope the base class set to web avoids RN style warnings, and centralizing viatvais consistent with other UI wrappers.app/components/ui/scroll-view/index.tsx (1)
1-24: LGTM: RN ScrollView wrapper with TVA-based classNameTyping, ref-forwarding, and class composition look good.
| const toggleSentry = async () => { | ||
| const next = !sentryEnabled; | ||
| setSentryEnabled(next); | ||
| await AsyncStorage.setItem("sentryConsent", next ? "1" : "0"); | ||
| DevSettings.reload(); | ||
| }; |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Production-safe reload: prefer expo-updates over DevSettings.reload()
DevSettings.reload() is dev-only and won’t work in production. Use expo-updates when available, falling back to DevSettings.reload().
-import { DevSettings } from "react-native";
+import { DevSettings } from "react-native";
+import * as Updates from "expo-updates";
@@
const toggleSentry = async () => {
const next = !sentryEnabled;
setSentryEnabled(next);
await AsyncStorage.setItem("sentryConsent", next ? "1" : "0");
- DevSettings.reload();
+ if (Updates?.reloadAsync) {
+ await Updates.reloadAsync();
+ } else if (DevSettings?.reload) {
+ DevSettings.reload();
+ }
};📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const toggleSentry = async () => { | |
| const next = !sentryEnabled; | |
| setSentryEnabled(next); | |
| await AsyncStorage.setItem("sentryConsent", next ? "1" : "0"); | |
| DevSettings.reload(); | |
| }; | |
| // at the top of app/app/main/settings/index.tsx | |
| import { DevSettings } from "react-native"; | |
| import * as Updates from "expo-updates"; | |
| // … | |
| const toggleSentry = async () => { | |
| const next = !sentryEnabled; | |
| setSentryEnabled(next); | |
| await AsyncStorage.setItem("sentryConsent", next ? "1" : "0"); | |
| if (Updates?.reloadAsync) { | |
| await Updates.reloadAsync(); | |
| } else if (DevSettings?.reload) { | |
| DevSettings.reload(); | |
| } | |
| }; |
🤖 Prompt for AI Agents
In app/app/main/settings/index.tsx around lines 20 to 25, the toggleSentry
function calls DevSettings.reload() which only works in dev builds; replace that
call with expo-updates' reload when available and fall back to
DevSettings.reload() for older setups. Import { Updates } from 'expo-updates'
(or require dynamically), then after persisting the consent call await
Updates.reloadAsync() when Updates.isAvailable is true (or wrap in try/catch),
otherwise call DevSettings.reload(); ensure the reload invocation is awaited or
handled and gracefully falls back on error.
|
|
||
| const ScrollView = React.forwardRef<React.ComponentRef<"div">, IScrollViewProps>( | ||
| function ScrollView({ className, ...props }, ref) { | ||
| return <div ref={ref} {...props} className={scrollViewStyle({ class: className })} />; |
There was a problem hiding this comment.
Fix Prettier failure by wrapping long JSX line
CI flagged a Prettier issue. Wrap props across lines.
- return <div ref={ref} {...props} className={scrollViewStyle({ class: className })} />;
+ return (
+ <div
+ ref={ref}
+ {...props}
+ className={scrollViewStyle({ class: className })}
+ />
+ );📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| return <div ref={ref} {...props} className={scrollViewStyle({ class: className })} />; | |
| return ( | |
| <div | |
| ref={ref} | |
| {...props} | |
| className={scrollViewStyle({ class: className })} | |
| /> | |
| ); |
🤖 Prompt for AI Agents
In app/components/ui/scroll-view/index.web.tsx around line 10, the single long
JSX return line causes Prettier failure; split the JSX attributes across
multiple lines so the element is wrapped: place the opening tag on its own line,
put ref={ref}, {...props}, and className={scrollViewStyle({ class: className })}
each on separate indented lines, and close the tag on its own line to satisfy
line-length/formatting rules.
Summary
pnpm licenses listTesting
pnpm testpnpm lintpnpm type-checkhttps://chatgpt.com/codex/tasks/task_e_68c08dbe13e88333bb17f09fc44693b2
Summary by CodeRabbit
New Features
Enhancements
Removed