@hkdigital/lib-core 0.4.27 → 0.4.29
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/CLAUDE.md +350 -0
- package/dist/logging/index.d.ts +1 -1
- package/dist/logging/index.js +2 -2
- package/dist/logging/internal/adapters/console.js +1 -1
- package/dist/logging/internal/factories/client.js +1 -1
- package/dist/logging/internal/factories/server.js +1 -1
- package/dist/logging/internal/logger/Logger.js +1 -1
- package/dist/network/loaders/audio/AudioScene.svelte.d.ts +31 -28
- package/dist/network/loaders/audio/AudioScene.svelte.js +36 -166
- 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 -24
- package/dist/network/loaders/image/ImageScene.svelte.js +17 -155
- package/dist/services/service-manager/ServiceManager.d.ts +24 -4
- package/dist/services/service-manager/ServiceManager.js +89 -43
- package/dist/services/service-manager/constants.d.ts +2 -0
- package/dist/services/service-manager/constants.js +3 -0
- package/dist/services/service-manager/typedef.d.ts +8 -19
- package/dist/services/service-manager/typedef.js +6 -11
- package/dist/services/service-manager/util.d.ts +35 -0
- package/dist/services/service-manager/util.js +90 -0
- package/package.json +7 -4
- /package/dist/logging/{constants.d.ts → levels.d.ts} +0 -0
- /package/dist/logging/{constants.js → levels.js} +0 -0
|
@@ -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,34 +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
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
totalBytesLoaded: number;
|
|
18
|
-
totalSize: number;
|
|
19
|
-
sourcesLoaded: number;
|
|
20
|
-
numberOfSources: number;
|
|
21
|
-
};
|
|
22
|
-
/**
|
|
23
|
-
* Get image scene abort progress
|
|
24
|
-
*/
|
|
25
|
-
get abortProgress(): {
|
|
26
|
-
sourcesAborted: number;
|
|
27
|
-
numberOfSources: number;
|
|
28
|
-
};
|
|
29
|
-
/**
|
|
30
|
-
* Start loading all image sources
|
|
12
|
+
* Get the array of image sources managed by this scene
|
|
13
|
+
*
|
|
14
|
+
* @returns {ImageSceneSource[]}
|
|
31
15
|
*/
|
|
32
|
-
|
|
16
|
+
get sources(): ImageSceneSource[];
|
|
33
17
|
/**
|
|
34
|
-
*
|
|
18
|
+
* Extract the image loader from a source object
|
|
19
|
+
*
|
|
20
|
+
* @param {ImageSceneSource} source
|
|
21
|
+
*
|
|
22
|
+
* @returns {ImageLoader}
|
|
35
23
|
*/
|
|
36
|
-
|
|
37
|
-
destroy(): void;
|
|
24
|
+
getLoaderFromSource(source: ImageSceneSource): ImageLoader;
|
|
38
25
|
/**
|
|
39
26
|
* Add image source
|
|
40
27
|
* - Uses an ImageLoader instance to load image data from network
|
|
@@ -84,4 +71,5 @@ export type ImageSceneSource = {
|
|
|
84
71
|
label: string;
|
|
85
72
|
imageLoader: ImageLoader;
|
|
86
73
|
};
|
|
74
|
+
import SceneBase from '../base/SceneBase.svelte.js';
|
|
87
75
|
import ImageLoader from './ImageLoader.svelte.js';
|
|
@@ -2,21 +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
|
-
STATE_ABORTING,
|
|
12
|
-
STATE_ABORTED,
|
|
13
|
-
STATE_ERROR,
|
|
14
|
-
LOAD,
|
|
15
|
-
LOADED,
|
|
16
|
-
ABORT,
|
|
17
|
-
ABORTED
|
|
18
|
-
} from '../../../state/machines.js';
|
|
19
|
-
|
|
5
|
+
import SceneBase from '../base/SceneBase.svelte.js';
|
|
20
6
|
import ImageLoader from './ImageLoader.svelte.js';
|
|
21
7
|
|
|
22
8
|
/**
|
|
@@ -30,152 +16,40 @@ import ImageLoader from './ImageLoader.svelte.js';
|
|
|
30
16
|
* @property {ImageLoader} imageLoader
|
|
31
17
|
*/
|
|
32
18
|
|
|
33
|
-
export default class ImageScene {
|
|
34
|
-
#state = new LoadingStateMachine();
|
|
35
|
-
|
|
36
|
-
// @note this exported state is set by onenter
|
|
37
|
-
state = $state(STATE_INITIAL);
|
|
38
|
-
|
|
39
|
-
loaded = $derived.by(() => {
|
|
40
|
-
return this.state === STATE_LOADED;
|
|
41
|
-
});
|
|
19
|
+
export default class ImageScene extends SceneBase {
|
|
42
20
|
|
|
43
21
|
/** @type {ImageSceneSource[]} */
|
|
44
22
|
#imageSources = $state([]);
|
|
45
23
|
|
|
46
|
-
#progress = $derived.by(() => {
|
|
47
|
-
// console.log('update progress');
|
|
48
|
-
|
|
49
|
-
let totalSize = 0;
|
|
50
|
-
let totalBytesLoaded = 0;
|
|
51
|
-
let sourcesLoaded = 0;
|
|
52
|
-
|
|
53
|
-
const sources = this.#imageSources;
|
|
54
|
-
const numberOfSources = sources.length;
|
|
55
|
-
|
|
56
|
-
for (let j = 0; j < numberOfSources; j++) {
|
|
57
|
-
const source = sources[j];
|
|
58
|
-
const { imageLoader } = source;
|
|
59
|
-
|
|
60
|
-
const { bytesLoaded, size, loaded } = imageLoader.progress;
|
|
61
|
-
|
|
62
|
-
totalSize += size;
|
|
63
|
-
totalBytesLoaded += bytesLoaded;
|
|
64
|
-
|
|
65
|
-
if (loaded) {
|
|
66
|
-
sourcesLoaded++;
|
|
67
|
-
}
|
|
68
|
-
} // end for
|
|
69
|
-
|
|
70
|
-
return {
|
|
71
|
-
totalBytesLoaded,
|
|
72
|
-
totalSize,
|
|
73
|
-
sourcesLoaded,
|
|
74
|
-
numberOfSources
|
|
75
|
-
};
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
#abortProgress = $derived.by(() => {
|
|
79
|
-
let sourcesAborted = 0;
|
|
80
|
-
const sources = this.#imageSources;
|
|
81
|
-
const numberOfSources = sources.length;
|
|
82
|
-
|
|
83
|
-
for (let j = 0; j < numberOfSources; j++) {
|
|
84
|
-
const source = sources[j];
|
|
85
|
-
const { imageLoader } = source;
|
|
86
|
-
const loaderState = imageLoader.state;
|
|
87
|
-
|
|
88
|
-
if (loaderState === STATE_ABORTED || loaderState === STATE_ERROR) {
|
|
89
|
-
sourcesAborted++;
|
|
90
|
-
}
|
|
91
|
-
} // end for
|
|
92
|
-
|
|
93
|
-
return {
|
|
94
|
-
sourcesAborted,
|
|
95
|
-
numberOfSources
|
|
96
|
-
};
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
#sourcesLoaded = $derived( this.#progress.sourcesLoaded );
|
|
100
|
-
#numberOfSources = $derived( this.#progress.numberOfSources );
|
|
101
24
|
|
|
102
25
|
/**
|
|
103
26
|
* Construct ImageScene
|
|
104
27
|
*/
|
|
105
28
|
constructor() {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
$effect( () => {
|
|
109
|
-
if (state.current === STATE_LOADING) {
|
|
110
|
-
if (this.#sourcesLoaded === this.#numberOfSources) {
|
|
111
|
-
// console.log(`All [${this.#numberOfSources}] sources loaded`);
|
|
112
|
-
this.#state.send(LOADED);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
} );
|
|
116
|
-
|
|
117
|
-
$effect(() => {
|
|
118
|
-
if (state.current === STATE_ABORTING) {
|
|
119
|
-
const { sourcesAborted, numberOfSources } = this.#abortProgress;
|
|
120
|
-
|
|
121
|
-
if (sourcesAborted === numberOfSources) {
|
|
122
|
-
// console.debug(`ImageScene: ${numberOfSources} sources aborted`);
|
|
123
|
-
this.#state.send(ABORTED);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
state.onenter = ( currentState ) => {
|
|
129
|
-
// console.log('onenter', currentState );
|
|
130
|
-
|
|
131
|
-
if(currentState === STATE_LOADING )
|
|
132
|
-
{
|
|
133
|
-
// console.log('ImageScene:loading');
|
|
134
|
-
this.#startLoading();
|
|
135
|
-
}
|
|
136
|
-
else if(currentState === STATE_ABORTING )
|
|
137
|
-
{
|
|
138
|
-
// console.log('ImageScene:aborting');
|
|
139
|
-
this.#startAbort();
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
this.state = currentState;
|
|
143
|
-
};
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/* ==== Common loader interface */
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Get image scene loading progress
|
|
150
|
-
*/
|
|
151
|
-
get progress() {
|
|
152
|
-
return this.#progress;
|
|
29
|
+
super();
|
|
153
30
|
}
|
|
154
31
|
|
|
155
|
-
|
|
156
|
-
* Get image scene abort progress
|
|
157
|
-
*/
|
|
158
|
-
get abortProgress() {
|
|
159
|
-
return this.#abortProgress;
|
|
160
|
-
}
|
|
32
|
+
/* ==== SceneBase implementation */
|
|
161
33
|
|
|
162
34
|
/**
|
|
163
|
-
*
|
|
35
|
+
* Get the array of image sources managed by this scene
|
|
36
|
+
*
|
|
37
|
+
* @returns {ImageSceneSource[]}
|
|
164
38
|
*/
|
|
165
|
-
|
|
166
|
-
this.#
|
|
39
|
+
get sources() {
|
|
40
|
+
return this.#imageSources;
|
|
167
41
|
}
|
|
168
42
|
|
|
169
43
|
/**
|
|
170
|
-
*
|
|
44
|
+
* Extract the image loader from a source object
|
|
45
|
+
*
|
|
46
|
+
* @param {ImageSceneSource} source
|
|
47
|
+
*
|
|
48
|
+
* @returns {ImageLoader}
|
|
171
49
|
*/
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
destroy() {
|
|
177
|
-
// TODO: disconnect all image sources?
|
|
178
|
-
// TODO: Unload ImageLoaders?
|
|
50
|
+
// eslint-disable-next-line no-unused-vars
|
|
51
|
+
getLoaderFromSource(source) {
|
|
52
|
+
return source.imageLoader;
|
|
179
53
|
}
|
|
180
54
|
|
|
181
55
|
/* ==== Source definitions */
|
|
@@ -241,18 +115,6 @@ export default class ImageScene {
|
|
|
241
115
|
return source.imageLoader.getObjectURL();
|
|
242
116
|
}
|
|
243
117
|
|
|
244
|
-
async #startLoading() {
|
|
245
|
-
for (const { imageLoader } of this.#imageSources) {
|
|
246
|
-
imageLoader.load();
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
#startAbort() {
|
|
251
|
-
for (const { imageLoader } of this.#imageSources) {
|
|
252
|
-
imageLoader.abort();
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
|
|
256
118
|
/* ==== Internals */
|
|
257
119
|
|
|
258
120
|
/**
|
|
@@ -129,12 +129,32 @@ export class ServiceManager extends EventEmitter {
|
|
|
129
129
|
*/
|
|
130
130
|
isRunning(name: string): Promise<boolean>;
|
|
131
131
|
/**
|
|
132
|
-
*
|
|
132
|
+
* Listen to log messages emitted by individual services
|
|
133
133
|
*
|
|
134
|
-
* @param {
|
|
135
|
-
*
|
|
134
|
+
* @param {Function} listener - Log event handler
|
|
135
|
+
*
|
|
136
|
+
* @returns {Function} Unsubscribe function
|
|
137
|
+
*/
|
|
138
|
+
onServiceLogEvent(listener: Function): Function;
|
|
139
|
+
/**
|
|
140
|
+
* Set log level for the ServiceManager itself
|
|
141
|
+
*
|
|
142
|
+
* @param {string} level - Log level to set for the ServiceManager
|
|
143
|
+
*/
|
|
144
|
+
setManagerLogLevel(level: string): void;
|
|
145
|
+
/**
|
|
146
|
+
* Set log level for individual services
|
|
147
|
+
*
|
|
148
|
+
* @param {string|Object<string,string>} nameOrConfig
|
|
149
|
+
* Service configuration:
|
|
150
|
+
* - String with service name: 'auth' (requires level parameter)
|
|
151
|
+
* - String with config: 'auth:debug,database:info'
|
|
152
|
+
* - Object: { auth: 'debug', database: 'info' }
|
|
153
|
+
* @param {string} [level] - Log level (required when nameOrConfig is service name)
|
|
136
154
|
*/
|
|
137
|
-
|
|
155
|
+
setServiceLogLevel(nameOrConfig: string | {
|
|
156
|
+
[x: string]: string;
|
|
157
|
+
}, level?: string): void;
|
|
138
158
|
/**
|
|
139
159
|
* Get all services with a specific tag
|
|
140
160
|
*
|