move web components to web/
This commit is contained in:
207
web/frontend/src/api/player.tsx
Normal file
207
web/frontend/src/api/player.tsx
Normal file
@@ -0,0 +1,207 @@
|
||||
export interface NowPlayingResponse {
|
||||
success: boolean;
|
||||
playingItem: PlaylistItem;
|
||||
isPaused: boolean;
|
||||
volume: number;
|
||||
isIdle: boolean;
|
||||
currentFile: string;
|
||||
timePosition?: number;
|
||||
duration?: number;
|
||||
seekable?: boolean;
|
||||
}
|
||||
|
||||
export interface Features {
|
||||
video: boolean;
|
||||
screenshare: boolean;
|
||||
browserPlayback: boolean;
|
||||
}
|
||||
|
||||
export interface Metadata {
|
||||
title?: string;
|
||||
description?: string;
|
||||
siteName?: string;
|
||||
}
|
||||
|
||||
export interface PlaylistItem {
|
||||
filename: string;
|
||||
title: string | null;
|
||||
id: number;
|
||||
playing: boolean | null;
|
||||
metadata?: Metadata;
|
||||
}
|
||||
|
||||
export const getDisplayTitle = (item: PlaylistItem): string => {
|
||||
return item.title || item.metadata?.title || item.filename;
|
||||
}
|
||||
|
||||
export interface MetadataUpdateEvent {
|
||||
event: 'metadata_update';
|
||||
data: {
|
||||
url: string;
|
||||
metadata: Metadata;
|
||||
};
|
||||
}
|
||||
|
||||
export interface SearchResult {
|
||||
type: string;
|
||||
title: string;
|
||||
author: string;
|
||||
mediaUrl: string;
|
||||
thumbnailUrl: string;
|
||||
}
|
||||
|
||||
export interface SearchResponse {
|
||||
success: boolean;
|
||||
results: SearchResult[];
|
||||
}
|
||||
|
||||
export enum ServerEvent {
|
||||
PlaylistUpdate = "playlist_update",
|
||||
NowPlayingUpdate = "now_playing_update",
|
||||
VolumeUpdate = "volume_update",
|
||||
FavoritesUpdate = "favorites_update",
|
||||
MetadataUpdate = "metadata_update",
|
||||
MPDUpdate = "mpd_update",
|
||||
ScreenShare = "screen_share",
|
||||
}
|
||||
|
||||
export const API = {
|
||||
async getFeatures(): Promise<Features> {
|
||||
const response = await fetch('/api/features');
|
||||
return response.json();
|
||||
},
|
||||
|
||||
async getPlaylist(): Promise<PlaylistItem[]> {
|
||||
const response = await fetch('/api/playlist');
|
||||
return response.json();
|
||||
},
|
||||
|
||||
async addToPlaylist(url: string): Promise<void> {
|
||||
await fetch('/api/playlist', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ url }),
|
||||
});
|
||||
},
|
||||
|
||||
async replaceCurrentFile(url: string): Promise<void> {
|
||||
await fetch('/api/playlist/replace', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ url }),
|
||||
});
|
||||
},
|
||||
|
||||
async removeFromPlaylist(index: number): Promise<void> {
|
||||
await fetch(`/api/playlist/${index}`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
},
|
||||
|
||||
async play(): Promise<void> {
|
||||
await fetch('/api/play', { method: 'POST' });
|
||||
},
|
||||
|
||||
async stop(): Promise<void> {
|
||||
await fetch('/api/stop', { method: 'POST' });
|
||||
},
|
||||
|
||||
async pause(): Promise<void> {
|
||||
await fetch('/api/pause', { method: 'POST' });
|
||||
},
|
||||
|
||||
async skip(): Promise<void> {
|
||||
await fetch('/api/skip', { method: 'POST' });
|
||||
},
|
||||
|
||||
async skipTo(index: number): Promise<void> {
|
||||
await fetch(`/api/skip/${index}`, { method: 'POST' });
|
||||
},
|
||||
|
||||
async previous(): Promise<void> {
|
||||
await fetch('/api/previous', { method: 'POST' });
|
||||
},
|
||||
|
||||
async getNowPlaying(): Promise<NowPlayingResponse> {
|
||||
const response = await fetch('/api/nowplaying');
|
||||
return response.json();
|
||||
},
|
||||
|
||||
async setVolume(volume: number): Promise<void> {
|
||||
await fetch('/api/volume', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ volume }),
|
||||
});
|
||||
},
|
||||
|
||||
async seek(time: number): Promise<void> {
|
||||
await fetch('/api/player/seek', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ time }),
|
||||
});
|
||||
},
|
||||
|
||||
async search(query: string): Promise<SearchResponse> {
|
||||
const response = await fetch(`/api/search?q=${encodeURIComponent(query)}`);
|
||||
return response.json();
|
||||
},
|
||||
|
||||
subscribeToEvents(onMessage: (event: any) => void): WebSocket {
|
||||
const protocol = window.location.protocol === 'https:' ? 'wss' : 'ws';
|
||||
const ws = new WebSocket(`${protocol}://${window.location.host}/api/events`);
|
||||
ws.onmessage = (event) => {
|
||||
onMessage(JSON.parse(event.data));
|
||||
};
|
||||
|
||||
return ws;
|
||||
},
|
||||
|
||||
async getFavorites(): Promise<PlaylistItem[]> {
|
||||
const response = await fetch('/api/favorites');
|
||||
return response.json();
|
||||
},
|
||||
|
||||
async addToFavorites(filename: string): Promise<void> {
|
||||
await fetch('/api/favorites', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ filename }),
|
||||
});
|
||||
},
|
||||
|
||||
async removeFromFavorites(filename: string): Promise<void> {
|
||||
await fetch(`/api/favorites/${encodeURIComponent(filename)}`, { method: 'DELETE' });
|
||||
},
|
||||
|
||||
async clearFavorites(): Promise<void> {
|
||||
await fetch('/api/favorites', { method: 'DELETE' });
|
||||
},
|
||||
|
||||
async updateFavoriteTitle(filename: string, title: string): Promise<void> {
|
||||
await fetch(`/api/favorites/${encodeURIComponent(filename)}/title`, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ title }),
|
||||
});
|
||||
},
|
||||
|
||||
startScreenShare(mimeType: string): WebSocket {
|
||||
const protocol = window.location.protocol === 'https:' ? 'wss' : 'ws';
|
||||
const ws = new WebSocket(`${protocol}://${window.location.host}/api/screenshare?mimeType=${mimeType}`);
|
||||
return ws;
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user