Add actions
This commit is contained in:
Vendored
+48
-2
@@ -553,6 +553,23 @@ export interface paths {
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/users/{id}/last-listened-track": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
|
||||
get: operations["GetLastTrackListenedByUserId"];
|
||||
put?: never;
|
||||
post?: never;
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/users/{id}/listening-stats": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
@@ -560,7 +577,7 @@ export interface paths {
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
|
||||
|
||||
get: operations["GetListeningStats"];
|
||||
put?: never;
|
||||
post?: never;
|
||||
@@ -2364,7 +2381,7 @@ export interface operations {
|
||||
};
|
||||
requestBody?: never;
|
||||
responses: {
|
||||
|
||||
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
@@ -2375,6 +2392,35 @@ export interface operations {
|
||||
};
|
||||
};
|
||||
};
|
||||
GetLastTrackListenedByUserId: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path: {
|
||||
id: number | string;
|
||||
};
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody?: never;
|
||||
responses: {
|
||||
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["TrackApplicationResponse"];
|
||||
};
|
||||
};
|
||||
|
||||
404: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content?: never;
|
||||
};
|
||||
};
|
||||
};
|
||||
GetUserProfile: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
|
||||
@@ -315,6 +315,15 @@ class PlayerState {
|
||||
return `${url}${sep}t=${encodeURIComponent(ticket)}`;
|
||||
}
|
||||
|
||||
hydrate(item: ApiTrackLike) {
|
||||
if (this.currentId !== null || this.tracks.length > 0) return;
|
||||
const track = toTrack(toQueueItem(item));
|
||||
this.tracks = [track];
|
||||
this.currentId = track.id;
|
||||
this.#applyAccent(track.id);
|
||||
this.#syncMediaSessionMetadata(track);
|
||||
}
|
||||
|
||||
playlistTracks(ids: (string | number)[]): PlayerTrack[] {
|
||||
return ids
|
||||
.map((id) => this.tracks.find((t) => t.id === id))
|
||||
@@ -384,6 +393,10 @@ class PlayerState {
|
||||
toggle() {
|
||||
const audio = this.#audioEl();
|
||||
if (!audio || this.currentId === null) return;
|
||||
if (!audio.src) {
|
||||
this.#loadCurrent();
|
||||
return;
|
||||
}
|
||||
if (audio.paused) audio.play().catch(() => {});
|
||||
else audio.pause();
|
||||
}
|
||||
|
||||
@@ -39,6 +39,22 @@ async function fetchLikedTracks(fetchFn: typeof fetch, accessToken: string | nul
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchLastPlayedTrack(
|
||||
fetchFn: typeof fetch,
|
||||
accessToken: string | null,
|
||||
userId: string
|
||||
) {
|
||||
try {
|
||||
const api = createApiClient({ fetch: fetchFn, accessToken: accessToken ?? undefined });
|
||||
const { data } = await api.GET('/users/{id}/last-listened-track', {
|
||||
params: { path: { id: userId } }
|
||||
});
|
||||
return data ?? null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export const load: LayoutServerLoad = async ({ locals, url, fetch }) => {
|
||||
const allowAnonymousListening = await getAllowAnonymousListening(fetch);
|
||||
|
||||
@@ -56,13 +72,15 @@ export const load: LayoutServerLoad = async ({ locals, url, fetch }) => {
|
||||
allowAnonymousListening,
|
||||
sidebarPlaylists: [],
|
||||
likedTracks: [],
|
||||
lastPlayedTrack: null,
|
||||
accountUrl
|
||||
};
|
||||
}
|
||||
|
||||
const [sidebarPlaylists, likedTracks] = await Promise.all([
|
||||
const [sidebarPlaylists, likedTracks, lastPlayedTrack] = await Promise.all([
|
||||
fetchSidebarPlaylists(fetch, locals.accessToken, locals.user.sub),
|
||||
fetchLikedTracks(fetch, locals.accessToken)
|
||||
fetchLikedTracks(fetch, locals.accessToken),
|
||||
fetchLastPlayedTrack(fetch, locals.accessToken, locals.user.sub)
|
||||
]);
|
||||
|
||||
return {
|
||||
@@ -70,6 +88,7 @@ export const load: LayoutServerLoad = async ({ locals, url, fetch }) => {
|
||||
allowAnonymousListening,
|
||||
sidebarPlaylists,
|
||||
likedTracks,
|
||||
lastPlayedTrack,
|
||||
accountUrl
|
||||
};
|
||||
};
|
||||
|
||||
@@ -30,15 +30,19 @@
|
||||
if (data.likedTracks?.length) liked.hydrate(data.likedTracks);
|
||||
});
|
||||
|
||||
$effect(() => {
|
||||
if (data.lastPlayedTrack) player.hydrate(data.lastPlayedTrack);
|
||||
});
|
||||
|
||||
const isAuthPage = $derived(page.url.pathname === '/auth');
|
||||
const hasTrack = $derived(player.currentId !== null);
|
||||
|
||||
const initialThemeCss = `:root{${tokensToCss(buildThemeTokens(ACCENT_HUE, 'dark'))}}:root[data-theme='light']{${tokensToCss(buildThemeTokens(ACCENT_HUE, 'light'))}}`;
|
||||
|
||||
let hadTrack = false;
|
||||
let wasPlaying = false;
|
||||
$effect(() => {
|
||||
if (hasTrack && !hadTrack) queuePanel.show();
|
||||
hadTrack = hasTrack;
|
||||
if (player.playing && !wasPlaying) queuePanel.show();
|
||||
wasPlaying = player.playing;
|
||||
});
|
||||
|
||||
function isTypingTarget(target: EventTarget | null): boolean {
|
||||
|
||||
Reference in New Issue
Block a user