mirror of
https://github.com/imgfloat/server.git
synced 2026-06-22 21:01:23 +00:00
fix: playlist panel UX issues
- Phantom playlists: stop pushing locally on create; let PLAYLIST_CREATED STOMP event add the entry to avoid the REST/STOMP race that doubled items - Row click: attach toggle-expand listener on the li instead of the name span only; add cursor:pointer to .playlist-list-item - Input styling: apply surface-3 bg, border, radius, and color to .playlist-create-row input and .playlist-rename-form input with focus ring - Play/pause error toast: apiFetch now skips json() when response has no application/json Content-Type (empty 200 body from play/pause endpoints)
This commit is contained in:
@@ -1069,6 +1069,14 @@ button:disabled:hover {
|
|||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
padding: 5px 8px;
|
padding: 5px 8px;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
background: var(--color-surface-3);
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
border-radius: 6px;
|
||||||
|
color: var(--color-text);
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
.playlist-create-row input:focus {
|
||||||
|
border-color: var(--color-accent-border);
|
||||||
}
|
}
|
||||||
|
|
||||||
.playlist-list {
|
.playlist-list {
|
||||||
@@ -1095,6 +1103,7 @@ button:disabled:hover {
|
|||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
border: 1px solid transparent;
|
border: 1px solid transparent;
|
||||||
transition: background 0.12s;
|
transition: background 0.12s;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.playlist-list-item:hover {
|
.playlist-list-item:hover {
|
||||||
@@ -1171,6 +1180,14 @@ button:disabled:hover {
|
|||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
padding: 4px 7px;
|
padding: 4px 7px;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
background: var(--color-surface-3);
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
border-radius: 6px;
|
||||||
|
color: var(--color-text);
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
.playlist-rename-form input:focus {
|
||||||
|
border-color: var(--color-accent-border);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Playback controls */
|
/* Playback controls */
|
||||||
|
|||||||
@@ -62,7 +62,8 @@
|
|||||||
if (csrfToken && csrfHeader) headers[csrfHeader] = csrfToken;
|
if (csrfToken && csrfHeader) headers[csrfHeader] = csrfToken;
|
||||||
const response = await fetch(`${apiBase()}${path}`, { ...options, headers });
|
const response = await fetch(`${apiBase()}${path}`, { ...options, headers });
|
||||||
if (!response.ok) throw new Error(`Request failed: ${response.status}`);
|
if (!response.ok) throw new Error(`Request failed: ${response.status}`);
|
||||||
if (response.status === 204) return null;
|
const ct = response.headers.get("content-type") || "";
|
||||||
|
if (response.status === 204 || !ct.includes("application/json")) return null;
|
||||||
return response.json();
|
return response.json();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,10 +161,10 @@
|
|||||||
if (!name) { showToast("Enter a playlist name.", "info"); return; }
|
if (!name) { showToast("Enter a playlist name.", "info"); return; }
|
||||||
try {
|
try {
|
||||||
const view = await apiFetch("", { method: "POST", body: JSON.stringify({ name }) });
|
const view = await apiFetch("", { method: "POST", body: JSON.stringify({ name }) });
|
||||||
playlists.push(view);
|
|
||||||
input.value = "";
|
input.value = "";
|
||||||
renderPlaylistList();
|
// Don't push locally — the PLAYLIST_CREATED STOMP event will add it.
|
||||||
expandPlaylist(view.id);
|
// Just pre-set the expanded id so it opens as soon as the event renders it.
|
||||||
|
if (view?.id) expandedPlaylistId = view.id;
|
||||||
} catch {
|
} catch {
|
||||||
showToast("Could not create playlist.", "error");
|
showToast("Could not create playlist.", "error");
|
||||||
}
|
}
|
||||||
@@ -186,11 +187,11 @@
|
|||||||
const li = document.createElement("li");
|
const li = document.createElement("li");
|
||||||
li.className = "playlist-list-item" + (p.id === expandedPlaylistId ? " expanded" : "") + (p.id === activePlaylistId ? " active" : "");
|
li.className = "playlist-list-item" + (p.id === expandedPlaylistId ? " expanded" : "") + (p.id === activePlaylistId ? " active" : "");
|
||||||
li.dataset.id = p.id;
|
li.dataset.id = p.id;
|
||||||
|
li.addEventListener("click", () => toggleExpand(p.id));
|
||||||
|
|
||||||
const nameSpan = document.createElement("span");
|
const nameSpan = document.createElement("span");
|
||||||
nameSpan.className = "playlist-list-name";
|
nameSpan.className = "playlist-list-name";
|
||||||
nameSpan.textContent = p.name;
|
nameSpan.textContent = p.name;
|
||||||
nameSpan.addEventListener("click", () => toggleExpand(p.id));
|
|
||||||
|
|
||||||
const actions = document.createElement("div");
|
const actions = document.createElement("div");
|
||||||
actions.className = "playlist-list-actions";
|
actions.className = "playlist-list-actions";
|
||||||
|
|||||||
Reference in New Issue
Block a user