@quicktvui/web-renderer 1.0.0

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.
Files changed (56) hide show
  1. package/package.json +24 -0
  2. package/src/adapters/es3-video-player.js +828 -0
  3. package/src/components/Modal.js +119 -0
  4. package/src/components/QtAnimationView.js +678 -0
  5. package/src/components/QtBaseComponent.js +165 -0
  6. package/src/components/QtFastListView.js +1920 -0
  7. package/src/components/QtFlexView.js +799 -0
  8. package/src/components/QtImage.js +203 -0
  9. package/src/components/QtItemFrame.js +239 -0
  10. package/src/components/QtItemStoreView.js +93 -0
  11. package/src/components/QtItemView.js +125 -0
  12. package/src/components/QtListView.js +331 -0
  13. package/src/components/QtLoadingView.js +55 -0
  14. package/src/components/QtPageRootView.js +19 -0
  15. package/src/components/QtPlayMark.js +168 -0
  16. package/src/components/QtProgressBar.js +199 -0
  17. package/src/components/QtQRCode.js +78 -0
  18. package/src/components/QtReplaceChild.js +149 -0
  19. package/src/components/QtRippleView.js +166 -0
  20. package/src/components/QtSeekBar.js +409 -0
  21. package/src/components/QtText.js +679 -0
  22. package/src/components/QtTransitionImage.js +170 -0
  23. package/src/components/QtView.js +706 -0
  24. package/src/components/QtWebView.js +613 -0
  25. package/src/components/TabsView.js +420 -0
  26. package/src/components/ViewPager.js +206 -0
  27. package/src/components/index.js +24 -0
  28. package/src/components/plugins/TextV2Component.js +70 -0
  29. package/src/components/plugins/index.js +7 -0
  30. package/src/core/SceneBuilder.js +58 -0
  31. package/src/core/TVFocusManager.js +2014 -0
  32. package/src/core/asyncLocalStorage.js +175 -0
  33. package/src/core/autoProxy.js +165 -0
  34. package/src/core/componentRegistry.js +84 -0
  35. package/src/core/constants.js +6 -0
  36. package/src/core/index.js +8 -0
  37. package/src/core/moduleUtils.js +36 -0
  38. package/src/core/patches.js +958 -0
  39. package/src/core/templateBinding.js +666 -0
  40. package/src/index.js +246 -0
  41. package/src/modules/AndroidDevelopModule.js +101 -0
  42. package/src/modules/AndroidDeviceModule.js +341 -0
  43. package/src/modules/AndroidNetworkModule.js +178 -0
  44. package/src/modules/AndroidSharedPreferencesModule.js +100 -0
  45. package/src/modules/ESDeviceInfoModule.js +450 -0
  46. package/src/modules/ESGroupDataModule.js +195 -0
  47. package/src/modules/ESIJKAudioPlayerModule.js +477 -0
  48. package/src/modules/ESLocalStorageModule.js +100 -0
  49. package/src/modules/ESLogModule.js +65 -0
  50. package/src/modules/ESModule.js +106 -0
  51. package/src/modules/ESNetworkSpeedModule.js +117 -0
  52. package/src/modules/ESToastModule.js +172 -0
  53. package/src/modules/EsNativeModule.js +117 -0
  54. package/src/modules/FastListModule.js +101 -0
  55. package/src/modules/FocusModule.js +145 -0
  56. package/src/modules/RuntimeDeviceModule.js +176 -0
@@ -0,0 +1,477 @@
1
+ // ESIJKAudioPlayerModule - Web adapter for ES IJK Audio Player
2
+ // Uses HTML5 Audio API to implement audio playback
3
+
4
+ import { resolveAddon, createModuleInit } from '../core/moduleUtils'
5
+
6
+ // Player states (matching native ESPlayerState)
7
+ const ESPlayerState = {
8
+ ES_PLAYER_STATE_IDLE: 0,
9
+ ES_PLAYER_STATE_PREPARING: 1,
10
+ ES_PLAYER_STATE_PREPARED: 2,
11
+ ES_PLAYER_STATE_BUFFER_START: 3,
12
+ ES_PLAYER_STATE_BUFFER_END: 4,
13
+ ES_PLAYER_STATE_PLAYING: 5,
14
+ ES_PLAYER_STATE_SEEK_START: 6,
15
+ ES_PLAYER_STATE_SEEK_COMPLETED: 7,
16
+ ES_PLAYER_STATE_PAUSED: 8,
17
+ ES_PLAYER_STATE_RESUMED: 9,
18
+ ES_PLAYER_STATE_BEFORE_STOP: 10,
19
+ ES_PLAYER_STATE_STOP: 11,
20
+ ES_PLAYER_STATE_PLAYBACK_COMPLETED: 12,
21
+ ES_PLAYER_STATE_ERROR: 13,
22
+ ES_PLAYER_STATE_VIDEO_SIZE_CHANGED: 14,
23
+ ES_PLAYER_STATE_PLAYER_VIEW_CHANGED: 15,
24
+ ES_PLAYER_STATE_AD_START: 16,
25
+ ES_PLAYER_STATE_AD_END: 17,
26
+ ES_PLAYER_STATE_AD_SKIP: 18,
27
+ ES_PLAYER_STATE_AD_PAUSED: 19,
28
+ ES_PLAYER_STATE_AUTHORIZED: 20,
29
+ ES_PLAYER_STATE_SET_PLAY_RATE_SUCCESS: 21,
30
+ ES_PLAYER_STATE_SET_PLAY_RATE_ERROR: 22,
31
+ ES_PLAYER_STATE_AD_RESUMED: 23,
32
+ ES_PLAYER_STATE_AD_LOADED: 24,
33
+ ES_PLAYER_STATE_AD_TIME: 25,
34
+ ES_PLAYER_STATE_PLAYER_INITIALIZED: 26,
35
+ ES_PLAYER_STATE_TIMED_TEXT_CHANGED: 27,
36
+ ES_PLAYER_STATE_PLAYER_CLICKABLE: 28,
37
+ ES_PLAYER_STATE_INITIALIZE_SUCCESS: 29,
38
+ ES_PLAYER_STATE_INITIALIZE_ERROR: 30,
39
+ }
40
+
41
+ // Get EventBus lazily
42
+ let _eventBus = null
43
+ function getEventBus() {
44
+ if (!_eventBus) {
45
+ try {
46
+ const esVue = require('@extscreen/es3-vue')
47
+ if (esVue && esVue.EventBus) {
48
+ _eventBus = esVue.EventBus
49
+ }
50
+ } catch (e) {
51
+ console.warn('[ESIJKAudioPlayerModule] EventBus not available:', e.message)
52
+ }
53
+ }
54
+ return _eventBus
55
+ }
56
+
57
+ // Dispatch event to EventBus
58
+ function dispatchEvent(eventName, data) {
59
+ const eventBus = getEventBus()
60
+ if (eventBus && eventBus.$emit) {
61
+ eventBus.$emit(eventName, data)
62
+ }
63
+ // Also dispatch custom event for global listeners
64
+ if (typeof window !== 'undefined') {
65
+ window.dispatchEvent(new CustomEvent(eventName, { detail: data }))
66
+ }
67
+ }
68
+
69
+ // Audio instance manager
70
+ class AudioPlayerManager {
71
+ constructor() {
72
+ this.instances = new Map()
73
+ this.defaultPlayRate = 1.0
74
+ this.defaultVolume = 1.0
75
+ }
76
+
77
+ // Get or create audio instance with event binding
78
+ getInstance(id) {
79
+ if (!this.instances.has(id)) {
80
+ const audio = new Audio()
81
+ audio.defaultPlaybackRate = this.defaultPlayRate
82
+ audio.volume = this.defaultVolume
83
+ this._bindAudioEvents(audio, id)
84
+ this.instances.set(id, audio)
85
+ }
86
+ return this.instances.get(id)
87
+ }
88
+
89
+ _bindAudioEvents(audio, id) {
90
+ // Track if we've sent PREPARED for current source
91
+ let hasPrepared = false
92
+ let currentState = ESPlayerState.ES_PLAYER_STATE_IDLE
93
+
94
+ // Play event
95
+ audio.addEventListener('play', () => {
96
+ if (currentState !== ESPlayerState.ES_PLAYER_STATE_PLAYING) {
97
+ currentState = ESPlayerState.ES_PLAYER_STATE_PLAYING
98
+ dispatchEvent('onESAudioPlayerStatusChanged', {
99
+ playerStatus: ESPlayerState.ES_PLAYER_STATE_PLAYING,
100
+ playerState: ESPlayerState.ES_PLAYER_STATE_PLAYING,
101
+ })
102
+ }
103
+ })
104
+
105
+ // Playing event (after buffering) - don't send PREPARED again!
106
+ audio.addEventListener('playing', () => {
107
+ if (currentState !== ESPlayerState.ES_PLAYER_STATE_PLAYING) {
108
+ currentState = ESPlayerState.ES_PLAYER_STATE_PLAYING
109
+ dispatchEvent('onESAudioPlayerStatusChanged', {
110
+ playerStatus: ESPlayerState.ES_PLAYER_STATE_PLAYING,
111
+ playerState: ESPlayerState.ES_PLAYER_STATE_PLAYING,
112
+ })
113
+ }
114
+ })
115
+
116
+ // Pause event
117
+ audio.addEventListener('pause', () => {
118
+ currentState = ESPlayerState.ES_PLAYER_STATE_PAUSED
119
+ dispatchEvent('onESAudioPlayerStatusChanged', {
120
+ playerStatus: ESPlayerState.ES_PLAYER_STATE_PAUSED,
121
+ playerState: ESPlayerState.ES_PLAYER_STATE_PAUSED,
122
+ })
123
+ })
124
+
125
+ // Ended event
126
+ audio.addEventListener('ended', () => {
127
+ currentState = ESPlayerState.ES_PLAYER_STATE_PLAYBACK_COMPLETED
128
+ hasPrepared = true // Prevent canplay from sending PREPARED again
129
+ dispatchEvent('onESAudioPlayerStatusChanged', {
130
+ playerStatus: ESPlayerState.ES_PLAYER_STATE_PLAYBACK_COMPLETED,
131
+ playerState: ESPlayerState.ES_PLAYER_STATE_PLAYBACK_COMPLETED,
132
+ })
133
+ })
134
+
135
+ // Error event
136
+ audio.addEventListener('error', (e) => {
137
+ currentState = ESPlayerState.ES_PLAYER_STATE_ERROR
138
+ dispatchEvent('onESAudioPlayerError', {
139
+ errorCode: e.target.error?.code || -1,
140
+ errorMessage: e.target.error?.message || 'Audio error',
141
+ })
142
+ })
143
+
144
+ // Load start (preparing)
145
+ audio.addEventListener('loadstart', () => {
146
+ hasPrepared = false
147
+ currentState = ESPlayerState.ES_PLAYER_STATE_PREPARING
148
+ dispatchEvent('onESAudioPlayerStatusChanged', {
149
+ playerStatus: ESPlayerState.ES_PLAYER_STATE_PREPARING,
150
+ playerState: ESPlayerState.ES_PLAYER_STATE_PREPARING,
151
+ })
152
+ })
153
+
154
+ // Can play (prepared) - only send once per source
155
+ audio.addEventListener('canplay', () => {
156
+ if (!hasPrepared) {
157
+ hasPrepared = true
158
+ currentState = ESPlayerState.ES_PLAYER_STATE_PREPARED
159
+ dispatchEvent('onESAudioPlayerStatusChanged', {
160
+ playerStatus: ESPlayerState.ES_PLAYER_STATE_PREPARED,
161
+ playerState: ESPlayerState.ES_PLAYER_STATE_PREPARED,
162
+ })
163
+ }
164
+ })
165
+
166
+ // Waiting (buffering)
167
+ audio.addEventListener('waiting', () => {
168
+ dispatchEvent('onESAudioPlayerStatusChanged', {
169
+ playerStatus: ESPlayerState.ES_PLAYER_STATE_BUFFER_START,
170
+ playerState: ESPlayerState.ES_PLAYER_STATE_BUFFER_START,
171
+ })
172
+ })
173
+
174
+ // Can play through (buffer end)
175
+ audio.addEventListener('canplaythrough', () => {
176
+ dispatchEvent('onESAudioPlayerStatusChanged', {
177
+ playerStatus: ESPlayerState.ES_PLAYER_STATE_BUFFER_END,
178
+ playerState: ESPlayerState.ES_PLAYER_STATE_BUFFER_END,
179
+ })
180
+ })
181
+
182
+ // Duration change
183
+ audio.addEventListener('durationchange', () => {
184
+ if (audio.duration && !isNaN(audio.duration)) {
185
+ dispatchEvent('onESAudioPlayerInfo', {
186
+ what: 1, // MEDIA_INFO_DURATION
187
+ extra: Math.floor(audio.duration * 1000),
188
+ })
189
+ }
190
+ })
191
+
192
+ // Rate change
193
+ audio.addEventListener('ratechange', () => {
194
+ dispatchEvent('onESAudioPlayRateChanged', {
195
+ playRate: audio.playbackRate,
196
+ })
197
+ })
198
+
199
+ // Seeking
200
+ audio.addEventListener('seeking', () => {
201
+ dispatchEvent('onESAudioPlayerStatusChanged', {
202
+ playerStatus: ESPlayerState.ES_PLAYER_STATE_SEEK_START,
203
+ playerState: ESPlayerState.ES_PLAYER_STATE_SEEK_START,
204
+ })
205
+ })
206
+
207
+ // Seeked
208
+ audio.addEventListener('seeked', () => {
209
+ dispatchEvent('onESAudioPlayerStatusChanged', {
210
+ playerStatus: ESPlayerState.ES_PLAYER_STATE_SEEK_COMPLETED,
211
+ playerState: ESPlayerState.ES_PLAYER_STATE_SEEK_COMPLETED,
212
+ })
213
+ })
214
+
215
+ // Volume change
216
+ audio.addEventListener('volumechange', () => {
217
+ dispatchEvent('onESAudioPlayerInfo', {
218
+ what: 2, // MEDIA_INFO_VOLUME_CHANGED
219
+ extra: Math.floor(audio.volume * 100),
220
+ })
221
+ })
222
+ }
223
+
224
+ // Remove audio instance
225
+ removeInstance(id) {
226
+ const audio = this.instances.get(id)
227
+ if (audio) {
228
+ audio.pause()
229
+ audio.src = ''
230
+ this.instances.delete(id)
231
+ }
232
+ }
233
+
234
+ // Clear all instances
235
+ clearAll() {
236
+ this.instances.forEach((audio, id) => {
237
+ audio.pause()
238
+ audio.src = ''
239
+ })
240
+ this.instances.clear()
241
+ }
242
+ }
243
+
244
+ const audioManager = new AudioPlayerManager()
245
+
246
+ export class ESIJKAudioPlayerModule {
247
+ constructor(context) {
248
+ this.context = context
249
+ this.name = ''
250
+ this.mode = 'normal'
251
+ }
252
+
253
+ async init(...args) {
254
+ // Send initialized event
255
+ dispatchEvent('onESAudioPlayerStatusChanged', {
256
+ playerStatus: ESPlayerState.ES_PLAYER_STATE_PLAYER_INITIALIZED,
257
+ playerState: ESPlayerState.ES_PLAYER_STATE_PLAYER_INITIALIZED,
258
+ })
259
+ // Send init success
260
+ dispatchEvent('onESAudioPlayerStatusChanged', {
261
+ playerStatus: ESPlayerState.ES_PLAYER_STATE_INITIALIZE_SUCCESS,
262
+ playerState: ESPlayerState.ES_PLAYER_STATE_INITIALIZE_SUCCESS,
263
+ })
264
+ return createModuleInit(args)
265
+ }
266
+
267
+ initMediaPlayer(...args) {
268
+ // Send initialized event
269
+ dispatchEvent('onESAudioPlayerStatusChanged', {
270
+ playerStatus: ESPlayerState.ES_PLAYER_STATE_PLAYER_INITIALIZED,
271
+ playerState: ESPlayerState.ES_PLAYER_STATE_PLAYER_INITIALIZED,
272
+ })
273
+ // Send init success
274
+ dispatchEvent('onESAudioPlayerStatusChanged', {
275
+ playerStatus: ESPlayerState.ES_PLAYER_STATE_INITIALIZE_SUCCESS,
276
+ playerState: ESPlayerState.ES_PLAYER_STATE_INITIALIZE_SUCCESS,
277
+ })
278
+ return resolveAddon(args, null)
279
+ }
280
+
281
+ play(id, ...params) {
282
+ console.log('[ESIJKAudioPlayerModule] play called with id:', id, 'params:', params)
283
+ const audio = audioManager.getInstance(id)
284
+ const args = params || []
285
+
286
+ // Parse play parameters
287
+ // Can be:
288
+ // 1. URL string: play(-1, 'https://...')
289
+ // 2. URL in array: play(-1, ['https://...'])
290
+ // 3. Object: play(-1, { url: '...', uri: '...' })
291
+ let url = ''
292
+ let autoplay = true
293
+
294
+ if (args.length > 0) {
295
+ const firstArg = args[0]
296
+
297
+ // Check if it's a string (direct URL)
298
+ if (typeof firstArg === 'string') {
299
+ url = firstArg
300
+ }
301
+ // Check if it's an array with URL string
302
+ else if (Array.isArray(firstArg) && typeof firstArg[0] === 'string') {
303
+ url = firstArg[0]
304
+ }
305
+ // Check if it's an object with url/src/uri
306
+ else if (typeof firstArg === 'object' && firstArg !== null && !Array.isArray(firstArg)) {
307
+ url = firstArg.url || firstArg.src || firstArg.uri || ''
308
+ autoplay = firstArg.autoplay !== false
309
+ }
310
+ }
311
+
312
+ console.log('[ESIJKAudioPlayerModule] parsed url:', url, 'autoplay:', autoplay)
313
+
314
+ if (url) {
315
+ audio.src = url
316
+ audio.load()
317
+ }
318
+
319
+ if (autoplay && audio.src) {
320
+ audio.play().catch((e) => {
321
+ console.warn('[ESIJKAudioPlayerModule] play error:', e)
322
+ dispatchEvent('onESAudioPlayerError', {
323
+ errorCode: -1,
324
+ errorMessage: e.message || 'Play error',
325
+ })
326
+ })
327
+ }
328
+ return resolveAddon(args, null)
329
+ }
330
+
331
+ start(id, ...args) {
332
+ const audio = audioManager.getInstance(id)
333
+ if (audio.src) {
334
+ audio.play().catch((e) => {
335
+ console.warn('[ESIJKAudioPlayerModule] start error:', e)
336
+ })
337
+ }
338
+ return resolveAddon(args, null)
339
+ }
340
+
341
+ pause(id, ...args) {
342
+ const audio = audioManager.getInstance(id)
343
+ audio.pause()
344
+ return resolveAddon(args, null)
345
+ }
346
+
347
+ resume(id, ...args) {
348
+ const audio = audioManager.getInstance(id)
349
+ audio.play().catch((e) => {
350
+ console.warn('[ESIJKAudioPlayerModule] resume error:', e)
351
+ })
352
+ // Send resumed event
353
+ dispatchEvent('onESAudioPlayerStatusChanged', {
354
+ playerStatus: ESPlayerState.ES_PLAYER_STATE_RESUMED,
355
+ playerState: ESPlayerState.ES_PLAYER_STATE_RESUMED,
356
+ })
357
+ return resolveAddon(args, null)
358
+ }
359
+
360
+ seekTo(id, progress, ...args) {
361
+ const audio = audioManager.getInstance(id)
362
+ if (audio.duration && progress >= 0) {
363
+ audio.currentTime = Math.min(progress / 1000, audio.duration) // progress is in ms
364
+ }
365
+ return resolveAddon(args, null)
366
+ }
367
+
368
+ stop(id, ...args) {
369
+ const audio = audioManager.getInstance(id)
370
+ // Send before stop event
371
+ dispatchEvent('onESAudioPlayerStatusChanged', {
372
+ playerStatus: ESPlayerState.ES_PLAYER_STATE_BEFORE_STOP,
373
+ playerState: ESPlayerState.ES_PLAYER_STATE_BEFORE_STOP,
374
+ })
375
+ audio.pause()
376
+ audio.currentTime = 0
377
+ // Send stopped event
378
+ dispatchEvent('onESAudioPlayerStatusChanged', {
379
+ playerStatus: ESPlayerState.ES_PLAYER_STATE_STOP,
380
+ playerState: ESPlayerState.ES_PLAYER_STATE_STOP,
381
+ })
382
+ return resolveAddon(args, null)
383
+ }
384
+
385
+ setPlayRate(id, speed, ...args) {
386
+ const audio = audioManager.getInstance(id)
387
+ audio.playbackRate = Number(speed) || 1.0
388
+ dispatchEvent('onESAudioPlayRateChanged', {
389
+ playRate: audio.playbackRate,
390
+ })
391
+ return resolveAddon(args, null)
392
+ }
393
+
394
+ setVolume(id, volume, ...args) {
395
+ const audio = audioManager.getInstance(id)
396
+ audio.volume = Math.max(0, Math.min(1, Number(volume) || 0))
397
+ return resolveAddon(args, null)
398
+ }
399
+
400
+ setLeftRightVolume(id, leftVolume, rightVolume, ...args) {
401
+ const audio = audioManager.getInstance(id)
402
+ // HTML5 Audio doesn't support stereo balance, use average
403
+ const avgVolume = (Number(leftVolume) + Number(rightVolume)) / 2
404
+ audio.volume = Math.max(0, Math.min(1, avgVolume || 0))
405
+ return resolveAddon(args, null)
406
+ }
407
+
408
+ reset(id, ...args) {
409
+ const audio = audioManager.getInstance(id)
410
+ audio.pause()
411
+ audio.currentTime = 0
412
+ audio.src = ''
413
+ return resolveAddon(args, null)
414
+ }
415
+
416
+ release(id, ...args) {
417
+ audioManager.removeInstance(id)
418
+ return resolveAddon(args, null)
419
+ }
420
+
421
+ async isPlaying(id, ...args) {
422
+ const audio = audioManager.getInstance(id)
423
+ const result = !audio.paused && audio.currentTime > 0
424
+ return resolveAddon(args, result)
425
+ }
426
+
427
+ async isPaused(id, ...args) {
428
+ const audio = audioManager.getInstance(id)
429
+ const result = audio.paused
430
+ return resolveAddon(args, result)
431
+ }
432
+
433
+ async getDuration(id, ...args) {
434
+ const audio = audioManager.getInstance(id)
435
+ // Return duration in milliseconds
436
+ const duration = audio.duration && !isNaN(audio.duration) ? audio.duration * 1000 : -1
437
+ return resolveAddon(args, duration)
438
+ }
439
+
440
+ async getCurrentPosition(id, ...args) {
441
+ const audio = audioManager.getInstance(id)
442
+ // Return position in milliseconds
443
+ const position = audio.currentTime && !isNaN(audio.currentTime) ? audio.currentTime * 1000 : 0
444
+ return resolveAddon(args, position)
445
+ }
446
+
447
+ async getBufferPercentage(id, ...args) {
448
+ const audio = audioManager.getInstance(id)
449
+ if (audio.buffered.length > 0 && audio.duration > 0) {
450
+ const bufferedEnd = audio.buffered.end(audio.buffered.length - 1)
451
+ const percentage = Math.round((bufferedEnd / audio.duration) * 100)
452
+ return resolveAddon(args, percentage)
453
+ }
454
+ return resolveAddon(args, 0)
455
+ }
456
+
457
+ async getCurrentPlayRate(id, ...args) {
458
+ const audio = audioManager.getInstance(id)
459
+ return resolveAddon(args, audio.playbackRate || 1.0)
460
+ }
461
+
462
+ async getLeftVolume(id, ...args) {
463
+ const audio = audioManager.getInstance(id)
464
+ // HTML5 Audio doesn't support stereo, return same as volume
465
+ return resolveAddon(args, audio.volume)
466
+ }
467
+
468
+ async getRightVolume(id, ...args) {
469
+ const audio = audioManager.getInstance(id)
470
+ // HTML5 Audio doesn't support stereo, return same as volume
471
+ return resolveAddon(args, audio.volume)
472
+ }
473
+
474
+ destroy() {
475
+ audioManager.clearAll()
476
+ }
477
+ }
@@ -0,0 +1,100 @@
1
+ import { resolveAddon, createModuleInit } from '../core/moduleUtils'
2
+
3
+ function getRawStorage() {
4
+ const g = globalThis
5
+ return (g && g.__localStorage) || (g && g.localStorage) || null
6
+ }
7
+
8
+ async function readStorage(key) {
9
+ const s = getRawStorage()
10
+ if (!s || !s.getItem) return null
11
+ const v = s.getItem(key)
12
+ return v && typeof v.then === 'function' ? await v : v
13
+ }
14
+
15
+ async function writeStorage(key, value) {
16
+ const s = getRawStorage()
17
+ if (!s || !s.setItem) return false
18
+ const r = s.setItem(key, value)
19
+ if (r && typeof r.then === 'function') await r
20
+ return true
21
+ }
22
+
23
+ export class ESLocalStorageModule {
24
+ constructor(context) {
25
+ this.context = context
26
+ this.name = ''
27
+ this.mode = 'normal'
28
+ this._name = ''
29
+ }
30
+
31
+ _key(key) {
32
+ if (!this._name) return key
33
+ return `${this._name}:${key}`
34
+ }
35
+
36
+ async initSharedPreferences(name, ...args) {
37
+ this._name = String(name ?? '')
38
+ return resolveAddon(args, true)
39
+ }
40
+
41
+ async initESSharedPreferences(name, ...args) {
42
+ this._name = String(name ?? '')
43
+ return resolveAddon(args, true)
44
+ }
45
+
46
+ async getBoolean(key, defValue, ...args) {
47
+ const v = await readStorage(this._key(String(key)))
48
+ if (v === null || v === undefined) return resolveAddon(args, !!defValue)
49
+ if (v === 'true') return resolveAddon(args, true)
50
+ if (v === 'false') return resolveAddon(args, false)
51
+ if (v === '1') return resolveAddon(args, true)
52
+ if (v === '0') return resolveAddon(args, false)
53
+ return resolveAddon(args, !!defValue)
54
+ }
55
+
56
+ async putBoolean(key, value, ...args) {
57
+ const ok = await writeStorage(this._key(String(key)), value ? 'true' : 'false')
58
+ return resolveAddon(args, ok)
59
+ }
60
+
61
+ async getInt(key, defValue, ...args) {
62
+ const v = await readStorage(this._key(String(key)))
63
+ if (v === null || v === undefined || v === '') return resolveAddon(args, Number(defValue) || 0)
64
+ const n = Number.parseInt(String(v), 10)
65
+ return resolveAddon(args, Number.isFinite(n) ? n : Number(defValue) || 0)
66
+ }
67
+
68
+ async putInt(key, value, ...args) {
69
+ const ok = await writeStorage(this._key(String(key)), String(Number(value) | 0))
70
+ return resolveAddon(args, ok)
71
+ }
72
+
73
+ async getLong(key, defValue, ...args) {
74
+ const v = await readStorage(this._key(String(key)))
75
+ if (v === null || v === undefined || v === '') return resolveAddon(args, Number(defValue) || 0)
76
+ const n = Number.parseInt(String(v), 10)
77
+ return resolveAddon(args, Number.isFinite(n) ? n : Number(defValue) || 0)
78
+ }
79
+
80
+ async putLong(key, value, ...args) {
81
+ const ok = await writeStorage(this._key(String(key)), String(Math.trunc(Number(value))))
82
+ return resolveAddon(args, ok)
83
+ }
84
+
85
+ async getString(key, defValue, ...args) {
86
+ const v = await readStorage(this._key(String(key)))
87
+ return resolveAddon(args, v === null || v === undefined ? String(defValue ?? '') : String(v))
88
+ }
89
+
90
+ async putString(key, value, ...args) {
91
+ const ok = await writeStorage(this._key(String(key)), String(value ?? ''))
92
+ return resolveAddon(args, ok)
93
+ }
94
+
95
+ async init(...args) {
96
+ return createModuleInit(args)
97
+ }
98
+
99
+ destroy() {}
100
+ }
@@ -0,0 +1,65 @@
1
+ // ESLogModule - Web adapter for ES Log Module
2
+ // Uses console API for logging
3
+
4
+ import { resolveAddon, createModuleInit } from '../core/moduleUtils'
5
+
6
+ export class ESLogModule {
7
+ constructor(context) {
8
+ this.context = context
9
+ this.name = ''
10
+ this.mode = 'normal'
11
+ this.enabled = true
12
+ }
13
+
14
+ async init(...args) {
15
+ return createModuleInit(args)
16
+ }
17
+
18
+ destroy() {}
19
+
20
+ v(tag, ...args) {
21
+ if (!this.enabled) return
22
+ console.log(`[V][${tag}]`, ...args)
23
+ }
24
+
25
+ d(tag, ...args) {
26
+ if (!this.enabled) return
27
+ console.debug(`[D][${tag}]`, ...args)
28
+ }
29
+
30
+ i(tag, ...args) {
31
+ if (!this.enabled) return
32
+ console.info(`[I][${tag}]`, ...args)
33
+ }
34
+
35
+ w(tag, ...args) {
36
+ if (!this.enabled) return
37
+ console.warn(`[W][${tag}]`, ...args)
38
+ }
39
+
40
+ e(tag, ...args) {
41
+ if (!this.enabled) return
42
+ console.error(`[E][${tag}]`, ...args)
43
+ }
44
+
45
+ f(tag, ...args) {
46
+ if (!this.enabled) return
47
+ console.error(`[F][${tag}]`, ...args)
48
+ }
49
+
50
+ async getEsInfo(...args) {
51
+ const info = {
52
+ version: 'web',
53
+ platform: 'web',
54
+ }
55
+ return resolveAddon(args, info)
56
+ }
57
+
58
+ setEnabled(enabled) {
59
+ this.enabled = enabled
60
+ }
61
+
62
+ isEnabled() {
63
+ return this.enabled
64
+ }
65
+ }