11import { type Handle } from 'remix/component'
22import { navigate } from './client-router.tsx'
33import { Counter } from './counter.tsx'
4+ import {
5+ fetchSessionInfo ,
6+ type SessionInfo ,
7+ type SessionStatus ,
8+ } from './session.ts'
49import {
510 colors ,
611 radius ,
@@ -355,6 +360,8 @@ function OAuthAuthorizeForm(handle: Handle) {
355360 let message : OAuthAuthorizeMessage | null = null
356361 let submitting = false
357362 let lastSearch = ''
363+ let session : SessionInfo | null = null
364+ let sessionStatus : SessionStatus = 'idle'
358365
359366 function setMessage ( next : OAuthAuthorizeMessage | null ) {
360367 message = next
@@ -421,6 +428,16 @@ function OAuthAuthorizeForm(handle: Handle) {
421428 }
422429 }
423430
431+ async function loadSession ( ) {
432+ if ( sessionStatus !== 'idle' ) return
433+ sessionStatus = 'loading'
434+
435+ session = await fetchSessionInfo ( )
436+
437+ sessionStatus = 'ready'
438+ handle . update ( )
439+ }
440+
424441 async function submitDecision (
425442 decision : 'approve' | 'deny' ,
426443 form ?: HTMLFormElement ,
@@ -487,7 +504,11 @@ function OAuthAuthorizeForm(handle: Handle) {
487504 async function handleSubmit ( event : SubmitEvent ) {
488505 event . preventDefault ( )
489506 if ( ! ( event . currentTarget instanceof HTMLFormElement ) ) return
490- await submitDecision ( 'approve' , event . currentTarget )
507+ const hasSession = Boolean ( session ?. email )
508+ await submitDecision (
509+ 'approve' ,
510+ hasSession ? undefined : event . currentTarget ,
511+ )
491512 }
492513
493514 return ( ) => {
@@ -497,12 +518,26 @@ function OAuthAuthorizeForm(handle: Handle) {
497518 lastSearch = currentSearch
498519 void loadInfo ( )
499520 }
521+ if ( sessionStatus === 'idle' ) {
522+ void loadSession ( )
523+ }
500524
501525 const clientLabel = info ?. client ?. name ?? 'Unknown client'
502526 const scopes = info ?. scopes ?? [ ]
503527 const scopeLabel =
504528 scopes . length > 0 ? scopes . join ( ', ' ) : 'No scopes requested.'
505- const actionsDisabled = status !== 'ready' || submitting
529+ const sessionEmail = session ?. email ?? ''
530+ const isSessionReady = sessionStatus === 'ready'
531+ const isSessionLoading =
532+ sessionStatus === 'loading' || sessionStatus === 'idle'
533+ const isLoggedIn = isSessionReady && Boolean ( sessionEmail )
534+ const actionsDisabled = status !== 'ready' || submitting || isSessionLoading
535+ const formReady = status === 'ready' && ! isSessionLoading
536+ const authorizeLabel = submitting
537+ ? 'Submitting...'
538+ : isLoggedIn
539+ ? 'Approve connection'
540+ : 'Authorize'
506541
507542 return (
508543 < section
@@ -549,6 +584,34 @@ function OAuthAuthorizeForm(handle: Handle) {
549584 </ p >
550585 < p css = { { margin : 0 , color : colors . textMuted } } > { scopeLabel } </ p >
551586 </ section >
587+ { isSessionLoading ? (
588+ < p css = { { color : colors . textMuted } } > Checking your session…</ p >
589+ ) : null }
590+ { isLoggedIn ? (
591+ < section
592+ css = { {
593+ padding : spacing . md ,
594+ borderRadius : radius . md ,
595+ border : `1px solid ${ colors . border } ` ,
596+ backgroundColor : colors . surface ,
597+ display : 'grid' ,
598+ gap : spacing . xs ,
599+ } }
600+ >
601+ < p
602+ css = { {
603+ margin : 0 ,
604+ fontWeight : typography . fontWeight . medium ,
605+ color : colors . text ,
606+ } }
607+ >
608+ Signed in as { sessionEmail }
609+ </ p >
610+ < p css = { { margin : 0 , color : colors . textMuted } } >
611+ Approve to continue with this account.
612+ </ p >
613+ </ section >
614+ ) : null }
552615 { status === 'loading' ? (
553616 < p css = { { color : colors . textMuted } } >
554617 Loading authorization details…
@@ -574,62 +637,66 @@ function OAuthAuthorizeForm(handle: Handle) {
574637 border : `1px solid ${ colors . border } ` ,
575638 backgroundColor : colors . surface ,
576639 boxShadow : shadows . sm ,
577- opacity : status === 'ready' ? 1 : 0.7 ,
640+ opacity : formReady ? 1 : 0.7 ,
578641 } }
579642 on = { { submit : handleSubmit } }
580643 >
581- < label css = { { display : 'grid' , gap : spacing . xs } } >
582- < span
583- css = { {
584- color : colors . text ,
585- fontWeight : typography . fontWeight . medium ,
586- fontSize : typography . fontSize . sm ,
587- } }
588- >
589- Email
590- </ span >
591- < input
592- type = "email"
593- name = "email"
594- required
595- autoComplete = "email"
596- placeholder = "you@example.com"
597- disabled = { actionsDisabled }
598- css = { {
599- padding : spacing . sm ,
600- borderRadius : radius . md ,
601- border : `1px solid ${ colors . border } ` ,
602- fontSize : typography . fontSize . base ,
603- fontFamily : typography . fontFamily ,
604- } }
605- />
606- </ label >
607- < label css = { { display : 'grid' , gap : spacing . xs } } >
608- < span
609- css = { {
610- color : colors . text ,
611- fontWeight : typography . fontWeight . medium ,
612- fontSize : typography . fontSize . sm ,
613- } }
614- >
615- Password
616- </ span >
617- < input
618- type = "password"
619- name = "password"
620- required
621- autoComplete = "current-password"
622- placeholder = "Enter your password"
623- disabled = { actionsDisabled }
624- css = { {
625- padding : spacing . sm ,
626- borderRadius : radius . md ,
627- border : `1px solid ${ colors . border } ` ,
628- fontSize : typography . fontSize . base ,
629- fontFamily : typography . fontFamily ,
630- } }
631- />
632- </ label >
644+ { ! isLoggedIn && isSessionReady ? (
645+ < >
646+ < label css = { { display : 'grid' , gap : spacing . xs } } >
647+ < span
648+ css = { {
649+ color : colors . text ,
650+ fontWeight : typography . fontWeight . medium ,
651+ fontSize : typography . fontSize . sm ,
652+ } }
653+ >
654+ Email
655+ </ span >
656+ < input
657+ type = "email"
658+ name = "email"
659+ required
660+ autoComplete = "email"
661+ placeholder = "you@example.com"
662+ disabled = { actionsDisabled }
663+ css = { {
664+ padding : spacing . sm ,
665+ borderRadius : radius . md ,
666+ border : `1px solid ${ colors . border } ` ,
667+ fontSize : typography . fontSize . base ,
668+ fontFamily : typography . fontFamily ,
669+ } }
670+ />
671+ </ label >
672+ < label css = { { display : 'grid' , gap : spacing . xs } } >
673+ < span
674+ css = { {
675+ color : colors . text ,
676+ fontWeight : typography . fontWeight . medium ,
677+ fontSize : typography . fontSize . sm ,
678+ } }
679+ >
680+ Password
681+ </ span >
682+ < input
683+ type = "password"
684+ name = "password"
685+ required
686+ autoComplete = "current-password"
687+ placeholder = "Enter your password"
688+ disabled = { actionsDisabled }
689+ css = { {
690+ padding : spacing . sm ,
691+ borderRadius : radius . md ,
692+ border : `1px solid ${ colors . border } ` ,
693+ fontSize : typography . fontSize . base ,
694+ fontFamily : typography . fontFamily ,
695+ } }
696+ />
697+ </ label >
698+ </ >
699+ ) : null }
633700 < div css = { { display : 'flex' , gap : spacing . sm , flexWrap : 'wrap' } } >
634701 < button
635702 type = "submit"
@@ -646,7 +713,7 @@ function OAuthAuthorizeForm(handle: Handle) {
646713 opacity : actionsDisabled ? 0.7 : 1 ,
647714 } }
648715 >
649- { submitting ? 'Submitting...' : 'Authorize' }
716+ { authorizeLabel }
650717 </ button >
651718 < button
652719 type = "button"
0 commit comments