11import { css , type Handle } from 'remix/ui'
2- import { clientRoutes } from './routes/index.tsx'
2+ import { routes } from '#server/routes.ts'
3+ import { clientRouteLoaders , clientRoutes } from './routes/index.tsx'
34import {
45 getPathname ,
56 listenToRouterNavigation ,
@@ -10,14 +11,21 @@ import {
1011 type SessionInfo ,
1112 type SessionStatus ,
1213} from './session.ts'
14+ import { SessionProvider } from './session-context.tsx'
1315import { buildAuthLink } from './auth-links.ts'
1416import { colors , mq , spacing , typography } from './styles/tokens.ts'
15- export function App ( handle : Handle ) {
16- let session : SessionInfo | null = null
17- let sessionStatus : SessionStatus = 'idle'
17+
18+ type AppProps = {
19+ embeddedSession ?: SessionInfo | null
20+ notFound ?: boolean
21+ }
22+
23+ export function App ( handle : Handle < AppProps > ) {
24+ let session : SessionInfo | null = handle . props ?. embeddedSession ?? null
25+ let sessionStatus : SessionStatus = 'ready'
1826 let sessionRefreshInFlight = false
1927 let sessionRefreshQueued = false
20- let currentPathname = getPathname ( )
28+ let currentPathname = getPathname ( handle )
2129 function queueSessionRefresh ( ) {
2230 sessionRefreshQueued = true
2331 if ( sessionRefreshInFlight ) return
@@ -29,9 +37,22 @@ export function App(handle: Handle) {
2937 sessionRefreshQueued = false
3038 sessionRefreshInFlight = true
3139 handle . queueTask ( async ( signal ) => {
32- const nextSession = await fetchSessionInfo ( signal )
40+ let nextSession : SessionInfo | null = null
41+ try {
42+ nextSession = await fetchSessionInfo ( signal )
43+ } catch ( error ) {
44+ sessionRefreshInFlight = false
45+ if ( signal . aborted ) return
46+ console . error ( 'Session refresh failed' , error )
47+ sessionStatus = 'ready'
48+ handle . update ( )
49+ return
50+ }
3351 sessionRefreshInFlight = false
34- if ( signal . aborted ) return
52+ if ( signal . aborted ) {
53+ if ( sessionRefreshQueued ) queueSessionRefresh ( )
54+ return
55+ }
3556 session = nextSession
3657 sessionStatus = 'ready'
3758 handle . update ( )
@@ -43,11 +64,13 @@ export function App(handle: Handle) {
4364 handle . update ( )
4465 }
4566 }
46- handle . queueTask ( ( ) => {
47- queueSessionRefresh ( )
48- } )
67+ if ( typeof window !== 'undefined' ) {
68+ handle . queueTask ( ( ) => {
69+ queueSessionRefresh ( )
70+ } )
71+ }
4972 listenToRouterNavigation ( handle , ( ) => {
50- currentPathname = getPathname ( )
73+ currentPathname = getPathname ( handle )
5174 queueSessionRefresh ( )
5275 handle . update ( )
5376 } )
@@ -85,11 +108,12 @@ export function App(handle: Handle) {
85108 const isLoggedIn = isSessionReady && Boolean ( sessionEmail )
86109 const showAuthLinks = isSessionReady && ! isLoggedIn
87110 const oauthRedirectTo =
88- typeof window !== 'undefined' && currentPathname === '/oauth/authorize'
111+ typeof window !== 'undefined' &&
112+ currentPathname === routes . oauthAuthorize . href ( )
89113 ? `${ currentPathname } ${ window . location . search } `
90114 : null
91- const loginHref = buildAuthLink ( '/ login' , oauthRedirectTo )
92- const signupHref = buildAuthLink ( '/ signup' , oauthRedirectTo )
115+ const loginHref = buildAuthLink ( routes . login . href ( ) , oauthRedirectTo )
116+ const signupHref = buildAuthLink ( routes . signup . href ( ) , oauthRedirectTo )
93117 return (
94118 < main
95119 mix = { [
@@ -126,7 +150,11 @@ export function App(handle: Handle) {
126150 } ) ,
127151 ] }
128152 >
129- < a href = "/" aria-label = "Home" mix = { [ css ( navHomeLinkCss ) ] } >
153+ < a
154+ href = { routes . home . href ( ) }
155+ aria-label = "Home"
156+ mix = { [ css ( navHomeLinkCss ) ] }
157+ >
130158 < img
131159 src = "/logo.png"
132160 alt = ""
@@ -153,42 +181,50 @@ export function App(handle: Handle) {
153181 ) : null }
154182 { isLoggedIn ? (
155183 < >
156- < a href = "/ chat" mix = { [ css ( navLinkCss ) ] } >
184+ < a href = { routes . chat . href ( ) } mix = { [ css ( navLinkCss ) ] } >
157185 Chat
158186 </ a >
159- < a href = "/ account" mix = { [ css ( navLinkCss ) ] } >
187+ < a href = { routes . account . href ( ) } mix = { [ css ( navLinkCss ) ] } >
160188 { sessionEmail }
161189 </ a >
162- < form method = "post" action = "/logout" mix = { [ css ( { margin : 0 } ) ] } >
190+ < form
191+ method = "post"
192+ action = { routes . logout . href ( ) }
193+ mix = { [ css ( { margin : 0 } ) ] }
194+ >
163195 < button type = "submit" mix = { [ css ( logOutButtonCss ) ] } >
164196 Log out
165197 </ button >
166198 </ form >
167199 </ >
168200 ) : null }
169201 </ nav >
170- < Router
171- routes = { clientRoutes }
172- fallback = {
173- < section >
174- < h2
175- mix = { [
176- css ( {
177- fontSize : typography . fontSize . lg ,
178- fontWeight : typography . fontWeight . semibold ,
179- marginBottom : spacing . sm ,
180- color : colors . text ,
181- } ) ,
182- ] }
183- >
184- Not Found
185- </ h2 >
186- < p mix = { [ css ( { color : colors . textMuted } ) ] } >
187- That route does not exist.
188- </ p >
189- </ section >
190- }
191- />
202+ < SessionProvider session = { session } >
203+ < Router
204+ loaders = { clientRouteLoaders }
205+ routes = { clientRoutes }
206+ notFound = { handle . props ?. notFound === true }
207+ fallback = {
208+ < section >
209+ < h2
210+ mix = { [
211+ css ( {
212+ fontSize : typography . fontSize . lg ,
213+ fontWeight : typography . fontWeight . semibold ,
214+ marginBottom : spacing . sm ,
215+ color : colors . text ,
216+ } ) ,
217+ ] }
218+ >
219+ Not Found
220+ </ h2 >
221+ < p mix = { [ css ( { color : colors . textMuted } ) ] } >
222+ That route does not exist.
223+ </ p >
224+ </ section >
225+ }
226+ />
227+ </ SessionProvider >
192228 </ main >
193229 )
194230 }
0 commit comments