station sheet gets STATION FROM THIS TRACK and SHARE STATION; the * STATION pill goes; one fewer emoji in the tray so + stays on the row on phones
shots / shots (push) Successful in 2m17s
shots / shots (push) Successful in 2m17s
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K6897PWcUEwHiqZMcVnNF6
This commit is contained in:
1 parent
97d8bc938f
commit
fcdaaff678
1 file changed
+15
-5
+15
-5
@@ -299,7 +299,7 @@ input,textarea{font:inherit;color:inherit}
|
||||
</div><div id="trail" title="what this station has played · tap to jump"></div></div>
|
||||
<div id="meta"><h1 id="title">…</h1></div>
|
||||
<div id="bar"><i></i></div>
|
||||
<div id="meta2"><p id="lyric" title="reply to the DJ"></p><div id="next"></div><div id="pills"><button id="lyricsBtn">⇄ LYRICS</button><button id="keep" disabled>➕ KEEP</button><button id="share" disabled>↗ SHARE</button><button id="fromTrack" disabled title="start a new station from this track">* STATION</button></div><p id="tags" class="hidden"></p><div id="tagRow"></div><div id="tagList"></div></div>
|
||||
<div id="meta2"><p id="lyric" title="reply to the DJ"></p><div id="next"></div><div id="pills"><button id="lyricsBtn">⇄ LYRICS</button><button id="keep" disabled>➕ KEEP</button><button id="share" disabled>↗ SHARE</button></div><p id="tags" class="hidden"></p><div id="tagRow"></div><div id="tagList"></div></div>
|
||||
<div id="controls">
|
||||
<button id="backTrack" title="previous track">
|
||||
<svg viewBox="0 0 24 24"><path d="M18 6l-8.5 6 8.5 6V6zM6 6v12h2V6H6z"/></svg>
|
||||
@@ -330,7 +330,6 @@ input,textarea{font:inherit;color:inherit}
|
||||
<button data-e="🌧️" title="sadder">🌧️</button>
|
||||
<button data-e="⚡" title="faster, louder">⚡</button>
|
||||
<button data-e="🎸" title="more guitar">🎸</button>
|
||||
<button data-e="🎹" title="more keys">🎹</button>
|
||||
<button data-e="🚫" title="not this">🚫</button>
|
||||
<button id="more" title="more emoji">+</button>
|
||||
</div>
|
||||
@@ -880,6 +879,18 @@ async function stationSheet(id) {
|
||||
palRow.append(b);
|
||||
}
|
||||
p.append(palRow);
|
||||
if (state.stationId === id) {
|
||||
const more = document.createElement("div"); more.className = "row"; more.style.marginTop = "10px"; more.style.justifyContent = "flex-start";
|
||||
const fromT = Object.assign(document.createElement("button"), { textContent: "* STATION FROM THIS TRACK", title: "a new station grown from the track playing now" });
|
||||
fromT.disabled = !(state.current && state.current.blob && !state.current.spec.break);
|
||||
fromT.addEventListener("click", () => { p.classList.add("hidden"); stationFromCurrent(); });
|
||||
const shareS = Object.assign(document.createElement("button"), { textContent: "↗ SHARE STATION", title: "a link that opens this station's seed" });
|
||||
shareS.addEventListener("click", async () => {
|
||||
const url = `${location.origin}/#${encodeURIComponent(s.seed).replace(/%20/g, "+")}`;
|
||||
try { if (navigator.share) await navigator.share({ title: `${s.name || s.seed} · gandora`, url }); else { await navigator.clipboard.writeText(url); toast("Station link copied."); } } catch {}
|
||||
});
|
||||
more.append(fromT, shareS); p.append(more);
|
||||
}
|
||||
const row = document.createElement("div"); row.className = "row";
|
||||
const save = Object.assign(document.createElement("button"), { className: "go", textContent: "SAVE" });
|
||||
save.addEventListener("click", async () => { s.name = name.value.trim().slice(0, 60); await db.put(s, "stations"); if (state.stationId === id) { state.station = s.name; $("#stationName").textContent = s.name || s.seed; } p.classList.add("hidden"); listStations().catch(() => {}); toast("Renamed."); });
|
||||
@@ -944,12 +955,12 @@ async function stationFrom(t) {
|
||||
state.refFor = { blob: t.blob, left: 2, seconds: s.seconds || 120 }; // the next two tracks are rendered with the source as reference
|
||||
toast(`New station from “${s.title}”.`, 3000);
|
||||
}
|
||||
$("#fromTrack").addEventListener("click", async () => {
|
||||
async function stationFromCurrent() {
|
||||
const cur = state.current && state.current.spec; if (!cur) return;
|
||||
const row = (await db.all()).find((t) => t.id === cur.id) || (state.current.blob ? { spec: cur, blob: state.current.blob } : null);
|
||||
if (!row) { toast("That one hasn't finished cooking."); return; }
|
||||
stationFrom(row);
|
||||
});
|
||||
}
|
||||
const KEEP_UNKEPT = 40;
|
||||
// every rendered track is saved so the station can be scrolled back through; ❤️ pins one, the rest roll off after KEEP_UNKEPT
|
||||
async function remember(job, kept) {
|
||||
@@ -1048,7 +1059,6 @@ async function playJob(job) {
|
||||
if (state.current !== job) return; // skipped while cooking
|
||||
$("#cover").classList.remove("cooking");
|
||||
crackleOff();
|
||||
$("#fromTrack").disabled = false;
|
||||
if (job.err) { crackleOff(); toast(job.err.message, 6000); $("#lyric").textContent = job.err.message + (/limit|budget/i.test(job.err.message) ? "" : " · skip to try the next"); return; }
|
||||
if (state.audio.src) URL.revokeObjectURL(state.audio.src);
|
||||
state.audio.src = URL.createObjectURL(job.blob);
|
||||
|
||||
Reference in new issue
Block a user