feat: add media queue foundation
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
59
src/media/mediaQueue.ts
Normal file
59
src/media/mediaQueue.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
import type {
|
||||
MediaQueueItem,
|
||||
MediaState,
|
||||
ResolvedMediaSource,
|
||||
} from "./mediaTypes";
|
||||
|
||||
export class MediaQueue {
|
||||
private current: MediaQueueItem | null = null;
|
||||
private readonly items: MediaQueueItem[] = [];
|
||||
|
||||
constructor(
|
||||
private readonly createId = () => crypto.randomUUID(),
|
||||
private readonly now = () => Date.now(),
|
||||
) {}
|
||||
|
||||
add(source: ResolvedMediaSource, requestedBy = "dashboard"): MediaQueueItem {
|
||||
const item: MediaQueueItem = {
|
||||
id: this.createId(),
|
||||
mode: "music",
|
||||
requestedBy,
|
||||
addedAt: this.now(),
|
||||
status: "queued",
|
||||
...source,
|
||||
};
|
||||
this.items.push(item);
|
||||
return { ...item };
|
||||
}
|
||||
|
||||
startNext(): MediaQueueItem | null {
|
||||
if (this.current) return { ...this.current };
|
||||
const next = this.items.shift();
|
||||
if (!next) return null;
|
||||
this.current = { ...next, status: "playing" };
|
||||
return { ...this.current };
|
||||
}
|
||||
|
||||
completeCurrent(): void {
|
||||
this.current = null;
|
||||
}
|
||||
|
||||
failCurrent(): void {
|
||||
if (this.current) {
|
||||
this.current = { ...this.current, status: "failed" };
|
||||
}
|
||||
this.current = null;
|
||||
}
|
||||
|
||||
clear(): void {
|
||||
this.current = null;
|
||||
this.items.length = 0;
|
||||
}
|
||||
|
||||
snapshot(): Pick<MediaState, "current" | "queue"> {
|
||||
return {
|
||||
current: this.current ? { ...this.current } : null,
|
||||
queue: this.items.map((item) => ({ ...item })),
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user