Skip to content
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

feat: add site flow #1182

Merged
merged 1 commit into from
Dec 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions apps/mobile/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
ios/
android/
.expo/
20 changes: 18 additions & 2 deletions apps/mobile/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,22 @@
},
"ios": {
"supportsTablet": true,
"bundleIdentifier": "raven.thecommit.company"
"bundleIdentifier": "raven.thecommit.company",
"config": {
"usesNonExemptEncryption": false
},
"infoPlist": {
"NSAppTransportSecurity": {
"NSAllowsArbitraryLoads": true,
"NSAllowsLocalNetworking": true,
"NSExceptionDomains": {
"localhost": {
"NSIncludesSubdomains": true,
"NSExceptionAllowsInsecureHTTPLoads": true
}
}
}
}
},
"android": {
"adaptiveIcon": {
Expand All @@ -28,7 +43,8 @@
"favicon": "./assets/favicon.png"
},
"plugins": [
"expo-router"
"expo-router",
"expo-secure-store"
],
"extra": {
"router": {
Expand Down
134 changes: 134 additions & 0 deletions apps/mobile/app/[site_id]/_layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import { Text } from "@components/nativewindui/Text";
import { router, Stack, useLocalSearchParams } from "expo-router";
import { useContext, useEffect, useState } from "react";
import { View } from "react-native";
import { SiteInformation } from "../../types/SiteInformation";
import AsyncStorage from "@react-native-async-storage/async-storage";
import * as SecureStore from 'expo-secure-store';
import { TokenResponse } from "expo-auth-session";
import { FrappeConfig, FrappeContext, FrappeProvider, useFrappeGetDoc } from "frappe-react-sdk";

export default function SiteLayout() {

// Get the site ID from the route
const { site_id } = useLocalSearchParams()

// If this page is loaded, we need to fetch the site information and the access token
// On fetching the access token, we need to check if it's valid, and if not, we need to attempt to refresh it.
// If the refresh fails, we need to redirect the user to the landing page

const [loading, setLoading] = useState(true)
const [siteInfo, setSiteInfo] = useState<SiteInformation | null>(null)
const [accessToken, setAccessToken] = useState<TokenResponse | null>(null)


useEffect(() => {

let site_info: SiteInformation | null = null

AsyncStorage.getItem(`${site_id}-site-info`)
.then(siteInfo => {
if (!siteInfo) {
router.replace('/landing')

// TODO: Show the user a toast saying that the site is not found

return null
}

const parsedSiteInfo: SiteInformation = JSON.parse(siteInfo || '{}')
setSiteInfo(parsedSiteInfo)
site_info = parsedSiteInfo

return parsedSiteInfo
})
.then((siteInfo: SiteInformation | null) => {
if (!siteInfo) return null

return SecureStore.getItemAsync(`${site_id}-access-token`)
})
.then(accessToken => {
if (!accessToken) {
router.replace('/landing')

// TODO: Show the user a toast saying that the site is not found

return null
}
const tokenConfig: TokenResponse = JSON.parse(accessToken)

let tokenResponse = new TokenResponse(tokenConfig)

if (tokenResponse.shouldRefresh()) {
console.log("Refreshing token")
return tokenResponse.refreshAsync({
clientId: site_info?.client_id || '',
}, {
tokenEndpoint: site_info?.url + '/api/method/frappe.integrations.oauth2.get_token',
})
} else {
return tokenResponse
}
})
.then(tokenResponse => {
if (!tokenResponse) return

setAccessToken(tokenResponse)
})
.then(() => {
setLoading(false)
})

}, [site_id])

return <>
<Stack.Screen options={{ headerShown: false }} />
{loading ? <View className="flex-1 justify-center items-center gap-2">

{/* TODO: Change this UI */}
<Text className="text-4xl font-bold">raven</Text>
<Text>Setting up your workspace...</Text>
</View> :
<FrappeProvider
url={siteInfo?.url}
tokenParams={{
type: 'Bearer',
useToken: true,
token: () => accessToken?.accessToken || '',
}}
socketPort="9000"
siteName={siteInfo?.sitename}>
<TestSocket />
</FrappeProvider>
}
</>
}

const TestSocket = () => {

const { socket } = useContext(FrappeContext) as FrappeConfig

const [message, setMessage] = useState('')

const { data } = useFrappeGetDoc('User', 'Administrator')

useEffect(() => {

setTimeout(() => {
socket?.on('ice', () => {
setMessage('ice')
})
}, 1000)
setTimeout(() => {
socket?.emit('fire')
}, 2000)
}, [])

return <View className="flex-1 justify-center items-center">
<Text>{message}
{socket?.connected ? 'Connected' : 'Disconnected'}
{data?.name}
</Text>
</View>

}
15 changes: 13 additions & 2 deletions apps/mobile/app/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,25 @@ import { StatusBar } from 'expo-status-bar';
import { ActionSheetProvider } from '@expo/react-native-action-sheet';
import { PortalHost } from '@rn-primitives/portal';
import { KeyboardProvider } from 'react-native-keyboard-controller';
import { useAsyncStorage } from '@react-native-async-storage/async-storage';

export default function RootLayout() {

const path = usePathname()

const { getItem } = useAsyncStorage(`default-site`)
console.log(path)

// On load, check if the user has a site set

useEffect(() => {
// TODO: If authenticated and site set
router.replace('/(tabs)/home')
getItem().then(site => {
if (site) {
router.replace(`/${site}`)
} else {
router.replace('/landing')
}
})
}, [])

useInitialAndroidBarSync();
Expand All @@ -37,6 +46,8 @@ export default function RootLayout() {
<KeyboardProvider statusBarTranslucent navigationBarTranslucent>
<ThemeProvider value={NAV_THEME[colorScheme]}>
<Stack>
<Stack.Screen name="landing" />
<Stack.Screen name="[site_id]" options={{ headerShown: false }} />
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
<Stack.Screen name="+not-found" />
</Stack>
Expand Down
17 changes: 17 additions & 0 deletions apps/mobile/app/landing.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Stack } from 'expo-router';
import { View } from 'react-native';
import { Text } from '@components/nativewindui/Text';
import AddSite from '@components/features/auth/AddSite';

export default function NotFoundScreen() {
return (
<>
<Stack.Screen options={{ title: 'Sites', headerTitle: 'Sites' }} />
<View className='flex-1 py-8 px-4 gap-3'>
<Text className='text-3xl font-bold'>raven</Text>
<View className='h-2' />
<AddSite />
</View>
</>
);
}
Loading
Loading