parent
efe3c2c9c7
commit
37baf57093
20
src/App.tsx
20
src/App.tsx
@ -4,8 +4,6 @@ import { Navigate, Route, Routes } from 'react-router-dom'
|
||||
import { useAppSelector, useAuth } from './hooks'
|
||||
|
||||
import { MainLayout } from './layouts/Main'
|
||||
|
||||
import { appPrivateRoutes, appPublicRoutes } from './routes'
|
||||
import {
|
||||
privateRoutes,
|
||||
publicRoutes,
|
||||
@ -16,7 +14,7 @@ import './App.scss'
|
||||
|
||||
const App = () => {
|
||||
const { checkSession } = useAuth()
|
||||
const authState = useAppSelector((state) => state.auth)
|
||||
const isLoggedIn = useAppSelector((state) => state.auth?.loggedIn)
|
||||
|
||||
useEffect(() => {
|
||||
if (window.location.hostname === '0.0.0.0') {
|
||||
@ -29,19 +27,9 @@ const App = () => {
|
||||
checkSession()
|
||||
}, [checkSession])
|
||||
|
||||
const handleRootRedirect = () => {
|
||||
if (authState.loggedIn) return appPrivateRoutes.homePage
|
||||
|
||||
const callbackPathEncoded = btoa(
|
||||
window.location.href.split(`${window.location.origin}/#`)[1]
|
||||
)
|
||||
|
||||
return `${appPublicRoutes.landingPage}?callbackPath=${callbackPathEncoded}`
|
||||
}
|
||||
|
||||
// Hide route only if loggedIn and r.hiddenWhenLoggedIn are both true
|
||||
const publicRoutesList = recursiveRouteRenderer(publicRoutes, (r) => {
|
||||
return !authState.loggedIn || !r.hiddenWhenLoggedIn
|
||||
return !isLoggedIn || !r.hiddenWhenLoggedIn
|
||||
})
|
||||
|
||||
const privateRouteList = recursiveRouteRenderer(privateRoutes)
|
||||
@ -49,9 +37,9 @@ const App = () => {
|
||||
return (
|
||||
<Routes>
|
||||
<Route element={<MainLayout />}>
|
||||
{authState?.loggedIn && privateRouteList}
|
||||
{publicRoutesList}
|
||||
<Route path="*" element={<Navigate to={handleRootRedirect()} />} />
|
||||
{privateRouteList}
|
||||
<Route path="*" element={<Navigate to={'/'} />} />
|
||||
</Route>
|
||||
</Routes>
|
||||
)
|
||||
|
@ -1,16 +1,11 @@
|
||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import { Outlet, useNavigate, useSearchParams } from 'react-router-dom'
|
||||
|
||||
import { getPublicKey, nip19 } from 'nostr-tools'
|
||||
|
||||
import { init as initNostrLogin } from 'nostr-login'
|
||||
import { NostrLoginAuthOptions } from 'nostr-login/dist/types'
|
||||
|
||||
import { AppBar } from '../components/AppBar/AppBar'
|
||||
import { LoadingSpinner } from '../components/LoadingSpinner'
|
||||
|
||||
import { NostrController } from '../controllers'
|
||||
|
||||
import {
|
||||
useAppDispatch,
|
||||
useAppSelector,
|
||||
@ -19,7 +14,6 @@ import {
|
||||
useNDK,
|
||||
useNDKContext
|
||||
} from '../hooks'
|
||||
|
||||
import {
|
||||
restoreState,
|
||||
setUserProfile,
|
||||
@ -30,9 +24,7 @@ import {
|
||||
setUserRobotImage
|
||||
} from '../store/actions'
|
||||
import { LoginMethod } from '../store/auth/types'
|
||||
|
||||
import { getRoboHashPicture, loadState } from '../utils'
|
||||
|
||||
import styles from './style.module.scss'
|
||||
|
||||
export const MainLayout = () => {
|
||||
@ -53,29 +45,32 @@ export const MainLayout = () => {
|
||||
// Ref to track if `subscribeForSigits` has been called
|
||||
const hasSubscribed = useRef(false)
|
||||
|
||||
const navigateAfterLogin = (path: string) => {
|
||||
const callbackPath = searchParams.get('callbackPath')
|
||||
|
||||
if (callbackPath) {
|
||||
// base64 decoded path
|
||||
const path = atob(callbackPath)
|
||||
const navigateAfterLogin = useCallback(
|
||||
(path: string) => {
|
||||
const isCallback = window.location.hash.startsWith('#/?callbackPath=')
|
||||
if (isCallback) {
|
||||
const path = atob(window.location.hash.replace('#/?callbackPath=', ''))
|
||||
setSearchParams((prev) => {
|
||||
prev.delete('callbackPath')
|
||||
return prev
|
||||
})
|
||||
navigate(path)
|
||||
return
|
||||
}
|
||||
|
||||
navigate(path)
|
||||
}
|
||||
},
|
||||
[navigate, setSearchParams]
|
||||
)
|
||||
|
||||
const login = useCallback(async () => {
|
||||
try {
|
||||
dispatch(updateLoginMethod(LoginMethod.nostrLogin))
|
||||
|
||||
const nostrController = NostrController.getInstance()
|
||||
const pubkey = await nostrController.capturePublicKey()
|
||||
|
||||
const redirectPath = await authAndGetMetadataAndRelaysMap(pubkey)
|
||||
|
||||
if (redirectPath) {
|
||||
navigateAfterLogin(redirectPath)
|
||||
} catch (error) {
|
||||
console.error(`Error occured during login`, error)
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [dispatch])
|
||||
|
@ -1,7 +1,5 @@
|
||||
import { Box, Button } from '@mui/material'
|
||||
import { useEffect } from 'react'
|
||||
import { Outlet, useLocation } from 'react-router-dom'
|
||||
import { saveVisitedLink } from '../../utils'
|
||||
import { Outlet } from 'react-router-dom'
|
||||
import { CardComponent } from '../../components/Landing/CardComponent/CardComponent'
|
||||
import { Container } from '../../components/Container'
|
||||
import styles from './style.module.scss'
|
||||
@ -20,13 +18,19 @@ import {
|
||||
import { FontAwesomeIconStack } from '../../components/FontAwesomeIconStack'
|
||||
import { Footer } from '../../components/Footer/Footer'
|
||||
import { launch as launchNostrLoginDialog } from 'nostr-login'
|
||||
import { useDidMount } from '../../hooks'
|
||||
|
||||
export const LandingPage = () => {
|
||||
const location = useLocation()
|
||||
|
||||
const onSignInClick = async () => {
|
||||
launchNostrLoginDialog()
|
||||
}
|
||||
useDidMount(() => {
|
||||
const isCallback = window.location.hash.startsWith('#/?callbackPath=')
|
||||
// Open nostr login if detect callback
|
||||
if (isCallback) {
|
||||
onSignInClick()
|
||||
}
|
||||
})
|
||||
|
||||
const cards = [
|
||||
{
|
||||
@ -101,10 +105,6 @@ export const LandingPage = () => {
|
||||
}
|
||||
]
|
||||
|
||||
useEffect(() => {
|
||||
saveVisitedLink(location.pathname, location.search)
|
||||
}, [location])
|
||||
|
||||
return (
|
||||
<div className={styles.background}>
|
||||
<div
|
||||
|
21
src/routes/PrivateRoute.tsx
Normal file
21
src/routes/PrivateRoute.tsx
Normal file
@ -0,0 +1,21 @@
|
||||
import { Navigate, useLocation } from 'react-router-dom'
|
||||
import { useAppSelector } from '../hooks'
|
||||
import { appPublicRoutes } from '.'
|
||||
|
||||
export function PrivateRoute({ children }: { children: JSX.Element }) {
|
||||
const location = useLocation()
|
||||
const isLoggedIn = useAppSelector((state) => state.auth?.loggedIn)
|
||||
if (!isLoggedIn) {
|
||||
return (
|
||||
<Navigate
|
||||
to={{
|
||||
pathname: appPublicRoutes.landingPage,
|
||||
search: `?callbackPath=${btoa(location.pathname)}`
|
||||
}}
|
||||
replace
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
return children
|
||||
}
|
@ -11,6 +11,7 @@ import { RelaysPage } from '../pages/settings/relays'
|
||||
import { SettingsPage } from '../pages/settings/Settings'
|
||||
import { SignPage } from '../pages/sign'
|
||||
import { VerifyPage } from '../pages/verify'
|
||||
import { PrivateRoute } from './PrivateRoute'
|
||||
|
||||
/**
|
||||
* Helper type allows for extending react-router-dom's **RouteProps** with generic type
|
||||
@ -70,34 +71,66 @@ export const publicRoutes: PublicRouteProps[] = [
|
||||
export const privateRoutes = [
|
||||
{
|
||||
path: appPrivateRoutes.homePage,
|
||||
element: <HomePage />
|
||||
element: (
|
||||
<PrivateRoute>
|
||||
<HomePage />
|
||||
</PrivateRoute>
|
||||
)
|
||||
},
|
||||
{
|
||||
path: appPrivateRoutes.create,
|
||||
element: <CreatePage />
|
||||
element: (
|
||||
<PrivateRoute>
|
||||
<CreatePage />
|
||||
</PrivateRoute>
|
||||
)
|
||||
},
|
||||
{
|
||||
path: `${appPrivateRoutes.sign}/:id?`,
|
||||
element: <SignPage />
|
||||
element: (
|
||||
<PrivateRoute>
|
||||
<SignPage />
|
||||
</PrivateRoute>
|
||||
)
|
||||
},
|
||||
{
|
||||
path: appPrivateRoutes.settings,
|
||||
element: <SettingsPage />
|
||||
element: (
|
||||
<PrivateRoute>
|
||||
<SettingsPage />
|
||||
</PrivateRoute>
|
||||
)
|
||||
},
|
||||
{
|
||||
path: appPrivateRoutes.profileSettings,
|
||||
element: <ProfileSettingsPage />
|
||||
element: (
|
||||
<PrivateRoute>
|
||||
<ProfileSettingsPage />
|
||||
</PrivateRoute>
|
||||
)
|
||||
},
|
||||
{
|
||||
path: appPrivateRoutes.cacheSettings,
|
||||
element: <CacheSettingsPage />
|
||||
element: (
|
||||
<PrivateRoute>
|
||||
<CacheSettingsPage />
|
||||
</PrivateRoute>
|
||||
)
|
||||
},
|
||||
{
|
||||
path: appPrivateRoutes.relays,
|
||||
element: <RelaysPage />
|
||||
element: (
|
||||
<PrivateRoute>
|
||||
<RelaysPage />
|
||||
</PrivateRoute>
|
||||
)
|
||||
},
|
||||
{
|
||||
path: appPrivateRoutes.nostrLogin,
|
||||
element: <NostrLoginPage />
|
||||
element: (
|
||||
<PrivateRoute>
|
||||
<NostrLoginPage />
|
||||
</PrivateRoute>
|
||||
)
|
||||
}
|
||||
]
|
||||
|
@ -26,30 +26,6 @@ export const clearState = () => {
|
||||
localStorage.removeItem('state')
|
||||
}
|
||||
|
||||
export const saveVisitedLink = (pathname: string, search: string) => {
|
||||
localStorage.setItem(
|
||||
'visitedLink',
|
||||
JSON.stringify({
|
||||
pathname,
|
||||
search
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
export const getVisitedLink = () => {
|
||||
const visitedLink = localStorage.getItem('visitedLink')
|
||||
if (!visitedLink) return null
|
||||
|
||||
try {
|
||||
return JSON.parse(visitedLink) as {
|
||||
pathname: string
|
||||
search: string
|
||||
}
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
export const saveAuthToken = (token: string) => {
|
||||
localStorage.setItem('authToken', token)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user