A music player that connects to your cloud/distributed storage.

feat: scrobble feature facet + copy facet descriptions

+60 -13
+2
src/_components/facets/grid.vto
··· 18 18 <li 19 19 class="grid-item" 20 20 data-active-color="{{color}}" 21 + data-description="{{item.desc.trim()}}" 21 22 data-name="{{item.title}}" 23 + data-kind="{{item.kind ?? `interface`}}" 22 24 data-uri="{{ item.url |> facetOrThemeURI }}" 23 25 > 24 26 <div class="grid-item__contents">
+7
src/_data/facets.yaml
··· 10 10 featured: true 11 11 desc: > 12 12 Automatically put tracks into the queue. 13 + - url: "facets/scrobble/index.html" 14 + title: "Scrobble" 15 + kind: "prelude" 16 + category: Misc 17 + featured: true 18 + desc: > 19 + Enable scrobbling, keep track of what you're listening to. 13 20 - url: "facets/scrobble/last.fm/index.html" 14 21 title: "Scrobble / Last.fm" 15 22 category: Misc
+1 -3
src/common/facets/foundation.js
··· 82 82 } 83 83 84 84 async function playAudioFromQueue() { 85 - const [a, q, ms, qa, sca] = await Promise.all([ 85 + const [a, q, ms, qa] = await Promise.all([ 86 86 // engine 87 87 audio(), 88 88 queue(), ··· 90 90 // orchestrator 91 91 mediaSession(), 92 92 queueAudio(), 93 - scrobbleAudio(), 94 93 ]); 95 94 96 95 return { ··· 101 100 orchestrator: { 102 101 mediaSession: ms, 103 102 queueAudio: qa, 104 - scrobbleAudio: sca, 105 103 }, 106 104 }; 107 105 }
+7 -2
src/common/facets/utils.js
··· 10 10 */ 11 11 12 12 /** 13 - * @param {{ name: string; uri: string }} _args 13 + * @param {{ description?: string; kind: string | undefined; name: string; uri: string }} _args 14 14 * @param {{ fetchHTML: boolean }} options 15 15 */ 16 - export async function facetFromURI({ name, uri }, { fetchHTML }) { 16 + export async function facetFromURI( 17 + { description, kind, name, uri }, 18 + { fetchHTML }, 19 + ) { 17 20 const html = fetchHTML ? await loadURI(uri) : undefined; 18 21 const cid = html 19 22 ? await CID.create(0x55, new TextEncoder().encode(html)) ··· 26 29 createdAt: timestamp, 27 30 id: TID.now(), 28 31 cid, 32 + description, 29 33 html, 30 34 name, 35 + kind: kind === "interactive" || kind === "prelude" ? kind : undefined, 31 36 updatedAt: timestamp, 32 37 uri, 33 38 };
+7 -2
src/facets/common/build.js
··· 105 105 const cid = await CID.create(0x55, new TextEncoder().encode(html)); 106 106 const name = nameEl?.value ?? "nameless"; 107 107 const description = descriptionEl?.value ?? ""; 108 - const kind = /** @type {"interactive" | "prelude"} */ (kindEl?.value ?? "interactive"); 108 + const kind = 109 + /** @type {"interactive" | "prelude"} */ (kindEl?.value ?? "interactive"); 109 110 110 111 /** @type {Facet} */ 111 112 const facet = $editingFacet.value ··· 231 232 const name = target.closest("li")?.getAttribute("data-name"); 232 233 if (!name) return; 233 234 235 + const kind = target.closest("li")?.getAttribute("data-kind") ?? undefined; 236 + 234 237 switch (rel) { 235 238 case "edit": { 236 - const facet = await facetFromURI({ name, uri }, { fetchHTML: true }); 239 + const facet = await facetFromURI({ kind, name, uri }, { 240 + fetchHTML: true, 241 + }); 237 242 editFacet(facet); 238 243 document.querySelector("#build")?.scrollIntoView(); 239 244 break;
+6 -1
src/facets/common/grid.js
··· 26 26 27 27 const uri = li.getAttribute("data-uri"); 28 28 const name = li.getAttribute("data-name"); 29 + const kind = li.getAttribute("data-kind") ?? undefined; 30 + const description = li.getAttribute("data-description") ?? undefined; 31 + 29 32 if (!uri || !name) return; 30 33 31 34 const out = await foundation.orchestrator.output(); ··· 35 38 if (isActive) { 36 39 out.facets.save(collection.filter((f) => f.uri !== uri)); 37 40 } else { 38 - const facet = await facetFromURI({ name, uri }, { fetchHTML: false }); 41 + const facet = await facetFromURI({ description, kind, name, uri }, { 42 + fetchHTML: false, 43 + }); 39 44 out.facets.save([...collection, facet]); 40 45 } 41 46 });
+22 -1
src/facets/common/you.js
··· 87 87 /> 88 88 </div> 89 89 <div> 90 + <label>Kind</label> 91 + <select id="add-uri-kind"> 92 + <option value="interactive">interface</option> 93 + <option value="prelude">feature</option> 94 + </select> 95 + </div> 96 + <div> 90 97 <label>URI</label> 91 98 <input 92 99 id="add-uri-uri" ··· 118 125 "submit", 119 126 async (e) => { 120 127 e.preventDefault(); 128 + 121 129 const nameEl = /** @type {HTMLInputElement} */ ( 122 130 dialog?.querySelector("#add-uri-name") 123 131 ); 132 + 133 + const kindEl = /** @type {HTMLSelectElement} */ ( 134 + dialog?.querySelector("#add-uri-kind") 135 + ); 136 + 124 137 const uriEl = /** @type {HTMLInputElement} */ ( 125 138 dialog?.querySelector("#add-uri-uri") 126 139 ); 140 + 127 141 const name = nameEl?.value.trim() ?? ""; 142 + const kind = kindEl?.value ?? "interactive"; 128 143 const uri = uriEl?.value.trim() ?? ""; 129 144 if (!name || !uri) return; 130 - const facet = await facetFromURI({ name, uri }, { fetchHTML: false }); 145 + 146 + const facet = await facetFromURI({ kind, name, uri }, { fetchHTML: false }); 131 147 await saveFacet(facet); 148 + 132 149 /** @type {HTMLDialogElement} */ (dialog).close(); 133 150 }, 134 151 ); ··· 137 154 const nameEl = /** @type {HTMLInputElement} */ ( 138 155 dialog.querySelector("#add-uri-name") 139 156 ); 157 + const kindEl = /** @type {HTMLSelectElement} */ ( 158 + dialog.querySelector("#add-uri-kind") 159 + ); 140 160 const uriEl = /** @type {HTMLInputElement} */ ( 141 161 dialog.querySelector("#add-uri-uri") 142 162 ); 143 163 if (nameEl) nameEl.value = ""; 164 + if (kindEl) kindEl.value = "interactive"; 144 165 if (uriEl) uriEl.value = ""; 145 166 146 167 dialog.showModal();
+1
src/facets/scrobble/index.html
··· 1 + <script type="module" src="./index.inline.js"></script>
+2
src/facets/scrobble/index.inline.js
··· 1 + import foundation from "~/common/facets/foundation.js"; 2 + await foundation.orchestrator.scrobbleAudio();
+5 -4
src/styles/diffuse/page.css
··· 225 225 select { 226 226 appearance: none; 227 227 background: transparent; 228 - border: 2px solid var(--form-color); 229 - border-radius: var(--radius-md); 228 + border: 3px solid var(--form-color); 229 + border-radius: var(--radius-sm); 230 230 color: inherit; 231 231 font-family: inherit; 232 232 font-size: var(--fs-sm); ··· 304 304 border-radius: 9999px; 305 305 display: inline-block; 306 306 font-size: var(--fs-2xs); 307 - font-weight: 500; 308 - padding: 1px var(--space-3xs); 307 + font-weight: 600; 308 + padding: var(--space-3xs); 309 + text-box: trim-both cap alphabetic; 309 310 vertical-align: middle; 310 311 } 311 312