tunzo-player 1.0.8 → 1.0.11

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.
@@ -1,3 +1,4 @@
1
+ import { BehaviorSubject } from 'rxjs';
1
2
  export declare class Player {
2
3
  private static audio;
3
4
  private static currentSong;
@@ -7,33 +8,33 @@ export declare class Player {
7
8
  private static duration;
8
9
  private static isShuffle;
9
10
  private static queue;
11
+ static queue$: BehaviorSubject<any[]>;
10
12
  private static playlist;
11
13
  private static selectedQuality;
12
- private static isInitialized;
13
- static initialize(playlist?: any[], quality?: number): void;
14
- static play(song: any, index?: number): Promise<void>;
15
- private static setupMusicControls;
16
- static pause(): Promise<void>;
17
- static resume(): Promise<void>;
18
- static stop(): Promise<void>;
19
- static togglePlayPause(): Promise<void>;
20
- static next(): Promise<void>;
21
- static prev(): Promise<void>;
22
- static autoNext(): Promise<void>;
23
- static playRandom(): Promise<void>;
14
+ /** Initialize with playlist and quality */
15
+ static initialize(playlist: any[], quality?: number): void;
16
+ /** Call this once on user gesture to unlock audio in WebView */
17
+ static unlockAudio(): void;
18
+ static play(song: any, index?: number): void;
19
+ static pause(): void;
20
+ static resume(): void;
21
+ static togglePlayPause(): void;
22
+ static next(): void;
23
+ static prev(): void;
24
+ static seek(seconds: number): void;
25
+ static autoNext(): void;
26
+ static playRandom(): void;
24
27
  static toggleShuffle(): void;
28
+ static getShuffleStatus(): boolean;
25
29
  static addToQueue(song: any): void;
26
30
  static removeFromQueue(index: number): void;
27
31
  static reorderQueue(from: number, to: number): void;
28
- static seekTo(seconds: number): Promise<void>;
29
32
  static getCurrentTime(): number;
30
33
  static getDuration(): number;
31
- static formatTime(t: number): string;
34
+ static formatTime(time: number): string;
32
35
  static isPlayingSong(): boolean;
33
36
  static getCurrentSong(): any;
34
37
  static setQuality(index: number): void;
35
38
  static getQueue(): any[];
36
39
  static getPlaylist(): any[];
37
- static getShuffleStatus(): boolean;
38
- static destroy(): Promise<void>;
39
40
  }
@@ -1,178 +1,116 @@
1
1
  "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
2
  Object.defineProperty(exports, "__esModule", { value: true });
12
3
  exports.Player = void 0;
13
- const core_1 = require("@capacitor/core");
14
- const capacitor_music_controls_plugin_1 = require("capacitor-music-controls-plugin");
4
+ const rxjs_1 = require("rxjs");
15
5
  class Player {
16
- static initialize(playlist = [], quality = 3) {
17
- if (!core_1.Capacitor.isNativePlatform()) {
18
- this.audio = new Audio();
19
- }
20
- this.playlist = [...playlist];
6
+ /** Initialize with playlist and quality */
7
+ static initialize(playlist, quality = 3) {
8
+ this.playlist = playlist;
21
9
  this.selectedQuality = quality;
22
- this.isInitialized = true;
23
- }
24
- static play(song_1) {
25
- return __awaiter(this, arguments, void 0, function* (song, index = 0) {
26
- var _a, _b;
27
- if (!this.isInitialized)
28
- return;
29
- if (!(song === null || song === void 0 ? void 0 : song.downloadUrl))
30
- return;
31
- yield this.stop();
32
- this.currentSong = song;
33
- this.currentIndex = index;
34
- const url = ((_a = song.downloadUrl[this.selectedQuality]) === null || _a === void 0 ? void 0 : _a.url) || ((_b = song.downloadUrl[0]) === null || _b === void 0 ? void 0 : _b.url);
35
- if (!url)
36
- return;
37
- if (!this.audio)
38
- this.audio = new Audio();
39
- this.audio.src = url;
40
- this.audio.play().catch(console.error);
41
- this.audio.onloadedmetadata = () => this.duration = this.audio.duration;
42
- this.audio.ontimeupdate = () => this.currentTime = this.audio.currentTime;
43
- this.audio.onended = () => this.autoNext();
44
- yield this.setupMusicControls(song, true);
45
- this.isPlaying = true;
46
- });
47
10
  }
48
- static setupMusicControls(song, isPlaying) {
49
- return __awaiter(this, void 0, void 0, function* () {
50
- if (!core_1.Capacitor.isNativePlatform())
51
- return;
52
- yield capacitor_music_controls_plugin_1.CapacitorMusicControls.destroy(); // clear existing
53
- yield capacitor_music_controls_plugin_1.CapacitorMusicControls.create({
54
- track: song.name || '',
55
- artist: song.primaryArtists || '',
56
- album: song.album || '',
57
- cover: song.image || '',
58
- isPlaying,
59
- dismissable: true,
60
- hasPrev: true,
61
- hasNext: true,
62
- });
63
- capacitor_music_controls_plugin_1.CapacitorMusicControls.addListener('music-controls-next', () => this.next());
64
- capacitor_music_controls_plugin_1.CapacitorMusicControls.addListener('music-controls-previous', () => this.prev());
65
- capacitor_music_controls_plugin_1.CapacitorMusicControls.addListener('music-controls-pause', () => this.pause());
66
- capacitor_music_controls_plugin_1.CapacitorMusicControls.addListener('music-controls-play', () => this.resume());
67
- capacitor_music_controls_plugin_1.CapacitorMusicControls.addListener('music-controls-destroy', () => this.stop());
68
- });
11
+ /** Call this once on user gesture to unlock audio in WebView */
12
+ static unlockAudio() {
13
+ this.audio.src = '';
14
+ this.audio.load();
15
+ this.audio.play().catch(() => { });
69
16
  }
70
- static pause() {
71
- return __awaiter(this, void 0, void 0, function* () {
72
- if (this.audio)
73
- this.audio.pause();
17
+ static play(song, index = 0) {
18
+ var _a;
19
+ if (!song || !song.downloadUrl)
20
+ return;
21
+ this.currentSong = song;
22
+ this.currentIndex = index;
23
+ this.audio.src = ((_a = song.downloadUrl[this.selectedQuality]) === null || _a === void 0 ? void 0 : _a.url) || '';
24
+ this.audio.load(); // Ensure audio is loaded before play
25
+ this.audio.play().then(() => {
26
+ this.isPlaying = true;
27
+ }).catch((err) => {
28
+ // Handle play errors (autoplay, WebView restrictions)
74
29
  this.isPlaying = false;
75
- core_1.Capacitor.isNativePlatform() && capacitor_music_controls_plugin_1.CapacitorMusicControls.updateIsPlaying({ isPlaying: false });
30
+ console.warn('Audio play failed:', err);
76
31
  });
32
+ // Set duration
33
+ this.audio.onloadedmetadata = () => {
34
+ this.duration = this.audio.duration;
35
+ };
36
+ // Set current time
37
+ this.audio.ontimeupdate = () => {
38
+ this.currentTime = this.audio.currentTime;
39
+ };
40
+ // Auto-play next song
41
+ this.audio.onended = () => {
42
+ this.autoNext();
43
+ };
77
44
  }
78
- static resume() {
79
- return __awaiter(this, void 0, void 0, function* () {
80
- if (this.audio)
81
- yield this.audio.play();
82
- this.isPlaying = true;
83
- core_1.Capacitor.isNativePlatform() && capacitor_music_controls_plugin_1.CapacitorMusicControls.updateIsPlaying({ isPlaying: true });
84
- });
45
+ static pause() {
46
+ this.audio.pause();
47
+ this.isPlaying = false;
85
48
  }
86
- static stop() {
87
- return __awaiter(this, void 0, void 0, function* () {
88
- if (this.audio) {
89
- this.audio.pause();
90
- this.audio.src = '';
91
- }
92
- this.isPlaying = false;
93
- yield capacitor_music_controls_plugin_1.CapacitorMusicControls.destroy();
94
- });
49
+ static resume() {
50
+ this.audio.play();
51
+ this.isPlaying = true;
95
52
  }
96
53
  static togglePlayPause() {
97
- return __awaiter(this, void 0, void 0, function* () {
98
- if (this.isPlaying) {
99
- yield this.pause();
100
- }
101
- else if (this.currentSong) {
102
- yield this.resume();
103
- }
104
- else if (this.playlist.length > 0) {
105
- yield this.play(this.playlist[0], 0);
106
- }
107
- });
54
+ if (this.isPlaying) {
55
+ this.pause();
56
+ }
57
+ else {
58
+ this.resume();
59
+ }
108
60
  }
109
61
  static next() {
110
- return __awaiter(this, void 0, void 0, function* () {
111
- if (this.queue.length > 0) {
112
- const next = this.queue.shift();
113
- const index = this.playlist.findIndex(s => s.id === next.id);
114
- yield this.play(next, index);
115
- }
116
- else if (this.isShuffle) {
117
- yield this.playRandom();
118
- }
119
- else if (this.currentIndex < this.playlist.length - 1) {
120
- yield this.play(this.playlist[this.currentIndex + 1], this.currentIndex + 1);
121
- }
122
- });
62
+ if (this.queue.length > 0) {
63
+ const nextQueued = this.queue.shift();
64
+ const index = this.playlist.findIndex(s => s.id === nextQueued.id);
65
+ this.play(nextQueued, index);
66
+ }
67
+ else if (this.isShuffle) {
68
+ this.playRandom();
69
+ }
70
+ else if (this.currentIndex < this.playlist.length - 1) {
71
+ this.play(this.playlist[this.currentIndex + 1], this.currentIndex + 1);
72
+ }
123
73
  }
124
74
  static prev() {
125
- return __awaiter(this, void 0, void 0, function* () {
126
- if (this.currentTime > 3) {
127
- yield this.seekTo(0);
128
- }
129
- else if (this.currentIndex > 0) {
130
- yield this.play(this.playlist[this.currentIndex - 1], this.currentIndex - 1);
131
- }
132
- });
75
+ if (this.currentIndex > 0) {
76
+ this.play(this.playlist[this.currentIndex - 1], this.currentIndex - 1);
77
+ }
78
+ }
79
+ static seek(seconds) {
80
+ this.audio.currentTime = seconds;
133
81
  }
134
82
  static autoNext() {
135
- return __awaiter(this, void 0, void 0, function* () {
136
- yield this.next();
137
- });
83
+ this.next();
138
84
  }
139
85
  static playRandom() {
140
- return __awaiter(this, void 0, void 0, function* () {
141
- if (this.playlist.length <= 1)
142
- return;
143
- let rand = this.currentIndex;
144
- while (rand === this.currentIndex) {
145
- rand = Math.floor(Math.random() * this.playlist.length);
146
- }
147
- yield this.play(this.playlist[rand], rand);
148
- });
86
+ if (this.playlist.length <= 1)
87
+ return;
88
+ let randomIndex;
89
+ do {
90
+ randomIndex = Math.floor(Math.random() * this.playlist.length);
91
+ } while (randomIndex === this.currentIndex);
92
+ this.play(this.playlist[randomIndex], randomIndex);
149
93
  }
150
94
  static toggleShuffle() {
151
95
  this.isShuffle = !this.isShuffle;
152
96
  }
97
+ static getShuffleStatus() {
98
+ return this.isShuffle;
99
+ }
153
100
  static addToQueue(song) {
154
- if (!this.queue.find(s => s.id === song.id)) {
101
+ if (!this.queue.some(q => q.id === song.id)) {
155
102
  this.queue.push(song);
103
+ this.queue$.next([...this.queue]);
156
104
  }
157
105
  }
158
106
  static removeFromQueue(index) {
159
- if (index >= 0 && index < this.queue.length) {
160
- this.queue.splice(index, 1);
161
- }
107
+ this.queue.splice(index, 1);
108
+ this.queue$.next([...this.queue]);
162
109
  }
163
110
  static reorderQueue(from, to) {
164
- if (from === to)
165
- return;
166
- const [item] = this.queue.splice(from, 1);
111
+ const item = this.queue.splice(from, 1)[0];
167
112
  this.queue.splice(to, 0, item);
168
- }
169
- static seekTo(seconds) {
170
- return __awaiter(this, void 0, void 0, function* () {
171
- if (this.audio) {
172
- this.audio.currentTime = seconds;
173
- this.currentTime = seconds;
174
- }
175
- });
113
+ this.queue$.next([...this.queue]);
176
114
  }
177
115
  static getCurrentTime() {
178
116
  return this.currentTime;
@@ -180,10 +118,10 @@ class Player {
180
118
  static getDuration() {
181
119
  return this.duration;
182
120
  }
183
- static formatTime(t) {
184
- const m = Math.floor(t / 60);
185
- const s = Math.floor(t % 60);
186
- return `${m}:${s < 10 ? '0' : ''}${s}`;
121
+ static formatTime(time) {
122
+ const minutes = Math.floor(time / 60);
123
+ const seconds = Math.floor(time % 60);
124
+ return `${minutes}:${seconds < 10 ? '0' : ''}${seconds}`;
187
125
  }
188
126
  static isPlayingSong() {
189
127
  return this.isPlaying;
@@ -195,33 +133,21 @@ class Player {
195
133
  this.selectedQuality = index;
196
134
  }
197
135
  static getQueue() {
198
- return [...this.queue];
136
+ return this.queue;
199
137
  }
200
138
  static getPlaylist() {
201
- return [...this.playlist];
202
- }
203
- static getShuffleStatus() {
204
- return this.isShuffle;
205
- }
206
- static destroy() {
207
- return __awaiter(this, void 0, void 0, function* () {
208
- yield this.stop();
209
- this.playlist = [];
210
- this.queue = [];
211
- this.audio = null;
212
- this.isInitialized = false;
213
- });
139
+ return this.playlist;
214
140
  }
215
141
  }
216
142
  exports.Player = Player;
217
- Player.audio = null;
143
+ Player.audio = new Audio();
218
144
  Player.currentSong = null;
219
145
  Player.currentIndex = 0;
220
146
  Player.isPlaying = false;
221
147
  Player.currentTime = 0;
222
148
  Player.duration = 0;
223
- Player.isShuffle = false;
149
+ Player.isShuffle = true;
224
150
  Player.queue = [];
151
+ Player.queue$ = new rxjs_1.BehaviorSubject([]);
225
152
  Player.playlist = [];
226
153
  Player.selectedQuality = 3;
227
- Player.isInitialized = false;
package/package.json CHANGED
@@ -1,29 +1,34 @@
1
1
  {
2
- "name": "tunzo-player",
3
- "version": "1.0.8",
4
- "description": "A music playback service for Angular and Ionic apps with native audio control support.",
5
- "main": "dist/index.js",
6
- "types": "dist/index.d.ts",
7
- "scripts": {
8
- "build": "tsc"
9
- },
10
- "keywords": [
11
- "music",
12
- "player",
13
- "angular",
14
- "ionic",
15
- "audio"
16
- ],
17
- "author": "Kulasekaran",
18
- "license": "MIT",
19
- "publishConfig": {
20
- "access": "public"
21
- },
22
- "devDependencies": {
23
- "typescript": "^5.8.3"
24
- },
25
- "dependencies": {
26
- "@capacitor-community/native-audio": "^7.0.0",
27
- "capacitor-music-controls-plugin": "^6.1.0"
28
- }
2
+ "name": "tunzo-player",
3
+ "version": "1.0.11",
4
+ "description": "A music playback service for Angular and Ionic apps with native audio control support.",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "scripts": {
8
+ "build": "tsc",
9
+ "publish:patch": "npm version patch && npm run build && npm publish",
10
+ "publish:minor": "npm version minor && npm run build && npm publish",
11
+ "publish:major": "npm version major && npm run build && npm publish",
12
+ "publish": "npm run build && npm publish"
13
+ },
14
+ "keywords": [
15
+ "music",
16
+ "player",
17
+ "angular",
18
+ "ionic",
19
+ "audio",
20
+ "native",
21
+ "playback",
22
+ "service",
23
+ "tunzo",
24
+ "tunzo-player"
25
+ ],
26
+ "author": "Kulasekaran",
27
+ "license": "MIT",
28
+ "publishConfig": {
29
+ "access": "public"
30
+ },
31
+ "dependencies": {
32
+ "rxjs": "^7.8.2"
33
+ }
29
34
  }
@@ -1,214 +1,174 @@
1
- import { Capacitor } from '@capacitor/core';
2
- import { CapacitorMusicControls } from 'capacitor-music-controls-plugin';
1
+ import { BehaviorSubject } from 'rxjs';
3
2
 
4
3
  export class Player {
5
- private static audio: HTMLAudioElement | null = null;
6
- private static currentSong: any = null;
7
- private static currentIndex = 0;
8
- private static isPlaying = false;
9
- private static currentTime = 0;
10
- private static duration = 0;
11
- private static isShuffle = false;
12
- private static queue: any[] = [];
13
- private static playlist: any[] = [];
14
- private static selectedQuality = 3;
15
- private static isInitialized = false;
16
-
17
- static initialize(playlist: any[] = [], quality = 3) {
18
- if (!Capacitor.isNativePlatform()) {
19
- this.audio = new Audio();
4
+ private static audio = new Audio();
5
+ private static currentSong: any = null;
6
+ private static currentIndex = 0;
7
+ private static isPlaying = false;
8
+ private static currentTime = 0;
9
+ private static duration = 0;
10
+ private static isShuffle = true;
11
+ private static queue: any[] = [];
12
+ static queue$ = new BehaviorSubject<any[]>([]);
13
+ private static playlist: any[] = [];
14
+ private static selectedQuality = 3;
15
+
16
+ /** Initialize with playlist and quality */
17
+ static initialize(playlist: any[], quality = 3) {
18
+ this.playlist = playlist;
19
+ this.selectedQuality = quality;
20
20
  }
21
- this.playlist = [...playlist];
22
- this.selectedQuality = quality;
23
- this.isInitialized = true;
24
- }
25
-
26
- static async play(song: any, index = 0) {
27
- if (!this.isInitialized) return;
28
- if (!song?.downloadUrl) return;
29
-
30
- await this.stop();
31
-
32
- this.currentSong = song;
33
- this.currentIndex = index;
34
- const url = song.downloadUrl[this.selectedQuality]?.url || song.downloadUrl[0]?.url;
35
-
36
- if (!url) return;
37
-
38
- if (!this.audio) this.audio = new Audio();
39
-
40
- this.audio.src = url;
41
- this.audio.play().catch(console.error);
42
-
43
- this.audio.onloadedmetadata = () => this.duration = this.audio!.duration;
44
- this.audio.ontimeupdate = () => this.currentTime = this.audio!.currentTime;
45
- this.audio.onended = () => this.autoNext();
46
-
47
- await this.setupMusicControls(song, true);
48
-
49
- this.isPlaying = true;
50
- }
51
-
52
- private static async setupMusicControls(song: any, isPlaying: boolean) {
53
- if (!Capacitor.isNativePlatform()) return;
54
-
55
- await CapacitorMusicControls.destroy(); // clear existing
56
- await CapacitorMusicControls.create({
57
- track: song.name || '',
58
- artist: song.primaryArtists || '',
59
- album: song.album || '',
60
- cover: song.image || '',
61
- isPlaying,
62
- dismissable: true,
63
- hasPrev: true,
64
- hasNext: true,
65
- });
66
-
67
- CapacitorMusicControls.addListener('music-controls-next', () => this.next());
68
- CapacitorMusicControls.addListener('music-controls-previous', () => this.prev());
69
- CapacitorMusicControls.addListener('music-controls-pause', () => this.pause());
70
- CapacitorMusicControls.addListener('music-controls-play', () => this.resume());
71
- CapacitorMusicControls.addListener('music-controls-destroy', () => this.stop());
72
- }
73
-
74
- static async pause() {
75
- if (this.audio) this.audio.pause();
76
- this.isPlaying = false;
77
- Capacitor.isNativePlatform() && CapacitorMusicControls.updateIsPlaying({ isPlaying: false });
78
-
79
- }
80
-
81
- static async resume() {
82
- if (this.audio) await this.audio.play();
83
- this.isPlaying = true;
84
- Capacitor.isNativePlatform() && CapacitorMusicControls.updateIsPlaying({ isPlaying: true });
85
-
86
- }
87
-
88
- static async stop() {
89
- if (this.audio) {
90
- this.audio.pause();
21
+
22
+ /** Call this once on user gesture to unlock audio in WebView */
23
+ static unlockAudio() {
91
24
  this.audio.src = '';
25
+ this.audio.load();
26
+ this.audio.play().catch(() => {});
92
27
  }
93
- this.isPlaying = false;
94
- await CapacitorMusicControls.destroy();
95
- }
96
-
97
- static async togglePlayPause() {
98
- if (this.isPlaying) {
99
- await this.pause();
100
- } else if (this.currentSong) {
101
- await this.resume();
102
- } else if (this.playlist.length > 0) {
103
- await this.play(this.playlist[0], 0);
28
+
29
+ static play(song: any, index: number = 0) {
30
+ if (!song || !song.downloadUrl) return;
31
+
32
+ this.currentSong = song;
33
+ this.currentIndex = index;
34
+ this.audio.src = song.downloadUrl[this.selectedQuality]?.url || '';
35
+ this.audio.load(); // Ensure audio is loaded before play
36
+ this.audio.play().then(() => {
37
+ this.isPlaying = true;
38
+ }).catch((err) => {
39
+ // Handle play errors (autoplay, WebView restrictions)
40
+ this.isPlaying = false;
41
+ console.warn('Audio play failed:', err);
42
+ });
43
+
44
+ // Set duration
45
+ this.audio.onloadedmetadata = () => {
46
+ this.duration = this.audio.duration;
47
+ };
48
+
49
+ // Set current time
50
+ this.audio.ontimeupdate = () => {
51
+ this.currentTime = this.audio.currentTime;
52
+ };
53
+
54
+ // Auto-play next song
55
+ this.audio.onended = () => {
56
+ this.autoNext();
57
+ };
104
58
  }
105
- }
106
-
107
- static async next() {
108
- if (this.queue.length > 0) {
109
- const next = this.queue.shift();
110
- const index = this.playlist.findIndex(s => s.id === next.id);
111
- await this.play(next, index);
112
- } else if (this.isShuffle) {
113
- await this.playRandom();
114
- } else if (this.currentIndex < this.playlist.length - 1) {
115
- await this.play(this.playlist[this.currentIndex + 1], this.currentIndex + 1);
59
+
60
+ static pause() {
61
+ this.audio.pause();
62
+ this.isPlaying = false;
116
63
  }
117
- }
118
-
119
- static async prev() {
120
- if (this.currentTime > 3) {
121
- await this.seekTo(0);
122
- } else if (this.currentIndex > 0) {
123
- await this.play(this.playlist[this.currentIndex - 1], this.currentIndex - 1);
64
+
65
+ static resume() {
66
+ this.audio.play();
67
+ this.isPlaying = true;
124
68
  }
125
- }
126
-
127
- static async autoNext() {
128
- await this.next();
129
- }
130
-
131
- static async playRandom() {
132
- if (this.playlist.length <= 1) return;
133
- let rand = this.currentIndex;
134
- while (rand === this.currentIndex) {
135
- rand = Math.floor(Math.random() * this.playlist.length);
69
+
70
+ static togglePlayPause() {
71
+ if (this.isPlaying) {
72
+ this.pause();
73
+ } else {
74
+ this.resume();
75
+ }
136
76
  }
137
- await this.play(this.playlist[rand], rand);
138
- }
139
-
140
- static toggleShuffle() {
141
- this.isShuffle = !this.isShuffle;
142
- }
143
-
144
- static addToQueue(song: any) {
145
- if (!this.queue.find(s => s.id === song.id)) {
146
- this.queue.push(song);
77
+
78
+ static next() {
79
+ if (this.queue.length > 0) {
80
+ const nextQueued = this.queue.shift();
81
+ const index = this.playlist.findIndex(s => s.id === nextQueued.id);
82
+ this.play(nextQueued, index);
83
+ } else if (this.isShuffle) {
84
+ this.playRandom();
85
+ } else if (this.currentIndex < this.playlist.length - 1) {
86
+ this.play(this.playlist[this.currentIndex + 1], this.currentIndex + 1);
87
+ }
147
88
  }
148
- }
149
-
150
- static removeFromQueue(index: number) {
151
- if (index >= 0 && index < this.queue.length) {
152
- this.queue.splice(index, 1);
89
+
90
+ static prev() {
91
+ if (this.currentIndex > 0) {
92
+ this.play(this.playlist[this.currentIndex - 1], this.currentIndex - 1);
93
+ }
153
94
  }
154
- }
155
-
156
- static reorderQueue(from: number, to: number) {
157
- if (from === to) return;
158
- const [item] = this.queue.splice(from, 1);
159
- this.queue.splice(to, 0, item);
160
- }
161
-
162
- static async seekTo(seconds: number) {
163
- if (this.audio) {
95
+
96
+ static seek(seconds: number) {
164
97
  this.audio.currentTime = seconds;
165
- this.currentTime = seconds;
166
98
  }
167
- }
168
-
169
- static getCurrentTime(): number {
170
- return this.currentTime;
171
- }
172
-
173
- static getDuration(): number {
174
- return this.duration;
175
- }
176
-
177
- static formatTime(t: number): string {
178
- const m = Math.floor(t / 60);
179
- const s = Math.floor(t % 60);
180
- return `${m}:${s < 10 ? '0' : ''}${s}`;
181
- }
182
-
183
- static isPlayingSong(): boolean {
184
- return this.isPlaying;
185
- }
186
-
187
- static getCurrentSong(): any {
188
- return this.currentSong;
189
- }
190
-
191
- static setQuality(index: number) {
192
- this.selectedQuality = index;
193
- }
194
-
195
- static getQueue(): any[] {
196
- return [...this.queue];
197
- }
198
-
199
- static getPlaylist(): any[] {
200
- return [...this.playlist];
201
- }
202
-
203
- static getShuffleStatus(): boolean {
204
- return this.isShuffle;
205
- }
99
+
100
+ static autoNext() {
101
+ this.next();
102
+ }
103
+
104
+ static playRandom() {
105
+ if (this.playlist.length <= 1) return;
106
+
107
+ let randomIndex;
108
+ do {
109
+ randomIndex = Math.floor(Math.random() * this.playlist.length);
110
+ } while (randomIndex === this.currentIndex);
111
+
112
+ this.play(this.playlist[randomIndex], randomIndex);
113
+ }
114
+
115
+ static toggleShuffle() {
116
+ this.isShuffle = !this.isShuffle;
117
+ }
206
118
 
207
- static async destroy() {
208
- await this.stop();
209
- this.playlist = [];
210
- this.queue = [];
211
- this.audio = null;
212
- this.isInitialized = false;
119
+ static getShuffleStatus(): boolean {
120
+ return this.isShuffle;
121
+ }
122
+
123
+ static addToQueue(song: any) {
124
+ if (!this.queue.some(q => q.id === song.id)) {
125
+ this.queue.push(song);
126
+ this.queue$.next([...this.queue]);
127
+ }
128
+ }
129
+
130
+ static removeFromQueue(index: number) {
131
+ this.queue.splice(index, 1);
132
+ this.queue$.next([...this.queue]);
133
+ }
134
+
135
+ static reorderQueue(from: number, to: number) {
136
+ const item = this.queue.splice(from, 1)[0];
137
+ this.queue.splice(to, 0, item);
138
+ this.queue$.next([...this.queue]);
139
+ }
140
+
141
+ static getCurrentTime(): number {
142
+ return this.currentTime;
143
+ }
144
+
145
+ static getDuration(): number {
146
+ return this.duration;
147
+ }
148
+
149
+ static formatTime(time: number): string {
150
+ const minutes = Math.floor(time / 60);
151
+ const seconds = Math.floor(time % 60);
152
+ return `${minutes}:${seconds < 10 ? '0' : ''}${seconds}`;
153
+ }
154
+
155
+ static isPlayingSong(): boolean {
156
+ return this.isPlaying;
157
+ }
158
+
159
+ static getCurrentSong(): any {
160
+ return this.currentSong;
161
+ }
162
+
163
+ static setQuality(index: number) {
164
+ this.selectedQuality = index;
165
+ }
166
+
167
+ static getQueue(): any[] {
168
+ return this.queue;
169
+ }
170
+
171
+ static getPlaylist(): any[] {
172
+ return this.playlist;
173
+ }
213
174
  }
214
- }
package/tsconfig.json CHANGED
@@ -14,8 +14,7 @@
14
14
  "esModuleInterop": true, // allow default imports from CommonJS
15
15
  "forceConsistentCasingInFileNames": true,
16
16
  "strict": true,
17
- "skipLibCheck": true,
18
- "types": ["@capacitor-community/native-audio"] // speed up builds, safe for libs
17
+ "skipLibCheck": true // speed up builds, safe for libs
19
18
  },
20
19
  "include": ["src"] // only compile the src folder
21
20
  }