@hkdigital/lib-core 0.4.26 → 0.4.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/network/loaders/audio/AudioScene.svelte.d.ts +32 -18
- package/dist/network/loaders/audio/AudioScene.svelte.js +38 -104
- package/dist/network/loaders/audio/README.md +195 -0
- package/dist/network/loaders/base/SceneBase.svelte.d.ts +65 -0
- package/dist/network/loaders/base/SceneBase.svelte.js +283 -0
- package/dist/network/loaders/image/ImageScene.svelte.d.ts +12 -13
- package/dist/network/loaders/image/ImageScene.svelte.js +17 -93
- package/dist/network/states/NetworkLoader.svelte.d.ts +2 -2
- package/dist/network/states/NetworkLoader.svelte.js +15 -13
- package/dist/state/machines/loading-state-machine/LoadingStateMachine.svelte.d.ts +4 -4
- package/dist/state/machines/loading-state-machine/LoadingStateMachine.svelte.js +15 -9
- package/dist/state/machines/loading-state-machine/README.md +70 -45
- package/dist/state/machines/loading-state-machine/constants.d.ts +4 -2
- package/dist/state/machines/loading-state-machine/constants.js +4 -2
- package/package.json +1 -1
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
import { LoadingStateMachine } from '../../../state/machines.js';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
STATE_INITIAL,
|
|
5
|
+
STATE_LOADING,
|
|
6
|
+
STATE_LOADED,
|
|
7
|
+
STATE_ABORTING,
|
|
8
|
+
STATE_ABORTED,
|
|
9
|
+
STATE_ERROR,
|
|
10
|
+
LOAD,
|
|
11
|
+
LOADED,
|
|
12
|
+
ABORT,
|
|
13
|
+
ABORTED
|
|
14
|
+
} from '../../../state/machines.js';
|
|
15
|
+
|
|
16
|
+
import { waitForState } from '../../../util/svelte.js';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Base class for scene loaders that manage collections of media sources
|
|
20
|
+
*/
|
|
21
|
+
export default class SceneBase {
|
|
22
|
+
#state = new LoadingStateMachine();
|
|
23
|
+
|
|
24
|
+
// @note this exported state is set by onenter
|
|
25
|
+
state = $state(STATE_INITIAL);
|
|
26
|
+
|
|
27
|
+
loaded = $derived.by(() => {
|
|
28
|
+
return this.state === STATE_LOADED;
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
#progress = $derived.by(() => {
|
|
32
|
+
let totalSize = 0;
|
|
33
|
+
let totalBytesLoaded = 0;
|
|
34
|
+
let sourcesLoaded = 0;
|
|
35
|
+
|
|
36
|
+
const sources = this.sources;
|
|
37
|
+
const numberOfSources = sources.length;
|
|
38
|
+
|
|
39
|
+
for (let j = 0; j < numberOfSources; j++) {
|
|
40
|
+
const source = sources[j];
|
|
41
|
+
const loader = this.getLoaderFromSource(source);
|
|
42
|
+
|
|
43
|
+
const { bytesLoaded, size, loaded } = loader.progress;
|
|
44
|
+
|
|
45
|
+
totalSize += size;
|
|
46
|
+
totalBytesLoaded += bytesLoaded;
|
|
47
|
+
|
|
48
|
+
if (loaded) {
|
|
49
|
+
sourcesLoaded++;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return {
|
|
54
|
+
totalBytesLoaded,
|
|
55
|
+
totalSize,
|
|
56
|
+
sourcesLoaded,
|
|
57
|
+
numberOfSources
|
|
58
|
+
};
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
#abortProgress = $derived.by(() => {
|
|
62
|
+
let sourcesAborted = 0;
|
|
63
|
+
const sources = this.sources;
|
|
64
|
+
const numberOfSources = sources.length;
|
|
65
|
+
|
|
66
|
+
for (let j = 0; j < numberOfSources; j++) {
|
|
67
|
+
const source = sources[j];
|
|
68
|
+
const loader = this.getLoaderFromSource(source);
|
|
69
|
+
const loaderState = loader.state;
|
|
70
|
+
|
|
71
|
+
if (loaderState === STATE_ABORTED || loaderState === STATE_ERROR) {
|
|
72
|
+
sourcesAborted++;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return {
|
|
77
|
+
sourcesAborted,
|
|
78
|
+
numberOfSources
|
|
79
|
+
};
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Construct SceneBase
|
|
84
|
+
*/
|
|
85
|
+
constructor() {
|
|
86
|
+
const state = this.#state;
|
|
87
|
+
|
|
88
|
+
$effect(() => {
|
|
89
|
+
if (state.current === STATE_LOADING) {
|
|
90
|
+
const { sourcesLoaded, numberOfSources } = this.#progress;
|
|
91
|
+
|
|
92
|
+
if (sourcesLoaded === numberOfSources) {
|
|
93
|
+
this.#state.send(LOADED);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
$effect(() => {
|
|
99
|
+
if (state.current === STATE_ABORTING) {
|
|
100
|
+
const { sourcesAborted, numberOfSources } = this.#abortProgress;
|
|
101
|
+
|
|
102
|
+
if (sourcesAborted === numberOfSources) {
|
|
103
|
+
this.#state.send(ABORTED);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
state.onenter = (currentState) => {
|
|
109
|
+
if (currentState === STATE_LOADING) {
|
|
110
|
+
this.#startLoading();
|
|
111
|
+
} else if (currentState === STATE_ABORTING) {
|
|
112
|
+
this.#startAbort();
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
this.state = currentState;
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/* ==== Abstract methods - must be implemented by subclasses */
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Get the array of sources managed by this scene
|
|
123
|
+
*
|
|
124
|
+
* @returns {Array} Array of source objects
|
|
125
|
+
*/
|
|
126
|
+
get sources() {
|
|
127
|
+
throw new Error('Subclass must implement sources getter');
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Extract the loader from a source object
|
|
132
|
+
*
|
|
133
|
+
* @param {*} source
|
|
134
|
+
*
|
|
135
|
+
* @returns {*} Loader object with progress and state properties
|
|
136
|
+
*/
|
|
137
|
+
// eslint-disable-next-line no-unused-vars
|
|
138
|
+
getLoaderFromSource(source) {
|
|
139
|
+
throw new Error('Subclass must implement getLoaderFromSource method');
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/* ==== Common loader interface */
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Get scene loading progress
|
|
146
|
+
*/
|
|
147
|
+
get progress() {
|
|
148
|
+
return this.#progress;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Get scene abort progress
|
|
153
|
+
*/
|
|
154
|
+
get abortProgress() {
|
|
155
|
+
return this.#abortProgress;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Start loading all sources
|
|
160
|
+
*/
|
|
161
|
+
load() {
|
|
162
|
+
this.#state.send(LOAD);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Abort loading all sources
|
|
167
|
+
*/
|
|
168
|
+
abort() {
|
|
169
|
+
this.#state.send(ABORT);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Preload all sources with progress tracking and abort capability
|
|
174
|
+
* - Starts loading and waits for completion
|
|
175
|
+
* - Supports timeout and progress callbacks
|
|
176
|
+
* - Returns object with promise and abort function
|
|
177
|
+
*
|
|
178
|
+
* @param {object} [options]
|
|
179
|
+
* @param {number} [options.timeoutMs=10000] - Timeout in milliseconds
|
|
180
|
+
* @param {Function} [options.onProgress] - Progress callback function
|
|
181
|
+
*
|
|
182
|
+
* @returns {object} Object with promise and abort function
|
|
183
|
+
* @returns {Promise<SceneBase>} returns.promise - Promise that resolves when loaded
|
|
184
|
+
* @returns {Function} returns.abort - Function to abort preloading
|
|
185
|
+
*/
|
|
186
|
+
preload({ timeoutMs = 10000, onProgress } = {}) {
|
|
187
|
+
let timeoutId = null;
|
|
188
|
+
let progressIntervalId = null;
|
|
189
|
+
let isAborted = false;
|
|
190
|
+
|
|
191
|
+
const abort = () => {
|
|
192
|
+
if (isAborted) return;
|
|
193
|
+
isAborted = true;
|
|
194
|
+
|
|
195
|
+
if (timeoutId) {
|
|
196
|
+
clearTimeout(timeoutId);
|
|
197
|
+
timeoutId = null;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (progressIntervalId) {
|
|
201
|
+
clearInterval(progressIntervalId);
|
|
202
|
+
progressIntervalId = null;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
this.abort();
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
const promise = new Promise((resolve, reject) => {
|
|
209
|
+
// Set up progress tracking with polling
|
|
210
|
+
if (onProgress) {
|
|
211
|
+
progressIntervalId = setInterval(() => {
|
|
212
|
+
if (!isAborted) {
|
|
213
|
+
onProgress(this.progress);
|
|
214
|
+
}
|
|
215
|
+
}, 50); // Poll every 50ms
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Set up timeout
|
|
219
|
+
if (timeoutMs > 0) {
|
|
220
|
+
timeoutId = setTimeout(() => {
|
|
221
|
+
abort();
|
|
222
|
+
reject(new Error(`Preload timed out after ${timeoutMs}ms`));
|
|
223
|
+
}, timeoutMs);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Start loading
|
|
227
|
+
this.load();
|
|
228
|
+
|
|
229
|
+
// Wait for completion with extended timeout
|
|
230
|
+
const waitTimeout = Math.max(timeoutMs + 1000, 2000);
|
|
231
|
+
waitForState(() => {
|
|
232
|
+
return this.loaded ||
|
|
233
|
+
this.state === STATE_ABORTED ||
|
|
234
|
+
this.state === STATE_ERROR;
|
|
235
|
+
}, waitTimeout)
|
|
236
|
+
.then(() => {
|
|
237
|
+
if (timeoutId) {
|
|
238
|
+
clearTimeout(timeoutId);
|
|
239
|
+
timeoutId = null;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
if (progressIntervalId) {
|
|
243
|
+
clearInterval(progressIntervalId);
|
|
244
|
+
progressIntervalId = null;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
if (isAborted || this.state === STATE_ABORTED) {
|
|
248
|
+
reject(new Error('Preload was aborted'));
|
|
249
|
+
} else if (this.state === STATE_ERROR) {
|
|
250
|
+
reject(new Error('Preload failed due to error'));
|
|
251
|
+
} else if (this.loaded) {
|
|
252
|
+
resolve(this);
|
|
253
|
+
} else {
|
|
254
|
+
reject(new Error(`Preload failed: unexpected state ${this.state}`));
|
|
255
|
+
}
|
|
256
|
+
})
|
|
257
|
+
.catch(reject);
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
return { promise, abort };
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
destroy() {
|
|
264
|
+
// TODO: disconnect all sources?
|
|
265
|
+
// TODO: Unload loaders?
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/* ==== Internal methods */
|
|
269
|
+
|
|
270
|
+
#startLoading() {
|
|
271
|
+
for (const source of this.sources) {
|
|
272
|
+
const loader = this.getLoaderFromSource(source);
|
|
273
|
+
loader.load();
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
#startAbort() {
|
|
278
|
+
for (const source of this.sources) {
|
|
279
|
+
const loader = this.getLoaderFromSource(source);
|
|
280
|
+
loader.abort();
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
@@ -7,23 +7,21 @@
|
|
|
7
7
|
* @property {string} label
|
|
8
8
|
* @property {ImageLoader} imageLoader
|
|
9
9
|
*/
|
|
10
|
-
export default class ImageScene {
|
|
11
|
-
state: string;
|
|
12
|
-
loaded: boolean;
|
|
10
|
+
export default class ImageScene extends SceneBase {
|
|
13
11
|
/**
|
|
14
|
-
* Get image
|
|
12
|
+
* Get the array of image sources managed by this scene
|
|
13
|
+
*
|
|
14
|
+
* @returns {ImageSceneSource[]}
|
|
15
15
|
*/
|
|
16
|
-
get
|
|
17
|
-
totalBytesLoaded: number;
|
|
18
|
-
totalSize: number;
|
|
19
|
-
sourcesLoaded: number;
|
|
20
|
-
numberOfSources: number;
|
|
21
|
-
};
|
|
16
|
+
get sources(): ImageSceneSource[];
|
|
22
17
|
/**
|
|
23
|
-
*
|
|
18
|
+
* Extract the image loader from a source object
|
|
19
|
+
*
|
|
20
|
+
* @param {ImageSceneSource} source
|
|
21
|
+
*
|
|
22
|
+
* @returns {ImageLoader}
|
|
24
23
|
*/
|
|
25
|
-
|
|
26
|
-
destroy(): void;
|
|
24
|
+
getLoaderFromSource(source: ImageSceneSource): ImageLoader;
|
|
27
25
|
/**
|
|
28
26
|
* Add image source
|
|
29
27
|
* - Uses an ImageLoader instance to load image data from network
|
|
@@ -73,4 +71,5 @@ export type ImageSceneSource = {
|
|
|
73
71
|
label: string;
|
|
74
72
|
imageLoader: ImageLoader;
|
|
75
73
|
};
|
|
74
|
+
import SceneBase from '../base/SceneBase.svelte.js';
|
|
76
75
|
import ImageLoader from './ImageLoader.svelte.js';
|
|
@@ -2,16 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import * as expect from '../../../util/expect.js';
|
|
4
4
|
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
import {
|
|
8
|
-
STATE_INITIAL,
|
|
9
|
-
STATE_LOADING,
|
|
10
|
-
STATE_LOADED,
|
|
11
|
-
LOAD,
|
|
12
|
-
LOADED
|
|
13
|
-
} from '../../../state/machines.js';
|
|
14
|
-
|
|
5
|
+
import SceneBase from '../base/SceneBase.svelte.js';
|
|
15
6
|
import ImageLoader from './ImageLoader.svelte.js';
|
|
16
7
|
|
|
17
8
|
/**
|
|
@@ -25,101 +16,40 @@ import ImageLoader from './ImageLoader.svelte.js';
|
|
|
25
16
|
* @property {ImageLoader} imageLoader
|
|
26
17
|
*/
|
|
27
18
|
|
|
28
|
-
export default class ImageScene {
|
|
29
|
-
#state = new LoadingStateMachine();
|
|
30
|
-
|
|
31
|
-
// @note this exported state is set by onenter
|
|
32
|
-
state = $state(STATE_INITIAL);
|
|
33
|
-
|
|
34
|
-
loaded = $derived.by(() => {
|
|
35
|
-
return this.state === STATE_LOADED;
|
|
36
|
-
});
|
|
19
|
+
export default class ImageScene extends SceneBase {
|
|
37
20
|
|
|
38
21
|
/** @type {ImageSceneSource[]} */
|
|
39
22
|
#imageSources = $state([]);
|
|
40
23
|
|
|
41
|
-
#progress = $derived.by(() => {
|
|
42
|
-
// console.log('update progress');
|
|
43
|
-
|
|
44
|
-
let totalSize = 0;
|
|
45
|
-
let totalBytesLoaded = 0;
|
|
46
|
-
let sourcesLoaded = 0;
|
|
47
|
-
|
|
48
|
-
const sources = this.#imageSources;
|
|
49
|
-
const numberOfSources = sources.length;
|
|
50
|
-
|
|
51
|
-
for (let j = 0; j < numberOfSources; j++) {
|
|
52
|
-
const source = sources[j];
|
|
53
|
-
const { imageLoader } = source;
|
|
54
|
-
|
|
55
|
-
const { bytesLoaded, size, loaded } = imageLoader.progress;
|
|
56
|
-
|
|
57
|
-
totalSize += size;
|
|
58
|
-
totalBytesLoaded += bytesLoaded;
|
|
59
|
-
|
|
60
|
-
if (loaded) {
|
|
61
|
-
sourcesLoaded++;
|
|
62
|
-
}
|
|
63
|
-
} // end for
|
|
64
|
-
|
|
65
|
-
return {
|
|
66
|
-
totalBytesLoaded,
|
|
67
|
-
totalSize,
|
|
68
|
-
sourcesLoaded,
|
|
69
|
-
numberOfSources
|
|
70
|
-
};
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
#sourcesLoaded = $derived( this.#progress.sourcesLoaded );
|
|
74
|
-
#numberOfSources = $derived( this.#progress.numberOfSources );
|
|
75
24
|
|
|
76
25
|
/**
|
|
77
26
|
* Construct ImageScene
|
|
78
27
|
*/
|
|
79
28
|
constructor() {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
$effect( () => {
|
|
83
|
-
if (state.current === STATE_LOADING) {
|
|
84
|
-
if (this.#sourcesLoaded === this.#numberOfSources) {
|
|
85
|
-
// console.log(`All [${this.#numberOfSources}] sources loaded`);
|
|
86
|
-
this.#state.send(LOADED);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
} );
|
|
90
|
-
|
|
91
|
-
state.onenter = ( currentState ) => {
|
|
92
|
-
// console.log('onenter', currentState );
|
|
93
|
-
|
|
94
|
-
if(currentState === STATE_LOADING )
|
|
95
|
-
{
|
|
96
|
-
// console.log('ImageScene:loading');
|
|
97
|
-
this.#startLoading();
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
this.state = currentState;
|
|
101
|
-
};
|
|
29
|
+
super();
|
|
102
30
|
}
|
|
103
31
|
|
|
104
|
-
/* ====
|
|
32
|
+
/* ==== SceneBase implementation */
|
|
105
33
|
|
|
106
34
|
/**
|
|
107
|
-
* Get image
|
|
35
|
+
* Get the array of image sources managed by this scene
|
|
36
|
+
*
|
|
37
|
+
* @returns {ImageSceneSource[]}
|
|
108
38
|
*/
|
|
109
|
-
get
|
|
110
|
-
return this.#
|
|
39
|
+
get sources() {
|
|
40
|
+
return this.#imageSources;
|
|
111
41
|
}
|
|
112
42
|
|
|
113
43
|
/**
|
|
114
|
-
*
|
|
44
|
+
* Extract the image loader from a source object
|
|
45
|
+
*
|
|
46
|
+
* @param {ImageSceneSource} source
|
|
47
|
+
*
|
|
48
|
+
* @returns {ImageLoader}
|
|
115
49
|
*/
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
destroy() {
|
|
121
|
-
// TODO: disconnect all image sources?
|
|
122
|
-
// TODO: Unload ImageLoaders?
|
|
50
|
+
// eslint-disable-next-line no-unused-vars
|
|
51
|
+
getLoaderFromSource(source) {
|
|
52
|
+
return source.imageLoader;
|
|
123
53
|
}
|
|
124
54
|
|
|
125
55
|
/* ==== Source definitions */
|
|
@@ -185,12 +115,6 @@ export default class ImageScene {
|
|
|
185
115
|
return source.imageLoader.getObjectURL();
|
|
186
116
|
}
|
|
187
117
|
|
|
188
|
-
async #startLoading() {
|
|
189
|
-
for (const { imageLoader } of this.#imageSources) {
|
|
190
|
-
imageLoader.load();
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
118
|
/* ==== Internals */
|
|
195
119
|
|
|
196
120
|
/**
|
|
@@ -45,9 +45,9 @@ export default class NetworkLoader {
|
|
|
45
45
|
/**
|
|
46
46
|
* Abort the current loading operation
|
|
47
47
|
* - Only works when in STATE_LOADING
|
|
48
|
-
* - Aborts network requests and transitions to
|
|
48
|
+
* - Aborts network requests and transitions to STATE_ABORTING
|
|
49
49
|
*/
|
|
50
|
-
|
|
50
|
+
abort(): void;
|
|
51
51
|
/**
|
|
52
52
|
* Get network data size in bytes
|
|
53
53
|
* - Info comes from the content length response header
|
|
@@ -7,14 +7,14 @@ import {
|
|
|
7
7
|
STATE_LOADING,
|
|
8
8
|
STATE_UNLOADING,
|
|
9
9
|
STATE_LOADED,
|
|
10
|
-
|
|
11
|
-
STATE_ERROR,
|
|
10
|
+
STATE_ABORTING,
|
|
12
11
|
LOAD,
|
|
13
12
|
ERROR,
|
|
14
13
|
LOADED,
|
|
15
14
|
UNLOAD,
|
|
16
15
|
INITIAL,
|
|
17
|
-
|
|
16
|
+
ABORT,
|
|
17
|
+
ABORTED
|
|
18
18
|
} from '../../state/machines.js';
|
|
19
19
|
|
|
20
20
|
import * as expect from '../../util/expect.js';
|
|
@@ -123,21 +123,23 @@ export default class NetworkLoader {
|
|
|
123
123
|
}
|
|
124
124
|
break;
|
|
125
125
|
|
|
126
|
-
case
|
|
126
|
+
case STATE_ABORTING:
|
|
127
127
|
{
|
|
128
|
-
// console.log('NetworkLoader:
|
|
128
|
+
// console.log('NetworkLoader:aborting');
|
|
129
129
|
if (this._abortLoading) {
|
|
130
130
|
this._abortLoading();
|
|
131
131
|
this._abortLoading = null;
|
|
132
132
|
}
|
|
133
|
+
// Transition to aborted state after abort completes
|
|
134
|
+
this._state.send(ABORTED);
|
|
133
135
|
}
|
|
134
136
|
break;
|
|
135
137
|
|
|
136
|
-
case STATE_ERROR:
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
138
|
+
// case STATE_ERROR:
|
|
139
|
+
// {
|
|
140
|
+
// console.log('NetworkLoader:error', state.error);
|
|
141
|
+
// }
|
|
142
|
+
// break;
|
|
141
143
|
} // end switch
|
|
142
144
|
};
|
|
143
145
|
}
|
|
@@ -160,10 +162,10 @@ export default class NetworkLoader {
|
|
|
160
162
|
/**
|
|
161
163
|
* Abort the current loading operation
|
|
162
164
|
* - Only works when in STATE_LOADING
|
|
163
|
-
* - Aborts network requests and transitions to
|
|
165
|
+
* - Aborts network requests and transitions to STATE_ABORTING
|
|
164
166
|
*/
|
|
165
|
-
|
|
166
|
-
this._state.send(
|
|
167
|
+
abort() {
|
|
168
|
+
this._state.send(ABORT);
|
|
167
169
|
}
|
|
168
170
|
|
|
169
171
|
/**
|
|
@@ -10,13 +10,13 @@ export default class LoadingStateMachine extends FiniteStateMachine {
|
|
|
10
10
|
* - Only valid when currently loading
|
|
11
11
|
* - Useful for external timeout management
|
|
12
12
|
*/
|
|
13
|
-
|
|
13
|
+
timeout(): void;
|
|
14
14
|
/**
|
|
15
|
-
* Transition to
|
|
15
|
+
* Transition to aborting state
|
|
16
16
|
* - Only valid when currently loading
|
|
17
|
-
* - Useful for external
|
|
17
|
+
* - Useful for external abort management
|
|
18
18
|
*/
|
|
19
|
-
|
|
19
|
+
abort(): void;
|
|
20
20
|
#private;
|
|
21
21
|
}
|
|
22
22
|
import FiniteStateMachine from '../finite-state-machine/FiniteStateMachine.svelte.js';
|
|
@@ -8,14 +8,16 @@ import {
|
|
|
8
8
|
STATE_LOADING,
|
|
9
9
|
STATE_UNLOADING,
|
|
10
10
|
STATE_LOADED,
|
|
11
|
-
|
|
11
|
+
STATE_ABORTING,
|
|
12
|
+
STATE_ABORTED,
|
|
12
13
|
STATE_ERROR,
|
|
13
14
|
STATE_TIMEOUT,
|
|
14
15
|
|
|
15
16
|
// > Signals
|
|
16
17
|
INITIAL,
|
|
17
18
|
LOAD,
|
|
18
|
-
|
|
19
|
+
ABORT,
|
|
20
|
+
ABORTED,
|
|
19
21
|
ERROR,
|
|
20
22
|
LOADED,
|
|
21
23
|
UNLOAD,
|
|
@@ -41,7 +43,7 @@ export default class LoadingStateMachine extends FiniteStateMachine {
|
|
|
41
43
|
// _enter: () => {
|
|
42
44
|
// console.log('LoadingStateMachine: enter LOADING');
|
|
43
45
|
// },
|
|
44
|
-
[
|
|
46
|
+
[ABORT]: STATE_ABORTING,
|
|
45
47
|
[ERROR]: STATE_ERROR,
|
|
46
48
|
[LOADED]: STATE_LOADED,
|
|
47
49
|
[TIMEOUT]: STATE_TIMEOUT
|
|
@@ -57,7 +59,11 @@ export default class LoadingStateMachine extends FiniteStateMachine {
|
|
|
57
59
|
[ERROR]: STATE_ERROR,
|
|
58
60
|
[INITIAL]: STATE_INITIAL
|
|
59
61
|
},
|
|
60
|
-
[
|
|
62
|
+
[STATE_ABORTING]: {
|
|
63
|
+
[ERROR]: STATE_ERROR,
|
|
64
|
+
[ABORTED]: STATE_ABORTED
|
|
65
|
+
},
|
|
66
|
+
[STATE_ABORTED]: {
|
|
61
67
|
[LOAD]: STATE_LOADING,
|
|
62
68
|
[UNLOAD]: STATE_UNLOADING
|
|
63
69
|
},
|
|
@@ -99,16 +105,16 @@ export default class LoadingStateMachine extends FiniteStateMachine {
|
|
|
99
105
|
* - Only valid when currently loading
|
|
100
106
|
* - Useful for external timeout management
|
|
101
107
|
*/
|
|
102
|
-
|
|
108
|
+
timeout() {
|
|
103
109
|
this.send(TIMEOUT);
|
|
104
110
|
}
|
|
105
111
|
|
|
106
112
|
/**
|
|
107
|
-
* Transition to
|
|
113
|
+
* Transition to aborting state
|
|
108
114
|
* - Only valid when currently loading
|
|
109
|
-
* - Useful for external
|
|
115
|
+
* - Useful for external abort management
|
|
110
116
|
*/
|
|
111
|
-
|
|
112
|
-
this.send(
|
|
117
|
+
abort() {
|
|
118
|
+
this.send(ABORT);
|
|
113
119
|
}
|
|
114
120
|
}
|