@@ -18,7 +18,7 @@ import { derived, writable } from 'svelte/store';
18
18
/**
19
19
* @type {import('svelte/store').Writable<State> }
20
20
*/
21
- const _state = writable ( {
21
+ const { subscribe , set , update } = writable ( {
22
22
status : 'initial' ,
23
23
stubs : [ ] ,
24
24
selected : null ,
@@ -34,100 +34,100 @@ const _state = writable({
34
34
} ) ;
35
35
36
36
export const state = {
37
- subscribe : _state . subscribe ,
37
+ subscribe,
38
+
38
39
/** @param {import('$lib/types').FileStub } file */
39
40
update_file : ( file ) => {
40
- _state . update ( ( state ) => {
41
- state . status = 'update' ;
42
- state . stubs = state . stubs . map ( ( stub ) => {
41
+ update ( ( state ) => ( {
42
+ ...state ,
43
+ status : 'update' ,
44
+ stubs : state . stubs . map ( ( stub ) => {
43
45
if ( stub . name === file . name ) {
44
46
return file ;
45
47
}
46
48
return stub ;
47
- } ) ;
48
- state . last_updated = file ;
49
- return state ;
50
- } ) ;
49
+ } ) ,
50
+ last_updated : file
51
+ } ) ) ;
51
52
} ,
53
+
52
54
/** @param {import('$lib/types').Stub[] } [stubs] */
53
55
set_stubs : ( stubs ) => {
54
- _state . update ( ( state ) => {
55
- state . status = 'set' ;
56
- state . stubs = stubs || state . stubs ;
57
- state . last_updated = undefined ;
58
- return state ;
59
- } ) ;
56
+ update ( ( state ) => ( {
57
+ ... state ,
58
+ status : 'set' ,
59
+ stubs : stubs ?? state . stubs ,
60
+ last_updated : undefined
61
+ } ) ) ;
60
62
} ,
63
+
61
64
/** @param {import('$lib/types').Exercise } exercise */
62
65
switch_exercise : ( exercise ) => {
63
- _state . update ( ( state ) => {
64
- const solution = { ...exercise . a } ;
65
- const editing_constraints = {
66
- create : exercise . editing_constraints . create ,
67
- remove : exercise . editing_constraints . remove
68
- } ;
69
-
70
- // TODO should exercise.a/b be an array in the first place?
71
- for ( const stub of Object . values ( exercise . b ) ) {
72
- if ( stub . type === 'file' && stub . contents . startsWith ( '__delete' ) ) {
73
- // remove file
74
- if ( ! editing_constraints . remove . includes ( stub . name ) ) {
75
- editing_constraints . remove . push ( stub . name ) ;
76
- }
77
- delete solution [ stub . name ] ;
78
- } else if ( stub . name . endsWith ( '/__delete' ) ) {
79
- // remove directory
80
- const parent = stub . name . slice ( 0 , stub . name . lastIndexOf ( '/' ) ) ;
81
- if ( ! editing_constraints . remove . includes ( parent ) ) {
82
- editing_constraints . remove . push ( parent ) ;
83
- }
84
- delete solution [ parent ] ;
85
- for ( const k in solution ) {
86
- if ( k . startsWith ( parent + '/' ) ) {
87
- delete solution [ k ] ;
88
- }
89
- }
90
- } else {
91
- if ( ! solution [ stub . name ] && ! editing_constraints . create . includes ( stub . name ) ) {
92
- editing_constraints . create . push ( stub . name ) ;
66
+ const solution = { ...exercise . a } ;
67
+ const editing_constraints = {
68
+ create : exercise . editing_constraints . create ,
69
+ remove : exercise . editing_constraints . remove
70
+ } ;
71
+
72
+ // TODO should exercise.a/b be an array in the first place?
73
+ for ( const stub of Object . values ( exercise . b ) ) {
74
+ if ( stub . type === 'file' && stub . contents . startsWith ( '__delete' ) ) {
75
+ // remove file
76
+ if ( ! editing_constraints . remove . includes ( stub . name ) ) {
77
+ editing_constraints . remove . push ( stub . name ) ;
78
+ }
79
+ delete solution [ stub . name ] ;
80
+ } else if ( stub . name . endsWith ( '/__delete' ) ) {
81
+ // remove directory
82
+ const parent = stub . name . slice ( 0 , stub . name . lastIndexOf ( '/' ) ) ;
83
+ if ( ! editing_constraints . remove . includes ( parent ) ) {
84
+ editing_constraints . remove . push ( parent ) ;
85
+ }
86
+ delete solution [ parent ] ;
87
+ for ( const k in solution ) {
88
+ if ( k . startsWith ( parent + '/' ) ) {
89
+ delete solution [ k ] ;
93
90
}
94
- solution [ stub . name ] = exercise . b [ stub . name ] ;
95
91
}
92
+ } else {
93
+ if ( ! solution [ stub . name ] && ! editing_constraints . create . includes ( stub . name ) ) {
94
+ editing_constraints . create . push ( stub . name ) ;
95
+ }
96
+ solution [ stub . name ] = exercise . b [ stub . name ] ;
96
97
}
98
+ }
97
99
98
- state . status = 'switch' ;
99
- state . stubs = Object . values ( exercise . a ) ;
100
- state . exercise = {
100
+ set ( {
101
+ status : 'switch' ,
102
+ stubs : Object . values ( exercise . a ) ,
103
+ exercise : {
101
104
initial : Object . values ( exercise . a ) ,
102
105
solution,
103
106
editing_constraints,
104
107
scope : exercise . scope
105
- } ;
106
- state . last_updated = undefined ;
107
- state . selected = exercise . focus ;
108
- return state ;
108
+ } ,
109
+ last_updated : undefined ,
110
+ selected : exercise . focus
109
111
} ) ;
110
112
} ,
113
+
111
114
toggle_completion : ( ) => {
112
- _state . update ( ( state ) => {
113
- if ( is_completed ( state ) ) {
114
- state . stubs = state . exercise . initial ;
115
- } else {
116
- state . stubs = Object . values ( state . exercise . solution ) ;
117
- }
118
- state . status = 'set' ;
119
- state . last_updated = undefined ;
120
- return state ;
121
- } ) ;
115
+ update ( ( state ) => ( {
116
+ ...state ,
117
+ status : 'set' ,
118
+ stubs : is_completed ( state ) ? state . exercise . initial : Object . values ( state . exercise . solution ) ,
119
+ last_updated : undefined
120
+ } ) ) ;
122
121
} ,
122
+
123
123
/** @param {string | null } name */
124
124
select_file : ( name ) => {
125
- _state . update ( ( state ) => {
126
- state . status = 'select' ;
127
- state . selected = name ;
128
- state . last_updated = undefined ;
129
- return state ;
130
- } ) ;
125
+ update ( ( state ) => ( {
126
+ ... state ,
127
+ status : 'select' ,
128
+ selected : name ,
129
+ last_updated : undefined
130
+ } ) ) ;
131
131
}
132
132
} ;
133
133
0 commit comments