mirror of
https://github.com/hanzo-io/team.git
synced 2026-10-30 18:56:23 +00:00
106 lines
3.3 KiB
TypeScript
106 lines
3.3 KiB
TypeScript
import { useCallback, useMemo, useEffect, useState } from "react"
|
|
import { useSheetRef } from "@components/nativewindui/Sheet"
|
|
import { SiteInformation } from "types/SiteInformation"
|
|
import { getAccessToken, getRevocationEndpoint, setDefaultSite, getSitesFromStorage, getTokenEndpoint, storeAccessToken } from "@lib/auth"
|
|
import { revokeAsync, TokenResponse } from "expo-auth-session"
|
|
import { router } from "expo-router"
|
|
|
|
export const useSiteSwitcher = () => {
|
|
|
|
const bottomSheetRef = useSheetRef()
|
|
|
|
const [sites, setSites] = useState<Record<string, SiteInformation>>({})
|
|
|
|
useEffect(() => {
|
|
getSitesFromStorage().then(setSites)
|
|
}, [])
|
|
|
|
const [siteInformation, setSiteInformation] = useState<SiteInformation | null>(null)
|
|
|
|
const clearSiteInformation = useCallback(() => {
|
|
setSiteInformation(null)
|
|
}, [])
|
|
|
|
const hasSites = useMemo(() => Object.keys(sites).length > 0, [sites])
|
|
|
|
const presentBottomSheet = useCallback(() => {
|
|
bottomSheetRef.current?.present()
|
|
}, [bottomSheetRef])
|
|
|
|
const handleSitePress = useCallback(async (siteName: string) => {
|
|
|
|
const siteInfo = sites[siteName]
|
|
setSiteInformation(siteInfo)
|
|
|
|
// We need to see if we have an Access Token for this site in SecureStore
|
|
// If yes, we need to check if it's expired
|
|
// If it's expired, try to refresh it
|
|
// If it's not expired, or the refresh succeeds, we need to set the site as the default site
|
|
// If the refresh fails, or the token is not in SecureStore, we need to show the auth flow
|
|
|
|
const accessToken = await getAccessToken(siteName)
|
|
|
|
if (!accessToken) {
|
|
presentBottomSheet()
|
|
return
|
|
}
|
|
|
|
let tokenResponse = new TokenResponse(accessToken)
|
|
|
|
if (tokenResponse.shouldRefresh()) {
|
|
|
|
const url = siteInfo?.url ?? ''
|
|
tokenResponse.refreshAsync({
|
|
clientId: siteInfo?.client_id || '',
|
|
}, {
|
|
tokenEndpoint: getTokenEndpoint(url),
|
|
}).then(async (tokenResponse) => {
|
|
await storeAccessToken(siteName, tokenResponse)
|
|
|
|
// Revoke the old token
|
|
try {
|
|
await revokeAsync({
|
|
clientId: siteInfo?.client_id || '',
|
|
token: accessToken.accessToken,
|
|
}, {
|
|
revocationEndpoint: getRevocationEndpoint(url),
|
|
})
|
|
} catch (error) {
|
|
// Can ignore this error
|
|
console.error(error)
|
|
}
|
|
|
|
// Set the site as the default site
|
|
setDefaultSite(siteName)
|
|
|
|
// Redirect to the site
|
|
router.replace(`/${siteName}`)
|
|
|
|
}).catch((error) => {
|
|
console.error(error)
|
|
|
|
// Present the bottom sheet to allow the user to try again
|
|
presentBottomSheet()
|
|
})
|
|
} else {
|
|
// Set the site as the default site
|
|
setDefaultSite(siteName)
|
|
|
|
// Redirect to the site
|
|
router.replace(`/${siteName}`)
|
|
}
|
|
|
|
}, [sites])
|
|
|
|
|
|
return {
|
|
sites,
|
|
siteInformation,
|
|
presentBottomSheet,
|
|
handleSitePress,
|
|
clearSiteInformation,
|
|
hasSites,
|
|
bottomSheetRef
|
|
}
|
|
|
|
} |