tiny-essentials 1.27.1 → 1.28.1
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/README.md +1 -0
- package/changelog/1/28/0.md +16 -0
- package/changelog/1/28/1.md +23 -0
- package/dist/v1/TinyAdvancedRaffle.min.js +1 -1
- package/dist/v1/TinyAfterScrollWatcher.min.js +1 -1
- package/dist/v1/TinyAnalogClock.min.js +1 -1
- package/dist/v1/TinyBasicsEs.min.js +1 -2
- package/dist/v1/TinyDayNightCycle.min.js +1 -1
- package/dist/v1/TinyDragDropDetector.min.js +1 -1
- package/dist/v1/TinyDragger.min.js +1 -1
- package/dist/v1/TinyElementObserver.min.js +1 -1
- package/dist/v1/TinyEssentials.min.js +1 -2
- package/dist/v1/TinyGamepad.min.js +1 -1
- package/dist/v1/TinyHtml.min.js +1 -1
- package/dist/v1/TinyI18.min.js +1 -1
- package/dist/v1/TinyIframeEvents.min.js +1 -1
- package/dist/v1/TinyLocalStorage.min.js +1 -1
- package/dist/v1/TinyMediaPlayer.min.js +1 -1
- package/dist/v1/TinyNewWinEvents.min.js +1 -1
- package/dist/v1/TinyNotifyCenter.min.js +1 -1
- package/dist/v1/TinyRadioFm.min.js +1 -1
- package/dist/v1/TinyRateLimiter.min.js +1 -1
- package/dist/v1/TinySmartScroller.min.js +1 -1
- package/dist/v1/TinyTextDiffer.min.js +1 -1
- package/dist/v1/TinyTextarea.min.js +1 -1
- package/dist/v1/TinyTimeout.min.js +1 -1
- package/dist/v1/TinyToastNotify.min.js +1 -1
- package/dist/v1/TinyUploadClicker.min.js +1 -2
- package/dist/v1/UltraRandomMsgGen.min.js +1 -1
- package/dist/v1/basics/array.cjs +57 -9
- package/dist/v1/basics/array.d.mts +27 -11
- package/dist/v1/basics/array.mjs +51 -9
- package/dist/v1/basics/clock.cjs +94 -42
- package/dist/v1/basics/clock.d.mts +10 -10
- package/dist/v1/basics/clock.mjs +91 -54
- package/dist/v1/basics/deprecated/html.cjs +246 -0
- package/dist/v1/basics/deprecated/html.d.mts +63 -0
- package/dist/v1/basics/deprecated/html.mjs +190 -0
- package/dist/v1/basics/extendObjType/Buffer.cjs +13 -0
- package/dist/v1/basics/extendObjType/Buffer.d.mts +4 -0
- package/dist/v1/basics/extendObjType/Buffer.mjs +8 -0
- package/dist/v1/basics/html.cjs +149 -130
- package/dist/v1/basics/html.d.mts +26 -61
- package/dist/v1/basics/html.mjs +113 -105
- package/dist/v1/basics/index.cjs +2 -0
- package/dist/v1/basics/index.d.mts +3 -1
- package/dist/v1/basics/index.mjs +3 -3
- package/dist/v1/basics/mediaContent.cjs +51 -9
- package/dist/v1/basics/mediaContent.d.mts +0 -87
- package/dist/v1/basics/mediaContent.mjs +40 -10
- package/dist/v1/basics/objChecker.cjs +7 -5
- package/dist/v1/basics/objChecker.d.mts +3 -2
- package/dist/v1/basics/objChecker.mjs +6 -6
- package/dist/v1/basics/objFilter.cjs +40 -18
- package/dist/v1/basics/objFilter.d.mts +6 -6
- package/dist/v1/basics/objFilter.mjs +32 -17
- package/dist/v1/basics/simpleMath.cjs +81 -25
- package/dist/v1/basics/simpleMath.d.mts +2 -2
- package/dist/v1/basics/simpleMath.mjs +70 -27
- package/dist/v1/basics/text.cjs +76 -31
- package/dist/v1/basics/text.d.mts +69 -7
- package/dist/v1/basics/text.mjs +62 -31
- package/dist/v1/index.cjs +4 -2
- package/dist/v1/index.d.mts +4 -2
- package/dist/v1/index.mjs +4 -4
- package/dist/v1/libs/TinyAdvancedRaffle.cjs +71 -255
- package/dist/v1/libs/TinyAdvancedRaffle.d.mts +6 -134
- package/dist/v1/libs/TinyAdvancedRaffle.mjs +69 -228
- package/dist/v1/libs/TinyAfterScrollWatcher.cjs +17 -1
- package/dist/v1/libs/TinyAfterScrollWatcher.d.mts +4 -1
- package/dist/v1/libs/TinyAfterScrollWatcher.mjs +15 -1
- package/dist/v1/libs/TinyAnalogClock.cjs +60 -0
- package/dist/v1/libs/TinyAnalogClock.d.mts +6 -0
- package/dist/v1/libs/TinyAnalogClock.mjs +57 -0
- package/dist/v1/libs/TinyClipboard.cjs +2 -0
- package/dist/v1/libs/TinyClipboard.d.mts +4 -2
- package/dist/v1/libs/TinyClipboard.mjs +2 -0
- package/dist/v1/libs/TinyColorConverter.cjs +1 -0
- package/dist/v1/libs/TinyColorConverter.d.mts +2 -1
- package/dist/v1/libs/TinyColorConverter.mjs +1 -0
- package/dist/v1/libs/TinyDayNightCycle.cjs +67 -42
- package/dist/v1/libs/TinyDayNightCycle.d.mts +2 -7
- package/dist/v1/libs/TinyDayNightCycle.mjs +65 -41
- package/dist/v1/libs/TinyDragDropDetector.cjs +25 -0
- package/dist/v1/libs/TinyDragDropDetector.d.mts +6 -0
- package/dist/v1/libs/TinyDragDropDetector.mjs +22 -0
- package/dist/v1/libs/TinyDragger.cjs +46 -19
- package/dist/v1/libs/TinyDragger.mjs +45 -18
- package/dist/v1/libs/TinyElementObserver.cjs +39 -0
- package/dist/v1/libs/TinyElementObserver.d.mts +6 -0
- package/dist/v1/libs/TinyElementObserver.mjs +36 -0
- package/dist/v1/libs/TinyGamepad.cjs +131 -1
- package/dist/v1/libs/TinyGamepad.mjs +129 -1
- package/dist/v1/libs/TinyHtml.cjs +1 -1
- package/dist/v1/libs/TinyHtml.mjs +2 -2
- package/dist/v1/libs/TinyI18.cjs +61 -0
- package/dist/v1/libs/TinyI18.d.mts +14 -0
- package/dist/v1/libs/TinyI18.mjs +55 -0
- package/dist/v1/libs/TinyIframeEvents.cjs +26 -196
- package/dist/v1/libs/TinyIframeEvents.d.mts +3 -122
- package/dist/v1/libs/TinyIframeEvents.mjs +26 -171
- package/dist/v1/libs/TinyLocalStorage.cjs +53 -205
- package/dist/v1/libs/TinyLocalStorage.d.mts +6 -127
- package/dist/v1/libs/TinyLocalStorage.mjs +50 -178
- package/dist/v1/libs/TinyMediaPlayer.cjs +74 -2
- package/dist/v1/libs/TinyMediaPlayer.d.mts +12 -2
- package/dist/v1/libs/TinyMediaPlayer.mjs +68 -2
- package/dist/v1/libs/TinyNewWinEvents.cjs +39 -197
- package/dist/v1/libs/TinyNewWinEvents.d.mts +6 -119
- package/dist/v1/libs/TinyNewWinEvents.mjs +36 -172
- package/dist/v1/libs/TinyNotifyCenter.cjs +36 -0
- package/dist/v1/libs/TinyNotifyCenter.d.mts +6 -0
- package/dist/v1/libs/TinyNotifyCenter.mjs +32 -0
- package/dist/v1/libs/TinyRadioFm.cjs +40 -3
- package/dist/v1/libs/TinyRadioFm.d.mts +3 -3
- package/dist/v1/libs/TinyRadioFm.mjs +37 -3
- package/dist/v1/libs/TinyRateLimiter.cjs +52 -0
- package/dist/v1/libs/TinyRateLimiter.d.mts +6 -0
- package/dist/v1/libs/TinyRateLimiter.mjs +48 -0
- package/dist/v1/libs/TinySmartScroller.cjs +56 -205
- package/dist/v1/libs/TinySmartScroller.d.mts +19 -152
- package/dist/v1/libs/TinySmartScroller.mjs +55 -181
- package/dist/v1/libs/TinyTextDiffer.cjs +19 -18
- package/dist/v1/libs/TinyTextDiffer.d.mts +1 -0
- package/dist/v1/libs/TinyTextDiffer.mjs +16 -17
- package/dist/v1/libs/TinyTextarea.cjs +19 -0
- package/dist/v1/libs/TinyTextarea.d.mts +6 -0
- package/dist/v1/libs/TinyTextarea.mjs +17 -0
- package/dist/v1/libs/TinyTimeout.cjs +11 -1
- package/dist/v1/libs/TinyTimeout.mjs +9 -1
- package/dist/v1/libs/TinyToastNotify.cjs +35 -0
- package/dist/v1/libs/TinyToastNotify.d.mts +6 -0
- package/dist/v1/libs/TinyToastNotify.mjs +31 -0
- package/dist/v1/libs/TinyUploadClicker.cjs +20 -0
- package/dist/v1/libs/TinyUploadClicker.d.mts +6 -0
- package/dist/v1/libs/TinyUploadClicker.mjs +17 -0
- package/dist/v1/libs/UltraRandomMsgGen.cjs +148 -35
- package/dist/v1/libs/UltraRandomMsgGen.d.mts +17 -3
- package/dist/v1/libs/UltraRandomMsgGen.mjs +133 -34
- package/dist/v1/libs/utils.cjs +21 -0
- package/dist/v1/libs/utils.d.mts +2 -0
- package/dist/v1/libs/utils.mjs +16 -0
- package/docs/v1/Exports.md +0 -1
- package/docs/v1/README.md +1 -1
- package/docs/v1/basics/array.md +2 -2
- package/docs/v1/basics/deprecated/html.md +17 -0
- package/docs/v1/basics/fullScreen.md +1 -1
- package/docs/v1/basics/html.md +12 -26
- package/docs/v1/basics/mediaContent.md +1 -1
- package/docs/v1/basics/objChecker.md +1 -1
- package/docs/v1/basics/objFilter.md +1 -1
- package/docs/v1/basics/text.md +2 -2
- package/docs/v1/fileManager/main.md +1 -1
- package/docs/v1/libs/ColorSafeStringify.md +1 -1
- package/docs/v1/libs/TinyAfterScrollWatcher.md +1 -1
- package/docs/v1/libs/TinyAnalogClock.md +1 -1
- package/docs/v1/libs/TinyArrayComparator.md +1 -1
- package/docs/v1/libs/TinyArrayPaginator.md +1 -1
- package/docs/v1/libs/TinyClassManager/TinyPluginInliner.md +2 -2
- package/docs/v1/libs/TinyClassManager.md +1 -1
- package/docs/v1/libs/TinyClipboard.md +1 -1
- package/docs/v1/libs/TinyCookieConsent.md +1 -1
- package/docs/v1/libs/TinyDomReadyManager.md +1 -1
- package/docs/v1/libs/TinyDragDropDetector.md +1 -1
- package/docs/v1/libs/TinyDragger.md +1 -1
- package/docs/v1/libs/TinyElementObserver.md +1 -1
- package/docs/v1/libs/TinyHtml.md +1 -1
- package/docs/v1/libs/TinyIframeEvents.md +10 -10
- package/docs/v1/libs/TinyLevelUp.md +1 -1
- package/docs/v1/libs/TinyLoadingScreen.md +1 -1
- package/docs/v1/libs/TinyLocalStorage.md +3 -3
- package/docs/v1/libs/TinyNewWinEvents.md +10 -11
- package/docs/v1/libs/TinyNotifications.md +1 -1
- package/docs/v1/libs/TinyPromiseQueue.md +2 -2
- package/docs/v1/libs/TinyTextDiffer.md +1 -1
- package/docs/v1/libs/TinyTextarea.md +1 -1
- package/package.json +15 -5
- package/dist/v1/TinyBasicsEs.min.js.LICENSE.txt +0 -8
- package/dist/v1/TinyEssentials.min.js.LICENSE.txt +0 -8
- package/dist/v1/TinyEvents.min.js +0 -1
- package/dist/v1/TinyUploadClicker.min.js.LICENSE.txt +0 -8
- package/dist/v1/build/TinyEvents.cjs +0 -7
- package/dist/v1/build/TinyEvents.d.mts +0 -3
- package/dist/v1/build/TinyEvents.mjs +0 -2
- package/dist/v1/libs/TinyEvents.cjs +0 -395
- package/dist/v1/libs/TinyEvents.d.mts +0 -164
- package/dist/v1/libs/TinyEvents.mjs +0 -360
- package/docs/v1/libs/TinyEvents.md +0 -187
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var events = require('events');
|
|
3
4
|
var mediaContent = require('../basics/mediaContent.cjs');
|
|
4
|
-
var
|
|
5
|
+
var utils = require('./utils.cjs');
|
|
6
|
+
|
|
7
|
+
const checkDestroy = utils.createCheckDestroyed('TinyRadioFm');
|
|
5
8
|
|
|
6
9
|
/**
|
|
7
10
|
* @typedef {import('../basics/mediaContent.mjs').MediaContentBase} MediaContentBase
|
|
@@ -126,10 +129,9 @@ var TinyEvents = require('./TinyEvents.cjs');
|
|
|
126
129
|
|
|
127
130
|
/**
|
|
128
131
|
* A deterministic, seed-based radio management system with scheduled adaptations and weighted random generation.
|
|
129
|
-
* @extends TinyEvents
|
|
130
132
|
* @beta
|
|
131
133
|
*/
|
|
132
|
-
class TinyRadioFm extends
|
|
134
|
+
class TinyRadioFm extends events.EventEmitter {
|
|
133
135
|
/**
|
|
134
136
|
* A Static Factory Method that prepares a MediaContent object by
|
|
135
137
|
* extracting metadata from an audio source.
|
|
@@ -180,11 +182,19 @@ class TinyRadioFm extends TinyEvents {
|
|
|
180
182
|
TinyRadioFm.#unknownArtist = value;
|
|
181
183
|
}
|
|
182
184
|
|
|
185
|
+
/** @type {boolean} */
|
|
186
|
+
#destroyed = false;
|
|
187
|
+
|
|
188
|
+
get destroyed() {
|
|
189
|
+
return this.#destroyed;
|
|
190
|
+
}
|
|
191
|
+
|
|
183
192
|
/**
|
|
184
193
|
* Gets the total count of all content items (music and voice) in the system.
|
|
185
194
|
* @returns {number}
|
|
186
195
|
*/
|
|
187
196
|
get size() {
|
|
197
|
+
checkDestroy(this.#destroyed);
|
|
188
198
|
return this.#musicList.length + this.#voiceList.length;
|
|
189
199
|
}
|
|
190
200
|
|
|
@@ -193,6 +203,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
193
203
|
* @returns {number}
|
|
194
204
|
*/
|
|
195
205
|
get musicSize() {
|
|
206
|
+
checkDestroy(this.#destroyed);
|
|
196
207
|
return this.#musicList.length;
|
|
197
208
|
}
|
|
198
209
|
|
|
@@ -201,6 +212,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
201
212
|
* @returns {number}
|
|
202
213
|
*/
|
|
203
214
|
get voiceSize() {
|
|
215
|
+
checkDestroy(this.#destroyed);
|
|
204
216
|
return this.#voiceList.length;
|
|
205
217
|
}
|
|
206
218
|
|
|
@@ -209,6 +221,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
209
221
|
* @returns {number}
|
|
210
222
|
*/
|
|
211
223
|
get customPosSize() {
|
|
224
|
+
checkDestroy(this.#destroyed);
|
|
212
225
|
return this.#customPositions.length;
|
|
213
226
|
}
|
|
214
227
|
|
|
@@ -217,6 +230,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
217
230
|
* @returns {number}
|
|
218
231
|
*/
|
|
219
232
|
get tasksSize() {
|
|
233
|
+
checkDestroy(this.#destroyed);
|
|
220
234
|
return this.#scheduledTasks.length;
|
|
221
235
|
}
|
|
222
236
|
|
|
@@ -225,6 +239,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
225
239
|
* @returns {number}
|
|
226
240
|
*/
|
|
227
241
|
get cycleCacheSize() {
|
|
242
|
+
checkDestroy(this.#destroyed);
|
|
228
243
|
return this.#cycleCache.size;
|
|
229
244
|
}
|
|
230
245
|
|
|
@@ -235,6 +250,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
235
250
|
* @returns {MediaContent[]}
|
|
236
251
|
*/
|
|
237
252
|
get musicList() {
|
|
253
|
+
checkDestroy(this.#destroyed);
|
|
238
254
|
return structuredClone(this.#musicList);
|
|
239
255
|
}
|
|
240
256
|
|
|
@@ -245,6 +261,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
245
261
|
* @returns {MediaContent[]}
|
|
246
262
|
*/
|
|
247
263
|
get voiceList() {
|
|
264
|
+
checkDestroy(this.#destroyed);
|
|
248
265
|
return structuredClone(this.#voiceList);
|
|
249
266
|
}
|
|
250
267
|
|
|
@@ -255,6 +272,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
255
272
|
* @returns {CustomPosition[]}
|
|
256
273
|
*/
|
|
257
274
|
get customPositions() {
|
|
275
|
+
checkDestroy(this.#destroyed);
|
|
258
276
|
return structuredClone(this.#customPositions);
|
|
259
277
|
}
|
|
260
278
|
|
|
@@ -265,6 +283,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
265
283
|
* @returns {ScheduledTask[]}
|
|
266
284
|
*/
|
|
267
285
|
get scheduledTasks() {
|
|
286
|
+
checkDestroy(this.#destroyed);
|
|
268
287
|
return structuredClone(this.#scheduledTasks);
|
|
269
288
|
}
|
|
270
289
|
|
|
@@ -273,6 +292,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
273
292
|
* @returns {MediaContent[]} A cloned object of the cache.
|
|
274
293
|
*/
|
|
275
294
|
get allList() {
|
|
295
|
+
checkDestroy(this.#destroyed);
|
|
276
296
|
return [...this.musicList, ...this.voiceList];
|
|
277
297
|
}
|
|
278
298
|
|
|
@@ -283,6 +303,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
283
303
|
* @returns {number}
|
|
284
304
|
*/
|
|
285
305
|
get seed() {
|
|
306
|
+
checkDestroy(this.#destroyed);
|
|
286
307
|
return this.#seed;
|
|
287
308
|
}
|
|
288
309
|
/**
|
|
@@ -290,6 +311,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
290
311
|
* @param {number} seed - The new seed.
|
|
291
312
|
*/
|
|
292
313
|
set seed(seed) {
|
|
314
|
+
checkDestroy(this.#destroyed);
|
|
293
315
|
if (typeof seed !== 'number') throw new TypeError('Seed must be a number.');
|
|
294
316
|
this.#seed = seed;
|
|
295
317
|
this.#cycleCache.clear();
|
|
@@ -303,6 +325,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
303
325
|
* @returns {number}
|
|
304
326
|
*/
|
|
305
327
|
get anchorDate() {
|
|
328
|
+
checkDestroy(this.#destroyed);
|
|
306
329
|
return this.#anchorDate;
|
|
307
330
|
}
|
|
308
331
|
|
|
@@ -326,6 +349,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
326
349
|
* @returns {RadioConfig}
|
|
327
350
|
*/
|
|
328
351
|
get config() {
|
|
352
|
+
checkDestroy(this.#destroyed);
|
|
329
353
|
return structuredClone(this.#config);
|
|
330
354
|
}
|
|
331
355
|
/**
|
|
@@ -334,6 +358,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
334
358
|
* @throws {TypeError|RangeError} If the new configuration is invalid.
|
|
335
359
|
*/
|
|
336
360
|
set config(config) {
|
|
361
|
+
checkDestroy(this.#destroyed);
|
|
337
362
|
// Validate the entire object before applying it
|
|
338
363
|
this.#validateConfig(config);
|
|
339
364
|
|
|
@@ -456,6 +481,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
456
481
|
* @throws {TypeError} If the type is invalid or the data lacks a valid ID and numerical duration.
|
|
457
482
|
*/
|
|
458
483
|
add(type, data, smartQueue = true) {
|
|
484
|
+
checkDestroy(this.#destroyed);
|
|
459
485
|
if (!['music', 'voice', 'custom'].includes(type)) {
|
|
460
486
|
throw new TypeError('Type must be "music", "voice", or "custom".');
|
|
461
487
|
}
|
|
@@ -492,6 +518,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
492
518
|
* @throws {TypeError} If arguments do not match the required types or action/type constraints.
|
|
493
519
|
*/
|
|
494
520
|
scheduleTask(timestamp, action, type, payload, smartQueue = true) {
|
|
521
|
+
checkDestroy(this.#destroyed);
|
|
495
522
|
if (typeof timestamp !== 'number' || isNaN(timestamp))
|
|
496
523
|
throw new TypeError('timestamp must be a valid number.');
|
|
497
524
|
if (!['add', 'remove', 'move'].includes(action))
|
|
@@ -561,6 +588,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
561
588
|
* @throws {TypeError} If the id is not a string.
|
|
562
589
|
*/
|
|
563
590
|
remove(id) {
|
|
591
|
+
checkDestroy(this.#destroyed);
|
|
564
592
|
if (typeof id !== 'string') throw new TypeError('id must be a string.');
|
|
565
593
|
|
|
566
594
|
// Revoke Blob URLs of items being removed to free memory
|
|
@@ -606,6 +634,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
606
634
|
* @throws {TypeError|RangeError} If the provided values or the resulting state is invalid.
|
|
607
635
|
*/
|
|
608
636
|
setConfig(config) {
|
|
637
|
+
checkDestroy(this.#destroyed);
|
|
609
638
|
// First, validate the incoming partial object for basic type correctness
|
|
610
639
|
this.#validateConfig(config);
|
|
611
640
|
|
|
@@ -625,6 +654,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
625
654
|
* @returns {RadioEvent|null} The current active event, or null if empty.
|
|
626
655
|
*/
|
|
627
656
|
getCurrentEvent() {
|
|
657
|
+
checkDestroy(this.#destroyed);
|
|
628
658
|
const now = Date.now();
|
|
629
659
|
this.#syncRealTimeState(now);
|
|
630
660
|
return this.#getEventAtTime(now, now);
|
|
@@ -640,6 +670,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
640
670
|
* @throws {RangeError} If the limit exceeds the configured queryLimit or is <= 0.
|
|
641
671
|
*/
|
|
642
672
|
queryTimeline(targetDate, limit = 10) {
|
|
673
|
+
checkDestroy(this.#destroyed);
|
|
643
674
|
if (typeof limit !== 'number' || isNaN(limit)) {
|
|
644
675
|
throw new TypeError(`Invalid query limit value. Ensure it is a number.`);
|
|
645
676
|
}
|
|
@@ -678,6 +709,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
678
709
|
* @returns {CustomPosition[]} Shallow copy of custom positions array.
|
|
679
710
|
*/
|
|
680
711
|
searchCustomPositions() {
|
|
712
|
+
checkDestroy(this.#destroyed);
|
|
681
713
|
this.#syncRealTimeState(Date.now());
|
|
682
714
|
return [...this.#customPositions];
|
|
683
715
|
}
|
|
@@ -727,6 +759,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
727
759
|
* @returns {Promise<string>} Stringified JSON state.
|
|
728
760
|
*/
|
|
729
761
|
async exportState() {
|
|
762
|
+
checkDestroy(this.#destroyed);
|
|
730
763
|
const processedMusic = await this._processListForExport(this.#musicList);
|
|
731
764
|
const processedVoice = await this._processListForExport(this.#voiceList);
|
|
732
765
|
|
|
@@ -771,6 +804,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
771
804
|
* @throws {TypeError} If json is not a valid string or object.
|
|
772
805
|
*/
|
|
773
806
|
importState(json) {
|
|
807
|
+
checkDestroy(this.#destroyed);
|
|
774
808
|
/** @type {TinyRadioFmImport} */
|
|
775
809
|
let data;
|
|
776
810
|
if (typeof json === 'string') {
|
|
@@ -1348,6 +1382,8 @@ class TinyRadioFm extends TinyEvents {
|
|
|
1348
1382
|
* @param {boolean} [destroyThumbs=true]
|
|
1349
1383
|
*/
|
|
1350
1384
|
destroy(destroyThumbs = true) {
|
|
1385
|
+
if (this.#destroyed) return;
|
|
1386
|
+
|
|
1351
1387
|
if (destroyThumbs) {
|
|
1352
1388
|
this.#musicList.forEach((item) => mediaContent.revokeContentUrls(item));
|
|
1353
1389
|
this.#voiceList.forEach((item) => mediaContent.revokeContentUrls(item));
|
|
@@ -1372,6 +1408,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
1372
1408
|
this.#cycleCache.clear();
|
|
1373
1409
|
this.emit('destroyed', { timestamp: Date.now() });
|
|
1374
1410
|
this.removeAllListeners();
|
|
1411
|
+
this.#destroyed = true;
|
|
1375
1412
|
}
|
|
1376
1413
|
}
|
|
1377
1414
|
|
|
@@ -327,10 +327,9 @@ export type TinyRadioFmImport = {
|
|
|
327
327
|
*/
|
|
328
328
|
/**
|
|
329
329
|
* A deterministic, seed-based radio management system with scheduled adaptations and weighted random generation.
|
|
330
|
-
* @extends TinyEvents
|
|
331
330
|
* @beta
|
|
332
331
|
*/
|
|
333
|
-
declare class TinyRadioFm extends
|
|
332
|
+
declare class TinyRadioFm extends EventEmitter<any> {
|
|
334
333
|
/**
|
|
335
334
|
* A Static Factory Method that prepares a MediaContent object by
|
|
336
335
|
* extracting metadata from an audio source.
|
|
@@ -378,6 +377,7 @@ declare class TinyRadioFm extends TinyEvents {
|
|
|
378
377
|
* @throws {TypeError} If initialData is not an object or null, or if seed is not a number.
|
|
379
378
|
*/
|
|
380
379
|
constructor(initialData?: TinyRadioFmImport | null, seed?: number);
|
|
380
|
+
get destroyed(): boolean;
|
|
381
381
|
/**
|
|
382
382
|
* Gets the total count of all content items (music and voice) in the system.
|
|
383
383
|
* @returns {number}
|
|
@@ -550,5 +550,5 @@ declare class TinyRadioFm extends TinyEvents {
|
|
|
550
550
|
destroy(destroyThumbs?: boolean): void;
|
|
551
551
|
#private;
|
|
552
552
|
}
|
|
553
|
-
import
|
|
553
|
+
import { EventEmitter } from 'events';
|
|
554
554
|
//# sourceMappingURL=TinyRadioFm.d.mts.map
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
1
2
|
import { blobUrlToBase64, convertToBlobUrl, parseMediaMetadata, revokeContentUrls, } from '../basics/mediaContent.mjs';
|
|
2
|
-
import
|
|
3
|
+
import { createCheckDestroyed } from './utils.mjs';
|
|
4
|
+
const checkDestroy = createCheckDestroyed('TinyRadioFm');
|
|
3
5
|
/**
|
|
4
6
|
* @typedef {import('../basics/mediaContent.mjs').MediaContentBase} MediaContentBase
|
|
5
7
|
* @typedef {import('../basics/mediaContent.mjs').MediaContentMetadata} MediaContentMetadata
|
|
@@ -105,10 +107,9 @@ import TinyEvents from './TinyEvents.mjs';
|
|
|
105
107
|
//////////////////////////////////////////////////////////////////
|
|
106
108
|
/**
|
|
107
109
|
* A deterministic, seed-based radio management system with scheduled adaptations and weighted random generation.
|
|
108
|
-
* @extends TinyEvents
|
|
109
110
|
* @beta
|
|
110
111
|
*/
|
|
111
|
-
class TinyRadioFm extends
|
|
112
|
+
class TinyRadioFm extends EventEmitter {
|
|
112
113
|
/**
|
|
113
114
|
* A Static Factory Method that prepares a MediaContent object by
|
|
114
115
|
* extracting metadata from an audio source.
|
|
@@ -148,11 +149,17 @@ class TinyRadioFm extends TinyEvents {
|
|
|
148
149
|
throw new TypeError('unknownArtist must have an string or function.');
|
|
149
150
|
TinyRadioFm.#unknownArtist = value;
|
|
150
151
|
}
|
|
152
|
+
/** @type {boolean} */
|
|
153
|
+
#destroyed = false;
|
|
154
|
+
get destroyed() {
|
|
155
|
+
return this.#destroyed;
|
|
156
|
+
}
|
|
151
157
|
/**
|
|
152
158
|
* Gets the total count of all content items (music and voice) in the system.
|
|
153
159
|
* @returns {number}
|
|
154
160
|
*/
|
|
155
161
|
get size() {
|
|
162
|
+
checkDestroy(this.#destroyed);
|
|
156
163
|
return this.#musicList.length + this.#voiceList.length;
|
|
157
164
|
}
|
|
158
165
|
/**
|
|
@@ -160,6 +167,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
160
167
|
* @returns {number}
|
|
161
168
|
*/
|
|
162
169
|
get musicSize() {
|
|
170
|
+
checkDestroy(this.#destroyed);
|
|
163
171
|
return this.#musicList.length;
|
|
164
172
|
}
|
|
165
173
|
/**
|
|
@@ -167,6 +175,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
167
175
|
* @returns {number}
|
|
168
176
|
*/
|
|
169
177
|
get voiceSize() {
|
|
178
|
+
checkDestroy(this.#destroyed);
|
|
170
179
|
return this.#voiceList.length;
|
|
171
180
|
}
|
|
172
181
|
/**
|
|
@@ -174,6 +183,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
174
183
|
* @returns {number}
|
|
175
184
|
*/
|
|
176
185
|
get customPosSize() {
|
|
186
|
+
checkDestroy(this.#destroyed);
|
|
177
187
|
return this.#customPositions.length;
|
|
178
188
|
}
|
|
179
189
|
/**
|
|
@@ -181,6 +191,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
181
191
|
* @returns {number}
|
|
182
192
|
*/
|
|
183
193
|
get tasksSize() {
|
|
194
|
+
checkDestroy(this.#destroyed);
|
|
184
195
|
return this.#scheduledTasks.length;
|
|
185
196
|
}
|
|
186
197
|
/**
|
|
@@ -188,6 +199,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
188
199
|
* @returns {number}
|
|
189
200
|
*/
|
|
190
201
|
get cycleCacheSize() {
|
|
202
|
+
checkDestroy(this.#destroyed);
|
|
191
203
|
return this.#cycleCache.size;
|
|
192
204
|
}
|
|
193
205
|
/** @type {MediaContent[]} */
|
|
@@ -197,6 +209,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
197
209
|
* @returns {MediaContent[]}
|
|
198
210
|
*/
|
|
199
211
|
get musicList() {
|
|
212
|
+
checkDestroy(this.#destroyed);
|
|
200
213
|
return structuredClone(this.#musicList);
|
|
201
214
|
}
|
|
202
215
|
/** @type {MediaContent[]} */
|
|
@@ -206,6 +219,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
206
219
|
* @returns {MediaContent[]}
|
|
207
220
|
*/
|
|
208
221
|
get voiceList() {
|
|
222
|
+
checkDestroy(this.#destroyed);
|
|
209
223
|
return structuredClone(this.#voiceList);
|
|
210
224
|
}
|
|
211
225
|
/** @type {CustomPosition[]} */
|
|
@@ -215,6 +229,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
215
229
|
* @returns {CustomPosition[]}
|
|
216
230
|
*/
|
|
217
231
|
get customPositions() {
|
|
232
|
+
checkDestroy(this.#destroyed);
|
|
218
233
|
return structuredClone(this.#customPositions);
|
|
219
234
|
}
|
|
220
235
|
/** @type {ScheduledTask[]} */
|
|
@@ -224,6 +239,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
224
239
|
* @returns {ScheduledTask[]}
|
|
225
240
|
*/
|
|
226
241
|
get scheduledTasks() {
|
|
242
|
+
checkDestroy(this.#destroyed);
|
|
227
243
|
return structuredClone(this.#scheduledTasks);
|
|
228
244
|
}
|
|
229
245
|
/**
|
|
@@ -231,6 +247,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
231
247
|
* @returns {MediaContent[]} A cloned object of the cache.
|
|
232
248
|
*/
|
|
233
249
|
get allList() {
|
|
250
|
+
checkDestroy(this.#destroyed);
|
|
234
251
|
return [...this.musicList, ...this.voiceList];
|
|
235
252
|
}
|
|
236
253
|
/** @type {number} */
|
|
@@ -240,6 +257,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
240
257
|
* @returns {number}
|
|
241
258
|
*/
|
|
242
259
|
get seed() {
|
|
260
|
+
checkDestroy(this.#destroyed);
|
|
243
261
|
return this.#seed;
|
|
244
262
|
}
|
|
245
263
|
/**
|
|
@@ -247,6 +265,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
247
265
|
* @param {number} seed - The new seed.
|
|
248
266
|
*/
|
|
249
267
|
set seed(seed) {
|
|
268
|
+
checkDestroy(this.#destroyed);
|
|
250
269
|
if (typeof seed !== 'number')
|
|
251
270
|
throw new TypeError('Seed must be a number.');
|
|
252
271
|
this.#seed = seed;
|
|
@@ -260,6 +279,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
260
279
|
* @returns {number}
|
|
261
280
|
*/
|
|
262
281
|
get anchorDate() {
|
|
282
|
+
checkDestroy(this.#destroyed);
|
|
263
283
|
return this.#anchorDate;
|
|
264
284
|
}
|
|
265
285
|
/** @type {Map<number, CycleBlock>} */
|
|
@@ -281,6 +301,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
281
301
|
* @returns {RadioConfig}
|
|
282
302
|
*/
|
|
283
303
|
get config() {
|
|
304
|
+
checkDestroy(this.#destroyed);
|
|
284
305
|
return structuredClone(this.#config);
|
|
285
306
|
}
|
|
286
307
|
/**
|
|
@@ -289,6 +310,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
289
310
|
* @throws {TypeError|RangeError} If the new configuration is invalid.
|
|
290
311
|
*/
|
|
291
312
|
set config(config) {
|
|
313
|
+
checkDestroy(this.#destroyed);
|
|
292
314
|
// Validate the entire object before applying it
|
|
293
315
|
this.#validateConfig(config);
|
|
294
316
|
this.#config = structuredClone(config);
|
|
@@ -378,6 +400,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
378
400
|
* @throws {TypeError} If the type is invalid or the data lacks a valid ID and numerical duration.
|
|
379
401
|
*/
|
|
380
402
|
add(type, data, smartQueue = true) {
|
|
403
|
+
checkDestroy(this.#destroyed);
|
|
381
404
|
if (!['music', 'voice', 'custom'].includes(type)) {
|
|
382
405
|
throw new TypeError('Type must be "music", "voice", or "custom".');
|
|
383
406
|
}
|
|
@@ -411,6 +434,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
411
434
|
* @throws {TypeError} If arguments do not match the required types or action/type constraints.
|
|
412
435
|
*/
|
|
413
436
|
scheduleTask(timestamp, action, type, payload, smartQueue = true) {
|
|
437
|
+
checkDestroy(this.#destroyed);
|
|
414
438
|
if (typeof timestamp !== 'number' || isNaN(timestamp))
|
|
415
439
|
throw new TypeError('timestamp must be a valid number.');
|
|
416
440
|
if (!['add', 'remove', 'move'].includes(action))
|
|
@@ -468,6 +492,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
468
492
|
* @throws {TypeError} If the id is not a string.
|
|
469
493
|
*/
|
|
470
494
|
remove(id) {
|
|
495
|
+
checkDestroy(this.#destroyed);
|
|
471
496
|
if (typeof id !== 'string')
|
|
472
497
|
throw new TypeError('id must be a string.');
|
|
473
498
|
// Revoke Blob URLs of items being removed to free memory
|
|
@@ -506,6 +531,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
506
531
|
* @throws {TypeError|RangeError} If the provided values or the resulting state is invalid.
|
|
507
532
|
*/
|
|
508
533
|
setConfig(config) {
|
|
534
|
+
checkDestroy(this.#destroyed);
|
|
509
535
|
// First, validate the incoming partial object for basic type correctness
|
|
510
536
|
this.#validateConfig(config);
|
|
511
537
|
// Create the potential new state
|
|
@@ -521,6 +547,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
521
547
|
* @returns {RadioEvent|null} The current active event, or null if empty.
|
|
522
548
|
*/
|
|
523
549
|
getCurrentEvent() {
|
|
550
|
+
checkDestroy(this.#destroyed);
|
|
524
551
|
const now = Date.now();
|
|
525
552
|
this.#syncRealTimeState(now);
|
|
526
553
|
return this.#getEventAtTime(now, now);
|
|
@@ -535,6 +562,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
535
562
|
* @throws {RangeError} If the limit exceeds the configured queryLimit or is <= 0.
|
|
536
563
|
*/
|
|
537
564
|
queryTimeline(targetDate, limit = 10) {
|
|
565
|
+
checkDestroy(this.#destroyed);
|
|
538
566
|
if (typeof limit !== 'number' || isNaN(limit)) {
|
|
539
567
|
throw new TypeError(`Invalid query limit value. Ensure it is a number.`);
|
|
540
568
|
}
|
|
@@ -566,6 +594,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
566
594
|
* @returns {CustomPosition[]} Shallow copy of custom positions array.
|
|
567
595
|
*/
|
|
568
596
|
searchCustomPositions() {
|
|
597
|
+
checkDestroy(this.#destroyed);
|
|
569
598
|
this.#syncRealTimeState(Date.now());
|
|
570
599
|
return [...this.#customPositions];
|
|
571
600
|
}
|
|
@@ -608,6 +637,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
608
637
|
* @returns {Promise<string>} Stringified JSON state.
|
|
609
638
|
*/
|
|
610
639
|
async exportState() {
|
|
640
|
+
checkDestroy(this.#destroyed);
|
|
611
641
|
const processedMusic = await this._processListForExport(this.#musicList);
|
|
612
642
|
const processedVoice = await this._processListForExport(this.#voiceList);
|
|
613
643
|
const processedCustom = await Promise.all(this.#customPositions.map(async (cp) => {
|
|
@@ -642,6 +672,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
642
672
|
* @throws {TypeError} If json is not a valid string or object.
|
|
643
673
|
*/
|
|
644
674
|
importState(json) {
|
|
675
|
+
checkDestroy(this.#destroyed);
|
|
645
676
|
/** @type {TinyRadioFmImport} */
|
|
646
677
|
let data;
|
|
647
678
|
if (typeof json === 'string') {
|
|
@@ -1112,6 +1143,8 @@ class TinyRadioFm extends TinyEvents {
|
|
|
1112
1143
|
* @param {boolean} [destroyThumbs=true]
|
|
1113
1144
|
*/
|
|
1114
1145
|
destroy(destroyThumbs = true) {
|
|
1146
|
+
if (this.#destroyed)
|
|
1147
|
+
return;
|
|
1115
1148
|
if (destroyThumbs) {
|
|
1116
1149
|
this.#musicList.forEach((item) => revokeContentUrls(item));
|
|
1117
1150
|
this.#voiceList.forEach((item) => revokeContentUrls(item));
|
|
@@ -1132,6 +1165,7 @@ class TinyRadioFm extends TinyEvents {
|
|
|
1132
1165
|
this.#cycleCache.clear();
|
|
1133
1166
|
this.emit('destroyed', { timestamp: Date.now() });
|
|
1134
1167
|
this.removeAllListeners();
|
|
1168
|
+
this.#destroyed = true;
|
|
1135
1169
|
}
|
|
1136
1170
|
}
|
|
1137
1171
|
export default TinyRadioFm;
|