@@ -2,6 +2,7 @@ import { createContext, useCallback, useEffect, useMemo, useReducer, useRef, use
22import { genUserIdDefault } from './utils.js' ;
33import { Result , db } from './database.js' ;
44import { DefaultEndScreen , renderDefaultErrorScreen } from './defaults.js' ;
5+ import { LoginOptions } from './login.js' ;
56import { createRoot } from 'react-dom/client' ;
67
78let errorHandlerEffectRun = false ;
@@ -14,6 +15,10 @@ interface ExperimentInternals {
1415 addResult : ( taskId : string , screenId : string , key : string , val : string ) => void ;
1516}
1617
18+ interface ExperimentControls {
19+ login : ( userId : string ) => void ;
20+ }
21+
1722const ExperimentInternalsDefault : ExperimentInternals = {
1823 currentTask : '' ,
1924 registerTask : ( ) => { throw new Error ( 'Experiment ancestor component not found.' ) ; } ,
@@ -22,10 +27,15 @@ const ExperimentInternalsDefault: ExperimentInternals = {
2227 addResult : ( ) => { throw new Error ( 'Experiment ancestor component not found.' ) ; } ,
2328} ;
2429
30+ const ExperimentControlsDefault : ExperimentControls = {
31+ login : ( ) => { throw new Error ( 'Experiment ancestor component not found.' ) ; } ,
32+ } ;
33+
2534const ExperimentInternalsContext = createContext ( ExperimentInternalsDefault ) ;
35+ const ExperimentControlsContext = createContext ( ExperimentControlsDefault ) ;
2636
2737type ExperimentProps = {
28- genUserId ?: ( ) => Promise < string > ;
38+ loginOptions ?: LoginOptions ;
2939 onResultAdded ?: ( result : Result ) => void ;
3040 endScreen ?: React . ReactNode ;
3141 useErrorHandling ?: boolean ;
@@ -34,10 +44,10 @@ type ExperimentProps = {
3444} ;
3545
3646function Experiment ( {
47+ loginOptions = { loginType : 'skip' , loginComponent : < > </ > } ,
3748 endScreen = < DefaultEndScreen /> ,
3849 useErrorHandling = false ,
3950 renderErrorScreen = renderDefaultErrorScreen ,
40- genUserId = genUserIdDefault ,
4151 ...otherProps
4252} : ExperimentProps ) {
4353 // valid user ID must not be empty
@@ -48,10 +58,10 @@ function Experiment({
4858 const [ , forceUpdate ] = useReducer ( x => x + 1 , 0 ) ;
4959
5060 useEffect ( ( ) => {
51- if ( userId == '' ) {
52- genUserId ( )
61+ if ( loginOptions . loginType == 'skip' && userId == '' ) {
62+ genUserIdDefault ( )
5363 . then ( ( id ) => {
54- setUserId ( id ) ;
64+ login ( id ) ;
5565 } ) ;
5666 }
5767 if ( useErrorHandling && ! errorHandlerEffectRun ) {
@@ -70,6 +80,7 @@ function Experiment({
7080 ) ;
7181 document . body . appendChild ( newDiv ) ;
7282 }
83+
7384 const registerTask = useCallback ( ( id : string ) => {
7485 // no duplicate IDs allowed
7586 if ( allTasksRef . current . includes ( id ) ) {
@@ -129,11 +140,32 @@ function Experiment({
129140 addResult,
130141 } ) , [ taskRef . current , registerTask , unregisterTask , advance , addResult ] ) ;
131142
143+ const login = useCallback ( ( userId : string ) => {
144+ setUserId ( userId ) ;
145+ } , [ setUserId ] ) ;
146+
147+ const experimentControls = useMemo ( ( ) => ( {
148+ login,
149+ } ) , [ login ] ) ;
150+
151+ let toDisplay ;
152+ if ( ended ) {
153+ toDisplay = endScreen ;
154+ }
155+ else if ( userId == '' ) {
156+ toDisplay = loginOptions . loginComponent ;
157+ }
158+ else {
159+ toDisplay = otherProps . children ;
160+ }
161+
132162 return (
133163 < ExperimentInternalsContext . Provider value = { experimentInternals } >
134- { ended ? endScreen : otherProps . children }
164+ < ExperimentControlsContext . Provider value = { experimentControls } >
165+ { toDisplay }
166+ </ ExperimentControlsContext . Provider >
135167 </ ExperimentInternalsContext . Provider >
136168 ) ;
137169} ;
138170
139- export { ExperimentInternalsContext , ExperimentProps , Experiment } ;
171+ export { ExperimentInternalsContext , ExperimentControlsContext , ExperimentProps , Experiment } ;
0 commit comments