-
Notifications
You must be signed in to change notification settings - Fork 0
Add markdown and LaTeX math rendering for chat messages #6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
730f558
0858a64
733c80b
6a875a0
c56cbf7
139d075
f43fbfc
cf381e2
fb05aad
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,13 @@ | ||
| import React from 'react'; | ||
| import { render, act } from '@testing-library/react-native'; | ||
| import RootLayout from '../_layout'; | ||
| import * as SplashScreen from 'expo-splash-screen'; | ||
| import * as Notifications from 'expo-notifications'; | ||
| import { fetchBots } from '@/api/bots'; | ||
| import { fetchChat } from '@/api/chats'; | ||
| import { UnauthorizedError } from '@/api/apiClient'; | ||
| import { useRouter, usePathname } from 'expo-router'; | ||
| import { View } from 'react-native'; | ||
|
|
||
| jest.mock('@sentry/react-native', () => ({ | ||
| reactNavigationIntegration: jest.fn(() => ({ | ||
|
|
@@ -12,13 +19,6 @@ jest.mock('@sentry/react-native', () => ({ | |
| jest.mock('../_layout', () => ({ | ||
| default: function MockRootLayout() { return null; }, | ||
| })); | ||
| import RootLayout from '../_layout'; | ||
| import * as SplashScreen from 'expo-splash-screen'; | ||
| import * as Notifications from 'expo-notifications'; | ||
| import { fetchBots } from '@/api/bots'; | ||
| import { fetchChat } from '@/api/chats'; | ||
| import { UnauthorizedError } from '@/api/apiClient'; | ||
| import { View } from 'react-native'; | ||
|
|
||
| // Create a mock Stack component | ||
| interface MockStackProps { | ||
|
|
@@ -177,6 +177,10 @@ describe('RootLayout', () => { | |
|
|
||
| unmount(); | ||
|
|
||
| expect(Notifications.removeNotificationSubscription).toHaveBeenCalled(); | ||
| const receivedSubscription = (Notifications.addNotificationReceivedListener as jest.Mock).mock.results[0]?.value; | ||
| const responseSubscription = (Notifications.addNotificationResponseReceivedListener as jest.Mock).mock.results[0]?.value; | ||
|
|
||
| expect(receivedSubscription.remove).toHaveBeenCalled(); | ||
| expect(responseSubscription.remove).toHaveBeenCalled(); | ||
|
Comment on lines
+180
to
+184
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: # First, let's examine the test file structure and the specific lines mentioned
cd front/app/__tests__ && cat -n _layout-test.tsx | head -30Repository: tpaulshippy/bots Length of output: 1182 🏁 Script executed: # Now let's look at lines 15-25 to see the mock setup
cat -n _layout-test.tsx | sed -n '15,25p'Repository: tpaulshippy/bots Length of output: 108 🏁 Script executed: # Look at lines 170-190 to see the full context of the assertions
cat -n _layout-test.tsx | sed -n '170,190p'Repository: tpaulshippy/bots Length of output: 108 🏁 Script executed: # Let's also check the actual implementation to understand cleanup behavior
cat -n ../../../app/_layout.tsx | sed -n '95,130p'Repository: tpaulshippy/bots Length of output: 116 🏁 Script executed: # Check if the test is skipped (using "skip" or "pending" keywords)
grep -n "\.skip\|\.todo\|pending\|xit" _layout-test.tsx | head -20Repository: tpaulshippy/bots Length of output: 109 🏁 Script executed: fd -type f -name "_layout-test.tsx"Repository: tpaulshippy/bots Length of output: 230 🏁 Script executed: fd -type f -name "_layout.tsx" | grep appRepository: tpaulshippy/bots Length of output: 230 🏁 Script executed: fd -t f -name "_layout-test.tsx"Repository: tpaulshippy/bots Length of output: 290 🏁 Script executed: fd -t f -name "_layout.tsx" | grep appRepository: tpaulshippy/bots Length of output: 290 🏁 Script executed: fd "_layout-test.tsx"Repository: tpaulshippy/bots Length of output: 96 🏁 Script executed: fd "_layout.tsx"Repository: tpaulshippy/bots Length of output: 81 🏁 Script executed: cat -n front/app/__tests__/_layout-test.tsx | sed -n '170,195p'Repository: tpaulshippy/bots Length of output: 857 🏁 Script executed: wc -l front/app/_layout.tsxRepository: tpaulshippy/bots Length of output: 85 🏁 Script executed: cat -n front/app/_layout.tsx | sed -n '90,140p'Repository: tpaulshippy/bots Length of output: 1882 🏁 Script executed: # Check the entire test to understand the render call and mock.results
cat -n front/app/__tests__/_layout-test.tsx | sed -n '150,185p'Repository: tpaulshippy/bots Length of output: 1600 This assertion never exercises the real cleanup path. The test is currently skipped (line 172). Because 🤖 Prompt for AI Agents |
||
| }); | ||
| }); | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -7,7 +7,7 @@ import { ErrorBoundary } from "@/components/ErrorBoundary"; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { useFonts } from "expo-font"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import * as SplashScreen from "expo-splash-screen"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { StatusBar } from "expo-status-bar"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { useEffect, useRef } from "react"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { useCallback, useEffect, useRef } from "react"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import * as Notifications from "expo-notifications"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import "react-native-reanimated"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { useColorScheme } from "@/hooks/useColorScheme"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -77,7 +77,7 @@ export default function RootLayout() { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const notificationListener = useRef<Notifications.EventSubscription | null>(null); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const responseListener = useRef<Notifications.EventSubscription | null>(null); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const navigateToChat = (chatId: string, title: string) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const navigateToChat = useCallback((chatId: string, title: string) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (pathname === "/chat") { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| router.replace({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pathname: "/chat", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -89,7 +89,7 @@ export default function RootLayout() { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| params: { chatId, title }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, [pathname, router]); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| useEffect(() => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (ref?.current) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -99,7 +99,7 @@ export default function RootLayout() { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| useEffect(() => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| notificationListener.current = | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Notifications.addNotificationReceivedListener(async (notification) => {}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Notifications.addNotificationReceivedListener(async () => {}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| responseListener.current = | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Notifications.addNotificationResponseReceivedListener( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -124,33 +124,12 @@ export default function RootLayout() { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| notificationListener.current && | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Notifications.removeNotificationSubscription( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| notificationListener.current | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| responseListener.current && | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Notifications.removeNotificationSubscription(responseListener.current); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| notificationListener.current?.remove(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| responseListener.current?.remove(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, []); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const getJWTFromLink = async (event?: any) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const url = event?.url; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (url) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const { queryParams } = Linking.parse(url); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (queryParams && queryParams.access && queryParams.refresh) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const access = queryParams.access as string; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const refresh = queryParams.refresh as string; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await setTokens({ access, refresh }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| WebBrowser.dismissBrowser(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, [navigateToChat]); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| router.replace("/"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await initialNavigationChecks(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const setProfile = async () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const setProfile = useCallback(async () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const profileData = await AsyncStorage.getItem("selectedProfile"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const profiles = await fetchProfiles(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (profileData) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -168,9 +147,9 @@ export default function RootLayout() { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, []); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const initialNavigationChecks = async () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const initialNavigationChecks = useCallback(async () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await fetchBots(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await setProfile(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -180,19 +159,41 @@ export default function RootLayout() { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| router.replace("/login"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, [router, setProfile]); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const getJWTFromLink = useCallback(async (event?: any) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const url = event?.url; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (url) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const { queryParams } = Linking.parse(url); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (queryParams && queryParams.access && queryParams.refresh) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const access = queryParams.access as string; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const refresh = queryParams.refresh as string; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await setTokens({ access, refresh }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| WebBrowser.dismissBrowser(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| router.replace("/"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await initialNavigationChecks(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, [initialNavigationChecks, router]); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| useEffect(() => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (loaded) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const subscription = Linking.addEventListener("url", getJWTFromLink); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const initialize = async () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| SplashScreen.hideAsync(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Linking.addEventListener("url", getJWTFromLink); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await initialNavigationChecks(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| initialize(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| void initialize(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| subscription.remove(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, [loaded]); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, [getJWTFromLink, initialNavigationChecks, loaded]); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
181
to
+196
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: # First, let's read the actual code to see what's at lines 181-196
cat -n front/app/_layout.tsx | sed -n '175,205p'Repository: tpaulshippy/bots Length of output: 957 🏁 Script executed: # Check if Linking.getInitialURL is used anywhere in the codebase
rg "getInitialURL" front/Repository: tpaulshippy/bots Length of output: 42 🏁 Script executed: # Look at the entire _layout.tsx file to understand the context
wc -l front/app/_layout.tsxRepository: tpaulshippy/bots Length of output: 85 🏁 Script executed: # Let's search for getJWTFromLink definition
rg "getJWTFromLink" front/app/_layout.tsx -B 5 -A 10Repository: tpaulshippy/bots Length of output: 1188 🏁 Script executed: # Check if there's any deep link handling in app initialization
rg "Linking\." front/app/_layout.tsxRepository: tpaulshippy/bots Length of output: 185 🏁 Script executed: # Look for any other Expo deep link handling patterns in the codebase
rg "Linking\.getInitialURL|Linking\.addEventListener" front/Repository: tpaulshippy/bots Length of output: 157 🏁 Script executed: # Let's see the full _layout.tsx file to understand the overall structure
cat -n front/app/_layout.tsx | head -100Repository: tpaulshippy/bots Length of output: 3902 🏁 Script executed: # Let's see more of the file, particularly the getJWTFromLink function definition
cat -n front/app/_layout.tsx | sed -n '100,180p'Repository: tpaulshippy/bots Length of output: 3031 🏁 Script executed: # Check Expo documentation for Linking API best practices by searching for any comments or setup
rg "Linking|deep.*link" front/app/_layout.tsx -iRepository: tpaulshippy/bots Length of output: 226 🏁 Script executed: # Let's verify the Expo Linking API pattern by checking if there are any other files that handle deep linking
rg "getInitialURL" . --type ts --type tsxRepository: tpaulshippy/bots Length of output: 87 🏁 Script executed: # Check the app.json or app configuration to see if deep linking is configured
fd -e "json" -e "config" | xargs grep -l "scheme\|deep.*link\|linking" 2>/dev/null | head -10Repository: tpaulshippy/bots Length of output: 117 🏁 Script executed: # Check the app.json for deep linking configuration
cat front/app.jsonRepository: tpaulshippy/bots Length of output: 2118 🏁 Script executed: # Search for deep linking patterns in the entire front directory
rg "getInitialURL|deeplink|deep.*link" front/ -iRepository: tpaulshippy/bots Length of output: 42 Process the initial deep link on cold start, not just runtime events. This effect only subscribes to future Suggested fix useEffect(() => {
if (loaded) {
const subscription = Linking.addEventListener("url", getJWTFromLink);
const initialize = async () => {
+ const initialUrl = await Linking.getInitialURL();
+ if (initialUrl) {
+ await getJWTFromLink({ url: initialUrl });
+ }
await initialNavigationChecks();
- SplashScreen.hideAsync();
+ await SplashScreen.hideAsync();
};
void initialize();
return () => {
subscription.remove();
};
}
}, [getJWTFromLink, initialNavigationChecks, loaded]);📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!loaded) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: tpaulshippy/bots
Length of output: 941
🏁 Script executed:
Repository: tpaulshippy/bots
Length of output: 84
🏁 Script executed:
Repository: tpaulshippy/bots
Length of output: 1148
🏁 Script executed:
Repository: tpaulshippy/bots
Length of output: 42
🏁 Script executed:
Repository: tpaulshippy/bots
Length of output: 76
🏁 Script executed:
Repository: tpaulshippy/bots
Length of output: 5810
🏁 Script executed:
cat -n front/api/apiClient.ts | head -80Repository: tpaulshippy/bots
Length of output: 2635
Use
okfor success checks to match codebase pattern.Lines 19 and 60 check exact status codes (
200and204), but the entire codebase—and theApiResponseinterface itself—uses theokflag for success validation. This exact-match approach is stricter and inconsistent. Line 41 in the same file (updateAccount) already uses!ok, confirming the intended pattern.Replace both exact status checks with
!okto align with devices.ts, profiles.ts, bots.ts, chats.ts, and aiModels.ts:Suggested fix
Also applies to: 56–61
🤖 Prompt for AI Agents