90 lines
2.2 KiB
TypeScript
90 lines
2.2 KiB
TypeScript
import type { ReactiveController, ReactiveControllerHost } from 'lit';
|
|
import type { PlayerState, TrackInfo } from '../player-store';
|
|
import { playerStore } from '../player-store';
|
|
|
|
/**
|
|
* PlayerController connects a Lit component to the PlayerStore.
|
|
*
|
|
* Usage in a component:
|
|
*
|
|
* private player = new PlayerController(this);
|
|
*
|
|
* render() {
|
|
* return html`
|
|
* <span>${this.player.currentTrack?.fileName}</span>
|
|
* <button @click=${() => this.player.play()}>Play</button>
|
|
* `;
|
|
* }
|
|
*/
|
|
export class PlayerController implements ReactiveController {
|
|
private host: ReactiveControllerHost;
|
|
private unsubscribe?: () => void;
|
|
|
|
constructor(host: ReactiveControllerHost) {
|
|
this.host = host;
|
|
host.addController(this);
|
|
}
|
|
|
|
// ===================================================================
|
|
// LIFECYCLE HOOKS
|
|
// ===================================================================
|
|
|
|
hostConnected(): void {
|
|
// Subscribe to store when component mounts
|
|
this.unsubscribe = playerStore.subscribe(() => {
|
|
this.host.requestUpdate();
|
|
});
|
|
}
|
|
|
|
hostDisconnected(): void {
|
|
// Unsubscribe when component unmounts (prevents memory leaks)
|
|
this.unsubscribe?.();
|
|
}
|
|
|
|
// ===================================================================
|
|
// STATE ACCESSORS
|
|
// Convenience getters so components don't need to call getState()
|
|
// ===================================================================
|
|
|
|
get state(): Readonly<PlayerState> {
|
|
return playerStore.getState();
|
|
}
|
|
|
|
get isPlaying(): boolean {
|
|
return this.state.isPlaying;
|
|
}
|
|
|
|
get currentTrack(): TrackInfo | null {
|
|
return this.state.currentTrack;
|
|
}
|
|
|
|
get volume(): number {
|
|
return this.state.volume;
|
|
}
|
|
|
|
// ===================================================================
|
|
// ACTIONS
|
|
// Delegate to store (which delegates to backend)
|
|
// ===================================================================
|
|
|
|
play(): void {
|
|
playerStore.play();
|
|
}
|
|
|
|
pause(): void {
|
|
playerStore.pause();
|
|
}
|
|
|
|
loadTrack(filePath: string): void {
|
|
playerStore.loadTrack(filePath);
|
|
}
|
|
|
|
seek(seconds: number): void {
|
|
playerStore.seek(seconds);
|
|
}
|
|
|
|
setVolume(level: number): void {
|
|
playerStore.setVolume(level);
|
|
}
|
|
}
|