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

Commit1b99222

Browse files
committed
continue tutorial progress
1 parent17a71b7 commit1b99222

File tree

11 files changed

+147
-111
lines changed

11 files changed

+147
-111
lines changed

‎src/Channel.ts

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import*asCRfrom'typings'
22
import*asvscodefrom'vscode'
3-
import*asstoragefrom'./services/storage'
43

54
importtutorialConfigfrom'./actions/tutorialConfig'
65
importsetupActionsfrom'./actions/setupActions'
@@ -11,10 +10,20 @@ interface Channel {
1110
send(action:CR.Action):Promise<void>
1211
}
1312

13+
interfaceChannelProps{
14+
postMessage:(action:CR.Action)=>Thenable<boolean>
15+
storage:{
16+
tutorial:any
17+
stepProgress:any
18+
}
19+
}
20+
1421
classChannelimplementsChannel{
1522
privatepostMessage:(action:CR.Action)=>Thenable<boolean>
16-
constructor(postMessage:(action:CR.Action)=>Thenable<boolean>){
23+
privatestorage:any
24+
constructor({postMessage, storage}:ChannelProps){
1725
this.postMessage=postMessage
26+
this.storage=storage
1827
}
1928

2029
// receive from webview
@@ -24,19 +33,29 @@ class Channel implements Channel {
2433
switch(actionType){
2534
// continue from tutorial from local storage
2635
case'TUTORIAL_LOAD_STORED':
27-
consttutorial=storage.tutorial.get()
28-
conststepProgress=storage.stepProgress.get()
29-
this.send({type:'TUTORIAL_LOADED',payload:{tutorial, stepProgress}})
36+
consttutorial=this.storage.tutorial.get()
37+
conststepProgress=this.storage.stepProgress.get()
38+
39+
console.log('looking at stored')
40+
console.log(JSON.stringify(tutorial))
41+
console.log(JSON.stringify(stepProgress))
42+
43+
if(tutorial&&tutorial.id){
44+
this.send({type:'CONTINUE_TUTORIAL',payload:{tutorial, stepProgress}})
45+
}else{
46+
this.send({type:'NEW_TUTORIAL'})
47+
}
48+
3049
return
3150
// clear tutorial local storage
3251
case'TUTORIAL_CLEAR':
33-
storage.tutorial.set(null)
34-
storage.stepProgress.set({})
52+
this.storage.tutorial.set(null)
53+
this.storage.stepProgress.set({})
3554
return
3655
// configure test runner, language, git
3756
case'TUTORIAL_CONFIG':
3857
tutorialConfig(action.payload)
39-
storage.tutorial.set(action.payload)
58+
this.storage.tutorial.set(action.payload)
4059
return
4160
// run unit tests on step
4261
case'TEST_RUN':

‎src/editor/ReactWebView.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,14 @@ const getNonce = (): string => {
1212
returntext
1313
}
1414

15+
interfaceReactWebViewProps{
16+
extensionPath:string
17+
storage:{
18+
tutorial:any
19+
stepProgress:any
20+
}
21+
}
22+
1523

1624
// Manages webview panel
1725
classReactWebView{
@@ -24,7 +32,7 @@ class ReactWebView {
2432
privatedisposables:vscode.Disposable[]=[]
2533
privatechannel:Channel
2634

27-
publicconstructor(extensionPath:string){
35+
publicconstructor({extensionPath, storage}:ReactWebViewProps){
2836
this.extensionPath=extensionPath
2937

3038
// Create and show a new webview panel
@@ -37,8 +45,11 @@ class ReactWebView {
3745
// This happens when the user closes the panel or when the panel is closed programmatically
3846
this.panel.onDidDispose(this.dispose,this,this.disposables)
3947

40-
this.channel=newChannel((action:Action):Thenable<boolean>=>{
41-
returnthis.panel.webview.postMessage(action)
48+
this.channel=newChannel({
49+
storage,
50+
postMessage:(action:Action):Thenable<boolean>=>{
51+
returnthis.panel.webview.postMessage(action)
52+
}
4253
})
4354
// Handle messages from the webview
4455
constreceive=this.channel.receive

‎src/editor/commands.ts

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
import*asGfrom'typings/graphql'
12
import*asvscodefrom'vscode'
2-
import*asstoragefrom'../services/storage'
3+
importStoragefrom'../services/storage'
34
importReactWebViewfrom'./ReactWebView'
45
importrunTestfrom'../actions/runTest'
56
import{isEmptyWorkspace}from'./workspace'
@@ -19,6 +20,18 @@ export const createCommands = ({vscodeExt}: CreateCommandProps) => {
1920
// React panel webview
2021
letwebview:any
2122
letcurrentStepId=''
23+
24+
consttutorial=newStorage<G.Tutorial|null>({
25+
key:'coderoad:tutorial',
26+
storage:vscodeExt.workspaceState
27+
})
28+
29+
conststepProgress=newStorage<{[stepId:string]:boolean}>({
30+
key:'coderoad:progress',
31+
storage:vscodeExt.workspaceState
32+
})
33+
34+
2235
return{
2336
// initialize
2437
[COMMANDS.START]:async()=>{
@@ -39,7 +52,13 @@ export const createCommands = ({vscodeExt}: CreateCommandProps) => {
3952
}
4053

4154
// activate machine
42-
webview=newReactWebView(vscodeExt.extensionPath)
55+
webview=newReactWebView({
56+
extensionPath:vscodeExt.extensionPath,
57+
storage:{
58+
tutorial,
59+
stepProgress
60+
}
61+
})
4362
},
4463
// open React webview
4564
[COMMANDS.OPEN_WEBVIEW]:(column:number=vscode.ViewColumn.Two)=>{
@@ -68,7 +87,7 @@ export const createCommands = ({vscodeExt}: CreateCommandProps) => {
6887
// send test pass message back to client
6988
webview.send({type:'TEST_PASS', payload})
7089
// update local storage stepProgress
71-
storage.stepProgress.update({
90+
stepProgress.update({
7291
[payload.stepId]:true
7392
})
7493
vscode.window.showInformationMessage('PASS')

‎src/editor/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ class Editor {
1616
publicactivate=(vscodeExt:vscode.ExtensionContext):void=>{
1717
console.log('ACTIVATE!')
1818
this.vscodeExt=vscodeExt
19+
1920
// commands
2021
this.activateCommands()
2122

‎src/services/storage/index.ts

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,28 @@
1-
import*asGfrom'typings/graphql'
1+
import*asvscodefrom'vscode'
22

3-
// localStorage not available on client
3+
//NOTE:localStorage not available on client
44
// must be stored in editor
5+
// https://github.com/Microsoft/vscode/issues/52246
56

7+
// storage is unfortunately bound to the vscode extension context
8+
// forcing it to be passed in through activation and down to other tools
69
classStorage<T>{
710
privatekey:string
8-
// TODO: replace somehow with localStorage
9-
// window.localStorage not working inside of vscode
10-
privatestorage=localStorage
11-
constructor({key, value}:{key:string,value:T}){
11+
privatestorage:vscode.Memento
12+
constructor({key, storage}:{key:string,storage:vscode.Memento}){
13+
this.storage=storage
1214
this.key=key
13-
this.set(value)
1415
}
1516
publicget=async():Promise<T|null>=>{
16-
constvalue=awaitthis.storage.getItem(this.key)
17+
constvalue:string|undefined=awaitthis.storage.get(this.key)
1718
if(value){
1819
returnJSON.parse(value)
1920
}
2021
returnnull
2122
}
2223
publicset=(value:T):void=>{
2324
conststringValue=JSON.stringify(value)
24-
this.storage.setItem(this.key,stringValue)
25+
this.storage.update(this.key,stringValue)
2526
}
2627
publicupdate=async(value:T):Promise<void>=>{
2728
constcurrent=awaitthis.get()
@@ -32,11 +33,4 @@ class Storage<T> {
3233
}
3334
}
3435

35-
exportconsttutorial=newStorage<G.Tutorial|null>({
36-
key:'coderoad:tutorial',
37-
value:null
38-
})
39-
exportconststepProgress=newStorage<{[stepId:string]:boolean}>({
40-
key:'coderoad:progress',
41-
value:{}
42-
})
36+
exportdefaultStorage

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const Workspace = ({ children }: Props) => {
1515
// solution for windows getting off size
1616
React.useEffect(()=>{
1717
setDimensions(resize())
18-
},[window.innerHeight,window.innerHeight])
18+
},[])
1919

2020
conststyles={
2121
page:{

‎web-app/src/services/channel/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@ class Channel {
3737
this.machineSend('TUTORIAL_LOADED')
3838
console.log('send action to state machine')
3939
return
40+
case'NEW_TUTORIAL':
41+
this.machineSend(action)
42+
return
43+
case'CONTINUE_TUTORIAL':
44+
this.machineSend(action)
45+
return
4046
case'TEST_PASS':
4147
// { type: 'TEST_PASS', payload: { stepId: string }}
4248
this.machineSend(action)

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

Lines changed: 53 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,72 @@
11
import{assign,send}from'xstate'
22
import*asGfrom'typings/graphql'
33
import*asCRfrom'typings'
4-
import*asstoragefrom'../storage'
54
import*asselectorsfrom'../../selectors'
65

76
exportdefault{
7+
continueTutorial:(context:CR.MachineContext,event:CR.MachineEvent)=>{
8+
9+
const{tutorial, stepProgress}=event.data.payload
10+
11+
constprogress:CR.Progress={
12+
steps:stepProgress,
13+
stages:{},
14+
levels:{},
15+
complete:false
16+
}
17+
18+
constposition:CR.Position={
19+
stepId:'',
20+
stageId:'',
21+
levelId:'',
22+
}
23+
24+
// calculate progress from tutorial & stepProgress
25+
for(constleveloftutorial.version.levels){
26+
for(conststageoflevel.stages){
27+
// set stage progress
28+
conststageComplete:boolean=stage.steps.every((step:G.Step)=>{
29+
returnstepProgress[step.id]
30+
})
31+
if(stageComplete){
32+
progress.stages[stage.id]=true
33+
}elseif(!position.stageId.length){
34+
// set stage amd step position
35+
position.stageId=stage.id
36+
position.stepId=stage.steps.find((step:G.Step)=>!stepProgress[step.id]).id
37+
}
38+
}
39+
// set level progress
40+
constlevelComplete:boolean=level.stages.every((stage:G.Stage)=>{
41+
returnprogress.stages[stage.id]
42+
})
43+
if(levelComplete){
44+
progress.levels[level.id]=true
45+
}elseif(!position.levelId.length){
46+
position.levelId=level.id
47+
}
48+
}
49+
// set tutorial progress
50+
progress.complete=tutorial.version.levels.every((level:G.Level)=>{
51+
returnprogress.levels[level.id]
52+
})
53+
54+
returnassign({
55+
tutorial,
56+
progress,
57+
position,
58+
})
59+
},
860
setTutorial:assign({
961
tutorial:(context:CR.MachineContext,event:CR.MachineEvent):any=>{
1062
const{tutorial}=event.payload
11-
storage.tutorial.set(tutorial)
1263
returntutorial
1364
},
1465
}),
15-
continueTutorial:assign({
16-
tutorial:(context:CR.MachineContext,event:CR.MachineEvent)=>event.data.payload.tutorial,
17-
progress:(context:CR.MachineContext,event:CR.MachineEvent)=>event.data.payload.progress,
18-
position:(context:CR.MachineContext,event:CR.MachineEvent)=>event.data.payload.position,
19-
}),
2066
//@ts-ignore
2167
initPosition:assign({
2268
position:(context:CR.MachineContext,event:CR.MachineEvent):CR.Position=>{
2369
constposition:CR.Position=selectors.initialPosition(event.payload)
24-
storage.position.set(position)
2570
returnposition
2671
},
2772
}),
@@ -51,8 +96,6 @@ export default {
5196
stepId:step.id
5297
}
5398

54-
storage.position.set(nextPosition)
55-
5699
returnnextPosition
57100
},
58101
}),
@@ -73,8 +116,6 @@ export default {
73116
stepId:stage.steps[0].id,
74117
}
75118

76-
storage.position.set(nextPosition)
77-
78119
returnnextPosition
79120
},
80121
}),
@@ -96,8 +137,6 @@ export default {
96137
stepId:level.stages[0].steps[0].id,
97138
}
98139

99-
storage.position.set(nextPosition)
100-
101140
returnnextPosition
102141
},
103142
}),
@@ -111,8 +150,6 @@ export default {
111150

112151
currentProgress.steps[stepId]=true
113152

114-
storage.progress.set(currentProgress)
115-
116153
returncurrentProgress
117154
},
118155
}),
@@ -126,8 +163,6 @@ export default {
126163

127164
progress.stages[stageId]=true
128165

129-
storage.progress.set(progress)
130-
131166
returnprogress
132167
},
133168
}),
@@ -228,17 +263,14 @@ export default {
228263
}),
229264
reset:assign({
230265
tutorial(){
231-
storage.tutorial.set(null)
232266
returnnull
233267
},
234268
progress():CR.Progress{
235269
constprogress:CR.Progress=selectors.defaultProgress()
236-
storage.progress.set(progress)
237270
returnprogress
238271
},
239272
position():CR.Position{
240273
constposition:CR.Position=selectors.defaultPosition()
241-
storage.position.set(position)
242274
returnposition
243275
}
244276
})

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ import * as selectors from '../../selectors'
44
importchannelfrom'../../channel'
55

66
exportdefault{
7+
loadStoredTutorial(){
8+
channel.editorSend({
9+
type:'TUTORIAL_LOAD_STORED',
10+
})
11+
},
712
initializeTutorial(context:CR.MachineContext,event:CR.MachineEvent){
813
// setup test runner and git
914
const{tutorial}=event.data.payload

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp