Importation automatique d'un train depuis Rail Planner par partage de l'URL d'un trajet

This commit is contained in:
Emmy D'Anello 2024-12-16 17:52:08 +01:00
parent 71b7df0008
commit b726305a44
Signed by: ynerant
GPG Key ID: 3A75C55819C8CF85
6 changed files with 74 additions and 51 deletions

View File

@ -5,7 +5,7 @@
"version": "1.0.0", "version": "1.0.0",
"orientation": "portrait", "orientation": "portrait",
"icon": "./assets/images/icon.png", "icon": "./assets/images/icon.png",
"scheme": "myapp", "scheme": "traintrapemoi",
"userInterfaceStyle": "automatic", "userInterfaceStyle": "automatic",
"newArchEnabled": true, "newArchEnabled": true,
"ios": { "ios": {
@ -45,7 +45,7 @@
"expo-notifications", "expo-notifications",
"expo-router", "expo-router",
"expo-secure-store", "expo-secure-store",
"expo-share-extension", "expo-share-intent",
[ [
"expo-splash-screen", "expo-splash-screen",
{ {

View File

@ -5,7 +5,8 @@ import { useTrain } from '@/hooks/useTrain'
import { TrainTrip } from '@/utils/features/train/trainSlice' import { TrainTrip } from '@/utils/features/train/trainSlice'
import { FontAwesome6 } from '@expo/vector-icons' import { FontAwesome6 } from '@expo/vector-icons'
import { useQueryClient } from '@tanstack/react-query' import { useQueryClient } from '@tanstack/react-query'
import { useMemo, useState } from 'react' import { useShareIntentContext } from 'expo-share-intent'
import { useEffect, useMemo, useState } from 'react'
import { FlatList, StyleSheet } from 'react-native' import { FlatList, StyleSheet } from 'react-native'
import { Button, Dialog, Divider, FAB, HelperText, List, MD3Colors, Portal, Snackbar, Surface, Text, TextInput } from 'react-native-paper' import { Button, Dialog, Divider, FAB, HelperText, List, MD3Colors, Portal, Snackbar, Surface, Text, TextInput } from 'react-native-paper'
@ -38,6 +39,24 @@ export default function TrainScreen() {
const trains = useTrain() const trains = useTrain()
const { hasShareIntent, shareIntent, resetShareIntent } = useShareIntentContext()
useEffect(() => {
console.log(hasShareIntent, shareIntent)
if (hasShareIntent) {
resetShareIntent()
if (!shareIntent.text || !shareIntent.text.includes("eurailapp.com/share"))
return
const parsedTrainId = /[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}/.exec(shareIntent.text)?.[0]
if (parsedTrainId)
addTrainMutation.mutate(parsedTrainId)
else {
setErrorVisible(true)
setError([400, "Impossible de récupérer l'identifiant du train à ajouter"])
}
}
}, [hasShareIntent])
return ( return (
<Surface style={{ flex: 1 }}> <Surface style={{ flex: 1 }}>
<PenaltyBanner /> <PenaltyBanner />

View File

@ -6,6 +6,7 @@ import { QueryClient } from '@tanstack/react-query'
import { createAsyncStoragePersister } from '@tanstack/query-async-storage-persister' import { createAsyncStoragePersister } from '@tanstack/query-async-storage-persister'
import { PersistQueryClientProvider } from '@tanstack/react-query-persist-client' import { PersistQueryClientProvider } from '@tanstack/react-query-persist-client'
import { Stack, useNavigationContainerRef } from 'expo-router' import { Stack, useNavigationContainerRef } from 'expo-router'
import { ShareIntentProvider } from 'expo-share-intent'
import { StatusBar } from 'expo-status-bar' import { StatusBar } from 'expo-status-bar'
import { MD3DarkTheme, MD3LightTheme, PaperProvider } from 'react-native-paper' import { MD3DarkTheme, MD3LightTheme, PaperProvider } from 'react-native-paper'
import { Provider as StoreProvider } from 'react-redux' import { Provider as StoreProvider } from 'react-redux'
@ -42,24 +43,26 @@ export default function RootLayout() {
client={queryClient} client={queryClient}
persistOptions={{ persister: asyncStoragePersister }} persistOptions={{ persister: asyncStoragePersister }}
onSuccess={() => queryClient.resumePausedMutations().then(() => queryClient.invalidateQueries())}> onSuccess={() => queryClient.resumePausedMutations().then(() => queryClient.invalidateQueries())}>
<LoginProvider loginRedirect={'/login'}> <ShareIntentProvider>
<GeolocationProvider> <LoginProvider loginRedirect={'/login'}>
<GameProvider> <GeolocationProvider>
<PaperProvider <GameProvider>
theme={colorScheme === 'dark' ? MD3DarkTheme : MD3LightTheme} > <PaperProvider
<ThemeProvider value={colorScheme === 'dark' ? DarkTheme : DefaultTheme}> theme={colorScheme === 'dark' ? MD3DarkTheme : MD3LightTheme} >
<Stack> <ThemeProvider value={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>
<Stack.Screen name="(tabs)" options={{ headerShown: false }} /> <Stack>
<Stack.Screen name="login" options={{ headerShown: false }} /> <Stack.Screen name="(tabs)" options={{ headerShown: false }} />
<Stack.Screen name="challenges-list" options={{ headerShown: false }} /> <Stack.Screen name="login" options={{ headerShown: false }} />
<Stack.Screen name="+not-found" /> <Stack.Screen name="challenges-list" options={{ headerShown: false }} />
</Stack> <Stack.Screen name="+not-found" />
<StatusBar style="auto" /> </Stack>
</ThemeProvider> <StatusBar style="auto" />
</PaperProvider> </ThemeProvider>
</GameProvider> </PaperProvider>
</GeolocationProvider> </GameProvider>
</LoginProvider> </GeolocationProvider>
</LoginProvider>
</ShareIntentProvider>
</PersistQueryClientProvider> </PersistQueryClientProvider>
</StoreProvider> </StoreProvider>
) )

View File

@ -8,6 +8,8 @@ import { isAuthValid } from '@/utils/features/auth/authSlice'
import { ChallengeAction, ChallengeActionPayload } from '@/utils/features/challengeActions/challengeActionsSlice' import { ChallengeAction, ChallengeActionPayload } from '@/utils/features/challengeActions/challengeActionsSlice'
import { Challenge } from '@/utils/features/challenges/challengesSlice' import { Challenge } from '@/utils/features/challenges/challengesSlice'
import { useQuery } from '@tanstack/react-query' import { useQuery } from '@tanstack/react-query'
import { router } from 'expo-router'
import { useShareIntentContext } from 'expo-share-intent'
import { ReactNode, useEffect } from 'react' import { ReactNode, useEffect } from 'react'
export default function GameProvider({ children }: { children: ReactNode }) { export default function GameProvider({ children }: { children: ReactNode }) {
@ -108,6 +110,16 @@ export default function GameProvider({ children }: { children: ReactNode }) {
} }
}, [game.currentRunner, challengeActions]) }, [game.currentRunner, challengeActions])
const { hasShareIntent, shareIntent, resetShareIntent } = useShareIntentContext()
useEffect(() => {
console.log(hasShareIntent, shareIntent)
if (hasShareIntent) {
if (!shareIntent.text || !shareIntent.text.includes("eurailapp.com/share"))
return resetShareIntent()
router.replace('/train')
}
}, [hasShareIntent])
return <> return <>
{children} {children}
</> </>

View File

@ -31,7 +31,7 @@
"expo-notifications": "~0.29.11", "expo-notifications": "~0.29.11",
"expo-router": "~4.0.9", "expo-router": "~4.0.9",
"expo-secure-store": "~14.0.0", "expo-secure-store": "~14.0.0",
"expo-share-extension": "^2.0.1", "expo-share-intent": "^3.1.1",
"expo-splash-screen": "~0.29.13", "expo-splash-screen": "~0.29.13",
"expo-status-bar": "~2.0.0", "expo-status-bar": "~2.0.0",
"expo-symbols": "~0.2.0", "expo-symbols": "~0.2.0",
@ -8121,33 +8121,31 @@
"expo": "*" "expo": "*"
} }
}, },
"node_modules/expo-share-extension": { "node_modules/expo-share-intent": {
"version": "2.0.1", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/expo-share-extension/-/expo-share-extension-2.0.1.tgz", "resolved": "https://registry.npmjs.org/expo-share-intent/-/expo-share-intent-3.1.1.tgz",
"integrity": "sha512-MFjzN8xapBAz3f8lZCTmgVYjVeVa8gUC0NLuTTMgeIwNlua3HW/ySbkYxyRsSX48q7MtVV/OwxqkOfnw6Bpj/w==", "integrity": "sha512-YoO7arEP8oRRevQ3digP7Fu1r1Nk6Zo2LfPndWfLXota1O8BLlAkl15W5dOLqRrYIAuRfQpcmmtXu/pUA0pvQg==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/achorein"
},
"https://www.buymeacoffee.com/achorein"
],
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"semver": "^7.6.3", "@expo/config-plugins": "^9.0.9",
"zod": "^3.23.8" "expo-constants": "^17.0.2",
"expo-linking": "~7.0.2"
}, },
"peerDependencies": { "peerDependencies": {
"expo": "*", "expo": "^52",
"expo-constants": ">=17.0.2",
"expo-linking": ">=7.0.2",
"react": "*", "react": "*",
"react-native": "*" "react-native": "*"
} }
}, },
"node_modules/expo-share-extension/node_modules/semver": {
"version": "7.6.3",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
"integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/expo-splash-screen": { "node_modules/expo-splash-screen": {
"version": "0.29.18", "version": "0.29.18",
"resolved": "https://registry.npmjs.org/expo-splash-screen/-/expo-splash-screen-0.29.18.tgz", "resolved": "https://registry.npmjs.org/expo-splash-screen/-/expo-splash-screen-0.29.18.tgz",
@ -16801,15 +16799,6 @@
"funding": { "funding": {
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
},
"node_modules/zod": {
"version": "3.24.1",
"resolved": "https://registry.npmjs.org/zod/-/zod-3.24.1.tgz",
"integrity": "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/colinhacks"
}
} }
} }
} }

View File

@ -37,7 +37,7 @@
"expo-notifications": "~0.29.11", "expo-notifications": "~0.29.11",
"expo-router": "~4.0.9", "expo-router": "~4.0.9",
"expo-secure-store": "~14.0.0", "expo-secure-store": "~14.0.0",
"expo-share-extension": "^2.0.1", "expo-share-intent": "^3.1.1",
"expo-splash-screen": "~0.29.13", "expo-splash-screen": "~0.29.13",
"expo-status-bar": "~2.0.0", "expo-status-bar": "~2.0.0",
"expo-symbols": "~0.2.0", "expo-symbols": "~0.2.0",