Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit81489f8

Browse files
committed
allow levels with no steps
1 parent367c98c commit81489f8

File tree

10 files changed

+91
-73
lines changed

10 files changed

+91
-73
lines changed

‎src/channel/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@ class Channel implements Channel {
7070
this.send({type:'START_NEW_TUTORIAL'})
7171
return
7272
}
73-
console.log('send LOAD_STORED_TUTORIAL')
7473
// communicate to client the tutorial & stepProgress state
7574
this.send({type:'LOAD_STORED_TUTORIAL',payload:{ tutorial, progress, position}})
7675

‎src/channel/state/Position.ts

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import * as G from 'typings/graphql'
33

44
constdefaultValue:CR.Position={
55
levelId:'',
6-
stepId:'',
6+
stepId:null,
77
}
88

99
// position
@@ -42,18 +42,25 @@ class Position {
4242

4343
// get step
4444
constcurrentLevel:G.Level=levels[lastLevelIndex]
45-
const{ steps}=currentLevel
46-
constlastStepIndex:number|undefined=steps.findIndex((s:G.Step)=>!progress.steps[s.id])
47-
if(lastStepIndex>=steps.length){
48-
thrownewError('Error setting progress step')
45+
letcurrentStepId:string|null
46+
if(!currentLevel.steps.length){
47+
// no steps available for level
48+
currentStepId=null
49+
}else{
50+
// find current step id
51+
const{ steps}=currentLevel
52+
constlastStepIndex:number|undefined=steps.findIndex((s:G.Step)=>!progress.steps[s.id])
53+
if(lastStepIndex>=steps.length){
54+
thrownewError('Error setting progress step')
55+
}
56+
// handle position when last step is complete but "continue" not yet selected
57+
constadjustedLastStepIndex=lastStepIndex===-1 ?steps.length-1 :lastStepIndex
58+
currentStepId=steps[adjustedLastStepIndex].id
4959
}
50-
// handle position when last step is complete but "continue" not yet selected
51-
constadjustedLastStepIndex=lastStepIndex===-1 ?steps.length-1 :lastStepIndex
52-
constcurrentStep:G.Step=steps[adjustedLastStepIndex]
5360

5461
this.value={
5562
levelId:currentLevel.id,
56-
stepId:currentStep.id,
63+
stepId:currentStepId,
5764
}
5865

5966
returnthis.value

‎typings/index.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export interface StepProgress {
1919
// current tutorial position
2020
exportinterfacePosition{
2121
levelId:string
22-
stepId:string
22+
stepId:string|null
2323
complete?:boolean
2424
}
2525

‎web-app/src/components/Router/index.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { createMachine } from '../../services/state/machine'
44
import{useMachine}from'../../services/xstate-react'
55
importRoutefrom'./Route'
66
importonErrorfrom'../../services/sentry/onError'
7+
import{LOG_STATE}from'../../environment'
78

89
interfaceOutput{
910
context:T.MachineContext
@@ -20,6 +21,10 @@ const editor = acquireVsCodeApi()
2021
constuseRouter=():Output=>{
2122
const[state,send]=useMachine<T.MachineContext,any>(createMachine({editorSend:editor.postMessage}))
2223

24+
if(LOG_STATE){
25+
console.log(JSON.stringify(state.value))
26+
}
27+
2328
// event bus listener
2429
React.useEffect(()=>{
2530
constlistener='message'

‎web-app/src/environment.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ export const DEBUG: boolean = (process.env.REACT_APP_DEBUG || '').toLowerCase()
1212
exportconstVERSION:string=process.env.VERSION||'unknown'
1313
exportconstNODE_ENV:string=process.env.NODE_ENV||'production'
1414
exportconstAUTH_TOKEN:string|null=process.env.AUTH_TOKEN||null
15+
exportconstLOG_STATE:boolean=(process.env.LOG_STATE||'').toLowerCase()==='true'

‎web-app/src/services/selectors/position.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ import * as tutorial from './tutorial'
55

66
exportconstdefaultPosition=()=>({
77
levelId:'',
8-
stepId:'',
8+
stepId:null,
99
})
1010

1111
exportconstinitialPosition=createSelector(tutorial.currentVersion,(version:G.TutorialVersion)=>{
1212
constlevel=version.data.levels[0]
1313
constposition:CR.Position={
1414
levelId:level.id,
15-
stepId:level.steps.length ?level.steps[0].id :'',
15+
stepId:level.steps.length ?level.steps[0].id :null,
1616
}
1717
returnposition
1818
})

‎web-app/src/services/selectors/tutorial.ts

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,9 @@ export const currentLevel = (context: MachineContext): G.Level =>
4141
},
4242
)(context)
4343

44-
exportconstcurrentStep=(context:MachineContext):G.Step=>
45-
createSelector(
46-
currentLevel,
47-
(level:G.Level):G.Step=>{
48-
conststeps:G.Step[]=level.steps
49-
letstep:G.Step|undefined=steps.find((s:G.Step)=>s.id===context.position.stepId)
50-
if(!step){
51-
step={id:'',content:'no steps for level'}
52-
}
53-
returnstep
54-
},
55-
)(context)
44+
exportconstcurrentStep=(context:MachineContext):G.Step|null=>
45+
createSelector(currentLevel,(level:G.Level):G.Step|null=>{
46+
conststeps:G.Step[]=level.steps
47+
conststep:G.Step|null=steps.find((s:G.Step)=>s.id===context.position.stepId)||null
48+
returnstep
49+
})(context)

‎web-app/src/services/state/actions/context.ts

Lines changed: 43 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ const contextActions: ActionFunctionMap<T.MachineContext, T.MachineEvent> = {
1717
//@ts-ignore
1818
storeContinuedTutorial:assign({
1919
tutorial:(context:T.MachineContext,event:T.MachineEvent)=>{
20-
console.log('storeContinuedTutorial')
2120
returnevent.payload.tutorial
2221
},
2322
progress:(context:T.MachineContext,event:T.MachineEvent)=>{
@@ -132,25 +131,27 @@ const contextActions: ActionFunctionMap<T.MachineContext, T.MachineEvent> = {
132131

133132
conststeps:G.Step[]=level.steps
134133

135-
conststepIndex=steps.findIndex((s:G.Step)=>s.id===position.stepId)
136-
conststepComplete=progress.steps[position.stepId]
137-
constfinalStep=stepIndex>-1&&stepIndex===steps.length-1
138-
consthasNextStep=!finalStep&&!stepComplete
139-
140-
// NEXT STEP
141-
if(hasNextStep){
142-
constnextPosition={ ...position,stepId:steps[stepIndex+1].id}
143-
return{type:'NEXT_STEP',payload:{position:nextPosition}}
144-
}
134+
if(steps.length&&position.stepId){
135+
conststepIndex=steps.findIndex((s:G.Step)=>s.id===position.stepId)
136+
conststepComplete=progress.steps[position.stepId]
137+
constfinalStep=stepIndex>-1&&stepIndex===steps.length-1
138+
consthasNextStep=!finalStep&&!stepComplete
145139

146-
// has next level?
140+
// NEXT STEP
141+
if(hasNextStep){
142+
constnextPosition={ ...position,stepId:steps[stepIndex+1].id}
143+
return{type:'NEXT_STEP',payload:{position:nextPosition}}
144+
}
147145

148-
if(!context.tutorial){
149-
consterror=newError('Tutorial not found')
150-
onError(error)
151-
throwerror
146+
// has next level?
147+
if(!context.tutorial){
148+
consterror=newError('Tutorial not found')
149+
onError(error)
150+
throwerror
151+
}
152152
}
153153

154+
//@ts-ignore
154155
constlevels=context.tutorial.version.data.levels||[]
155156
constlevelIndex=levels.findIndex((l:G.Level)=>l.id===position.levelId)
156157
constfinalLevel=levelIndex>-1&&levelIndex===levels.length-1
@@ -177,26 +178,27 @@ const contextActions: ActionFunctionMap<T.MachineContext, T.MachineEvent> = {
177178
constlevel:G.Level=selectors.currentLevel(context)
178179

179180
const{ steps}=level
180-
// TODO verify not -1
181-
conststepIndex=steps.findIndex((s:G.Step)=>s.id===position.stepId)
182-
constfinalStep=stepIndex===steps.length-1
183-
conststepComplete=progress.steps[position.stepId]
184-
// not final step, or final step but not complete
185-
consthasNextStep=!finalStep||!stepComplete
186-
187-
if(hasNextStep){
188-
constnextStep=steps[stepIndex+1]
189-
return{
190-
type:'LOAD_NEXT_STEP',
191-
payload:{
192-
step:nextStep,
193-
},
194-
}
195-
}else{
196-
return{
197-
type:'LEVEL_COMPLETE',
181+
182+
if(steps.length&&position.stepId){
183+
conststepIndex=steps.findIndex((s:G.Step)=>s.id===position.stepId)
184+
constfinalStep=stepIndex===steps.length-1
185+
conststepComplete=progress.steps[position.stepId]
186+
// not final step, or final step but not complete
187+
consthasNextStep=!finalStep||!stepComplete
188+
189+
if(hasNextStep){
190+
constnextStep=steps[stepIndex+1]
191+
return{
192+
type:'LOAD_NEXT_STEP',
193+
payload:{
194+
step:nextStep,
195+
},
196+
}
198197
}
199198
}
199+
return{
200+
type:'LEVEL_COMPLETE',
201+
}
200202
},
201203
),
202204
//@ts-ignore
@@ -223,6 +225,13 @@ const contextActions: ActionFunctionMap<T.MachineContext, T.MachineEvent> = {
223225
returnmessage
224226
},
225227
}),
228+
//@ts-ignore
229+
checkEmptySteps:send((context:T.MachineContext)=>{
230+
// no step id indicates no steps to complete
231+
return{
232+
type:context.position.stepId===null ?'START_COMPLETED_LEVEL' :'START_LEVEL',
233+
}
234+
}),
226235
}
227236

228237
exportdefaultcontextActions

‎web-app/src/services/state/actions/editor.ts

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ export default (editorSend: any) => ({
4444
}
4545
},
4646
loadStep(context:CR.MachineContext):void{
47-
conststep:G.Step=selectors.currentStep(context)
48-
if(step.setup){
47+
conststep:G.Step|null=selectors.currentStep(context)
48+
if(step&&step.setup){
4949
// load step actions
5050
editorSend({
5151
type:'SETUP_ACTIONS',
@@ -57,15 +57,17 @@ export default (editorSend: any) => ({
5757
}
5858
},
5959
editorLoadSolution(context:CR.MachineContext):void{
60-
conststep:G.Step=selectors.currentStep(context)
60+
conststep:G.Step|null=selectors.currentStep(context)
6161
// tell editor to load solution commit
62-
editorSend({
63-
type:'SOLUTION_ACTIONS',
64-
payload:{
65-
stepId:step.id,
66-
...step.solution,
67-
},
68-
})
62+
if(step&&step.solution){
63+
editorSend({
64+
type:'SOLUTION_ACTIONS',
65+
payload:{
66+
stepId:step.id,
67+
...step.solution,
68+
},
69+
})
70+
}
6971
},
7072
clearStorage():void{
7173
editorSend({type:'TUTORIAL_CLEAR'})

‎web-app/src/services/state/machine.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export const createMachine = (options: any) => {
2121
error:null,
2222
env:{machineId:'',sessionId:'',token:''},
2323
tutorial:null,
24-
position:{levelId:'',stepId:''},
24+
position:{levelId:'',stepId:null},
2525
progress:{
2626
levels:{},
2727
steps:{},
@@ -188,9 +188,10 @@ export const createMachine = (options: any) => {
188188
initial:'Load',
189189
states:{
190190
Load:{
191-
onEntry:['loadLevel','loadStep'],
192-
after:{
193-
0:'Normal',
191+
onEntry:['loadLevel','loadStep','checkEmptySteps'],
192+
on:{
193+
START_LEVEL:'Normal',
194+
START_COMPLETED_LEVEL:'LevelComplete',
194195
},
195196
},
196197
Normal:{

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp