tiny-essentials 1.28.6 → 1.28.7

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.
@@ -110,6 +110,21 @@ declare class BaseMediaAdapter extends EventEmitter {
110
110
  * @returns {Promise<void>}
111
111
  */
112
112
  seek(timeMs: number): Promise<void>;
113
+ /**
114
+ * Checks whether the player is currently muted.
115
+ * @returns {boolean|null} True if muted, false otherwise.
116
+ */
117
+ isMuted(): boolean | null;
118
+ /**
119
+ * Mutes the current playback.
120
+ * @returns {Promise<void>}
121
+ */
122
+ mute(): Promise<void>;
123
+ /**
124
+ * Unmutes the current playback.
125
+ * @returns {Promise<void>}
126
+ */
127
+ unMute(): Promise<void>;
113
128
  /**
114
129
  * Retrieves the current playback time from the underlying API.
115
130
  * @returns {number} The current time in milliseconds.
@@ -109,6 +109,30 @@ class BaseMediaAdapter extends EventEmitter {
109
109
  checkDestroy(this.#destroyed);
110
110
  throw new Error('Method "seek" must be implemented by the subclass.');
111
111
  }
112
+ /**
113
+ * Checks whether the player is currently muted.
114
+ * @returns {boolean|null} True if muted, false otherwise.
115
+ */
116
+ isMuted() {
117
+ checkDestroy(this.#destroyed);
118
+ throw new Error('Method "isMuted" must be implemented by the subclass.');
119
+ }
120
+ /**
121
+ * Mutes the current playback.
122
+ * @returns {Promise<void>}
123
+ */
124
+ async mute() {
125
+ checkDestroy(this.#destroyed);
126
+ throw new Error('Method "mute" must be implemented by the subclass.');
127
+ }
128
+ /**
129
+ * Unmutes the current playback.
130
+ * @returns {Promise<void>}
131
+ */
132
+ async unMute() {
133
+ checkDestroy(this.#destroyed);
134
+ throw new Error('Method "unMute" must be implemented by the subclass.');
135
+ }
112
136
  /**
113
137
  * Retrieves the current playback time from the underlying API.
114
138
  * @returns {number} The current time in milliseconds.
@@ -127,6 +127,9 @@ class TinyMediaPlayer extends events.EventEmitter {
127
127
  /** @type {boolean} */
128
128
  #isPlaying = false;
129
129
 
130
+ /** @type {boolean} */
131
+ #isMuted = false;
132
+
130
133
  /** @type {number} */
131
134
  #volume = 1.0;
132
135
 
@@ -683,6 +686,39 @@ class TinyMediaPlayer extends events.EventEmitter {
683
686
  }
684
687
  }
685
688
 
689
+ /** @returns {boolean} True if the player is currently muted. */
690
+ get isMuted() {
691
+ checkDestroy(this.#destroyed);
692
+ return this.#isMuted;
693
+ }
694
+
695
+ /**
696
+ * Sets the mute state of the player.
697
+ * This state is synchronized with the active adapter and respected when playing new tracks.
698
+ * @param {boolean} value - True to mute, false to unMute.
699
+ * @throws {TypeError} If the value is not a boolean.
700
+ */
701
+ set isMuted(value) {
702
+ checkDestroy(this.#destroyed);
703
+ if (typeof value !== 'boolean') {
704
+ throw new TypeError('isMuted must be a boolean.');
705
+ }
706
+
707
+ this.#isMuted = value;
708
+
709
+ // Synchronize with the active adapter immediately
710
+ try {
711
+ const adapter = this.#getActiveAdapter();
712
+ if (adapter) {
713
+ value ? adapter.mute() : adapter.unMute();
714
+ }
715
+ } catch (error) {
716
+ // If no active adapter, we just wait for the next play() call to apply the state
717
+ }
718
+
719
+ this.emit('muteChange', this.#isMuted);
720
+ }
721
+
686
722
  // ==========================================
687
723
  // ADAPTER MANAGEMENT
688
724
  // ==========================================
@@ -1125,6 +1161,7 @@ class TinyMediaPlayer extends events.EventEmitter {
1125
1161
  }
1126
1162
 
1127
1163
  await adapter.play(this.#playlist[this.#currentIndex]);
1164
+ if (this.#isMuted) await adapter.mute();
1128
1165
  this.#isPlaying = true;
1129
1166
  this.emit('play', this.#currentIndex);
1130
1167
  }
@@ -220,6 +220,15 @@ declare class TinyMediaPlayer extends EventEmitter {
220
220
  * @throws {TypeError} If the value is not a string or is empty.
221
221
  */
222
222
  set volumeStorageKey(value: string);
223
+ /** @returns {boolean} True if the player is currently muted. */
224
+ get isMuted(): boolean;
225
+ /**
226
+ * Sets the mute state of the player.
227
+ * This state is synchronized with the active adapter and respected when playing new tracks.
228
+ * @param {boolean} value - True to mute, false to unMute.
229
+ * @throws {TypeError} If the value is not a boolean.
230
+ */
231
+ set isMuted(value: boolean);
223
232
  get adapters(): BaseMediaAdapter[];
224
233
  get adaptersSize(): number;
225
234
  static get defaultAdapterEventNames(): string[];
@@ -98,6 +98,8 @@ class TinyMediaPlayer extends EventEmitter {
98
98
  #isRandom = false;
99
99
  /** @type {boolean} */
100
100
  #isPlaying = false;
101
+ /** @type {boolean} */
102
+ #isMuted = false;
101
103
  /** @type {number} */
102
104
  #volume = 1.0;
103
105
  /** @type {boolean} */
@@ -608,6 +610,35 @@ class TinyMediaPlayer extends EventEmitter {
608
610
  console.warn('[TinyMediaPlayer] Failed to migrate volume storage key.', error);
609
611
  }
610
612
  }
613
+ /** @returns {boolean} True if the player is currently muted. */
614
+ get isMuted() {
615
+ checkDestroy(this.#destroyed);
616
+ return this.#isMuted;
617
+ }
618
+ /**
619
+ * Sets the mute state of the player.
620
+ * This state is synchronized with the active adapter and respected when playing new tracks.
621
+ * @param {boolean} value - True to mute, false to unMute.
622
+ * @throws {TypeError} If the value is not a boolean.
623
+ */
624
+ set isMuted(value) {
625
+ checkDestroy(this.#destroyed);
626
+ if (typeof value !== 'boolean') {
627
+ throw new TypeError('isMuted must be a boolean.');
628
+ }
629
+ this.#isMuted = value;
630
+ // Synchronize with the active adapter immediately
631
+ try {
632
+ const adapter = this.#getActiveAdapter();
633
+ if (adapter) {
634
+ value ? adapter.mute() : adapter.unMute();
635
+ }
636
+ }
637
+ catch (error) {
638
+ // If no active adapter, we just wait for the next play() call to apply the state
639
+ }
640
+ this.emit('muteChange', this.#isMuted);
641
+ }
611
642
  // ==========================================
612
643
  // ADAPTER MANAGEMENT
613
644
  // ==========================================
@@ -1007,6 +1038,8 @@ class TinyMediaPlayer extends EventEmitter {
1007
1038
  adapter.setVolume(this.#volume);
1008
1039
  }
1009
1040
  await adapter.play(this.#playlist[this.#currentIndex]);
1041
+ if (this.#isMuted)
1042
+ await adapter.mute();
1010
1043
  this.#isPlaying = true;
1011
1044
  this.emit('play', this.#currentIndex);
1012
1045
  }
@@ -20,10 +20,15 @@ To support different media platforms, `TinyMediaPlayer` relies on **Adapters**.
20
20
  | Method | Description | Parameters | Returns |
21
21
  | :--- | :--- | :--- | :--- |
22
22
  | `canHandle` | Determines if the adapter can play the provided content. | `content: MediaContent` | `boolean` |
23
+ | `isReady` | Synchronously checks if the adapter is ready. | None | `boolean` |
24
+ | `waitIsReady` | Asynchronously waits until the adapter is ready. | None | `Promise<void>` |
23
25
  | `play` | Starts or resumes playback of the provided content. | `content: MediaContent` | `Promise<void>` |
24
26
  | `pause` | Pauses the current playback. | None | `Promise<void>` |
25
27
  | `stop` | Stops the playback completely and resets the platform state. | None | `Promise<void>` |
26
28
  | `seek` | Seeks to a specific time in the media timeline. | `timeMs: number` | `Promise<void>` |
29
+ | `isMuted` | Checks whether the player is currently muted. | None | `boolean \| null` |
30
+ | `mute` | Mutes the current playback. | None | `Promise<void>` |
31
+ | `unMute` | Unmutes the current playback. | None | `Promise<void>` |
27
32
  | `getCurrentTime` | Retrieves the current playback position. | None | `number` (ms) |
28
33
  | `getTotalDuration` | Gets the total duration of the content. | None | `number` (ms) |
29
34
  | `getRemainingTime` | Gets the remaining time until the content ends. | None | `number` (ms) |
@@ -31,7 +36,8 @@ To support different media platforms, `TinyMediaPlayer` relies on **Adapters**.
31
36
  | `getTimeData` | Retrieves a consolidated object containing all time-related metrics. | None | `ContentTimeData` |
32
37
  | `setVolume` | Sets the playback volume for the underlying API. | `volume: number` (0.0 to 1.0) | `void` |
33
38
  | `getVolume` | Gets the current playback volume. | None | `number` (0.0 to 1.0) |
34
- | `destroy` | Cleans up the instance, removes listeners, and marks it as destroyed. | None | `void` |
39
+ | `getContentData` | Retrieves the metadata of the loaded content. | None | `Promise<ContentData>` |
40
+ | `destroy` | Cleans up the instance and marks it as destroyed. | None | `void` |
35
41
 
36
42
  ---
37
43
 
@@ -59,9 +65,9 @@ const player = new TinyMediaPlayer({
59
65
  });
60
66
 
61
67
  YoutubeMediaAdapter.defaultContainer = YoutubeMediaAdapter.createIframeContainer({
62
- videoId: 'fzKvGbQ9SgY',
63
- hidden: true,
64
- autoplay: false,
68
+ videoId: 'fzKvGbQ9SgY',
69
+ hidden: true,
70
+ autoplay: false,
65
71
  });
66
72
 
67
73
  // Register the ready-made adapters
@@ -93,46 +99,30 @@ class MyCustomServiceAdapter extends BaseMediaAdapter {
93
99
  return content.url.startsWith('https://example.com/');
94
100
  }
95
101
 
96
- /**
97
- * Determines if this adapter can play the given content.
98
- * @param {MediaContent} content - The media content to check.
99
- * @returns {boolean} - True if the URL matches the service.
100
- */
101
102
  canHandle(content) {
102
103
  return MyCustomServiceAdapter.canHandle(content);
103
104
  }
104
105
 
105
- /**
106
- * Starts playback for the provided content.
107
- * @param {MediaContent} content - The content to play.
108
- * @returns {Promise<void>}
109
- */
110
106
  async play(content) {
111
107
  console.log(`Starting playback for: ${content.title}`);
112
- // Logic to interface with the custom service API goes here
113
- }
114
-
115
- async pause() {
116
- // Logic to pause custom service playback
117
- }
118
-
119
- async stop() {
120
- // Logic to stop custom service playback
121
- }
122
-
123
- async seek(timeMs) {
124
- // Logic to seek in custom service playback
125
- }
126
-
127
- getCurrentTime() {
128
- // Logic to return current time from custom service
129
- return 0;
130
108
  }
131
109
 
132
- setVolume(volume) {
133
- // Logic to set volume on custom service
134
- console.log(`Volume set to: ${volume}`);
135
- }
110
+ async pause() {}
111
+ async stop() {}
112
+ async seek(timeMs) {}
113
+ getCurrentTime() { return 0; }
114
+ setVolume(volume) {}
115
+ getVolume() { return 1.0; }
116
+ async getContentData() { return {}; }
117
+ async waitIsReady() {}
118
+ isReady() { return true; }
119
+ isMuted() { return false; }
120
+ async mute() {}
121
+ async unMute() {}
122
+ getTotalDuration() { return 0; }
123
+ getRemainingTime() { return 0; }
124
+ getPlaybackPercentage() { return 0; }
125
+ getTimeData() { return {}; }
136
126
  }
137
127
 
138
128
  // Registering the custom adapter
@@ -214,6 +204,7 @@ When initializing `new TinyMediaPlayer(options)`, you can pass the following `Ti
214
204
  | `isRandom` | `boolean` | Enables or disables shuffle mode. |
215
205
  | `isPlaying` | `boolean` | Indicates if media is currently playing. |
216
206
  | `volume` | `number` | The current volume level (strictly between `0.0` and `1.0`). |
207
+ | `isMuted` | `boolean` | Sets the mute state of the player. |
217
208
 
218
209
  #### 🎨 UX & Customization
219
210
  | Property | Type | Description |
@@ -274,13 +265,15 @@ When initializing `new TinyMediaPlayer(options)`, you can pass the following `Ti
274
265
  * **`next()`**: **(Async)** Advances to the next track (respects `loopMode` and `isRandom`).
275
266
  * **`prev()`**: **(Async)** Returns to the previous track (respects `loopMode` and `isRandom`).
276
267
  * **`seek(timeMs)`**: **(Async)** Jumps to a specific millisecond in the current track.
277
- * **`step(stepMs)`**: **(Async)** Moves the timeline forward (positive) or backward (negative) by a specified amount.
268
+ * **`step(stepMs)`**: **(Async)** Moves the timeline forward (+) or backward (-) by `stepMs`.
278
269
 
279
270
  #### ⏳ Time Utilities
280
271
  * **`getCurrentTime()`**: Gets the current playback time in milliseconds.
281
272
  * **`getTotalDuration()`**: Gets the total duration of the current track in milliseconds.
282
273
  * **`getRemainingTime()`**: Gets the remaining time until the current track ends in milliseconds.
283
274
  * **`getPlaybackPercentage()`**: Gets the percentage of the current track that has been played (0-100).
275
+ * **`getContentData()`**: Retrieves structured metadata for the current content.
276
+ * **`waitIsReady()`**: **(Async)** Waits until the active adapter is fully initialized.
284
277
 
285
278
  #### ♻️ Lifecycle
286
279
  * **`destroy()`**: **(Async)** Safely stops playback, clears state, removes adapters, and detaches all listeners to prevent memory leaks.
@@ -313,6 +306,7 @@ When initializing `new TinyMediaPlayer(options)`, you can pass the following `Ti
313
306
  | `smoothStopVolumeChange` | `boolean` | Emitted when the smooth stop volume setting is toggled. |
314
307
  | `fadeVolumeSpeedChange` | `number` | Emitted when the volume fade speed is updated. |
315
308
  | `prevClickTimeoutDurationChange` | `number` | Emitted when the "repeat on prev" timeout duration is updated. |
309
+ | `muteChange` | `boolean` | Emitted when the mute state is toggled. |
316
310
 
317
311
  ### 💀 Lifecycle Events
318
312
  | Event | Data Type | Description |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tiny-essentials",
3
- "version": "1.28.6",
3
+ "version": "1.28.7",
4
4
  "description": "Collection of small, essential scripts designed to be used across various projects. These simple utilities are crafted for speed, ease of use, and versatility.",
5
5
  "bin": {
6
6
  "tiny-essentials-fork": "./TinyFork.mjs"
@@ -160,6 +160,10 @@
160
160
  "require": "./dist/v1/libs/TinyMediaPlayer/docs/YouTubePlayer.cjs",
161
161
  "import": "./dist/v1/libs/TinyMediaPlayer/docs/YouTubePlayer.mjs"
162
162
  },
163
+ "./libs/TinyMediaPlayer/docs/SoundCloudWidget": {
164
+ "require": "./dist/v1/libs/TinyMediaPlayer/docs/SoundCloudWidget.cjs",
165
+ "import": "./dist/v1/libs/TinyMediaPlayer/docs/SoundCloudWidget.mjs"
166
+ },
163
167
  "./libs/TinyRadioFm": {
164
168
  "require": "./dist/v1/libs/TinyRadioFm.cjs",
165
169
  "import": "./dist/v1/libs/TinyRadioFm.mjs"