diff --git a/.direnv/nix-profile-.9418.c7f47036d3df b/.direnv/nix-profile-.9840.a4bf06618f0b similarity index 100% rename from .direnv/nix-profile-.9418.c7f47036d3df rename to .direnv/nix-profile-.9840.a4bf06618f0b diff --git a/.direnv/nix-profile-.9418.c7f47036d3df.rc b/.direnv/nix-profile-.9840.a4bf06618f0b.rc similarity index 100% rename from .direnv/nix-profile-.9418.c7f47036d3df.rc rename to .direnv/nix-profile-.9840.a4bf06618f0b.rc diff --git a/src/main/resources/static/css/styles.css b/src/main/resources/static/css/styles.css index 8f607a4..0f6e271 100644 --- a/src/main/resources/static/css/styles.css +++ b/src/main/resources/static/css/styles.css @@ -1069,6 +1069,14 @@ button:disabled:hover { font-size: 12px; padding: 5px 8px; 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 { @@ -1095,6 +1103,7 @@ button:disabled:hover { border-radius: 8px; border: 1px solid transparent; transition: background 0.12s; + cursor: pointer; } .playlist-list-item:hover { @@ -1171,6 +1180,14 @@ button:disabled:hover { font-size: 12px; padding: 4px 7px; 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 */ diff --git a/src/main/resources/static/js/playlist.js b/src/main/resources/static/js/playlist.js index 78bdea2..612eee2 100644 --- a/src/main/resources/static/js/playlist.js +++ b/src/main/resources/static/js/playlist.js @@ -62,7 +62,8 @@ if (csrfToken && csrfHeader) headers[csrfHeader] = csrfToken; const response = await fetch(`${apiBase()}${path}`, { ...options, headers }); 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(); } @@ -160,10 +161,10 @@ if (!name) { showToast("Enter a playlist name.", "info"); return; } try { const view = await apiFetch("", { method: "POST", body: JSON.stringify({ name }) }); - playlists.push(view); input.value = ""; - renderPlaylistList(); - expandPlaylist(view.id); + // Don't push locally — the PLAYLIST_CREATED STOMP event will add it. + // Just pre-set the expanded id so it opens as soon as the event renders it. + if (view?.id) expandedPlaylistId = view.id; } catch { showToast("Could not create playlist.", "error"); } @@ -186,11 +187,11 @@ const li = document.createElement("li"); li.className = "playlist-list-item" + (p.id === expandedPlaylistId ? " expanded" : "") + (p.id === activePlaylistId ? " active" : ""); li.dataset.id = p.id; + li.addEventListener("click", () => toggleExpand(p.id)); const nameSpan = document.createElement("span"); nameSpan.className = "playlist-list-name"; nameSpan.textContent = p.name; - nameSpan.addEventListener("click", () => toggleExpand(p.id)); const actions = document.createElement("div"); actions.className = "playlist-list-actions";