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

Configure Feed

Select the types of activity you want to include in your feed.

feat: s3 element

+118 -6
+73
src/components/input/s3/element.js
··· 1 + import { DiffuseElement } from "@common/element.js"; 2 + import { portProvider, proxyProvider } from "@common/worker.js"; 3 + 4 + /** 5 + * @import {InputActions} from "@common/types.d.ts" 6 + * @import {PortProviderMethod, ProxiedActions, ProxyProvider, ProxyProviderMethod} from "@common/worker.d.ts" 7 + */ 8 + 9 + //////////////////////////////////////////// 10 + // ELEMENT 11 + //////////////////////////////////////////// 12 + 13 + /** 14 + * @implements {ProxiedActions<InputActions>} 15 + * @implements {PortProviderMethod} 16 + * @implements {ProxyProviderMethod<InputActions>} 17 + */ 18 + class S3Input extends DiffuseElement { 19 + constructor() { 20 + super(); 21 + 22 + // Setup worker 23 + const worker = this.worker(this.group); 24 + 25 + /** @type {ProxyProvider<InputActions & { demo: () => Promise<void> }>} */ 26 + this.proxy = proxyProvider([ 27 + "consult", 28 + "contextualize", 29 + "groupConsult", 30 + "list", 31 + "resolve", 32 + 33 + "demo", 34 + ]); 35 + 36 + // Worker proxy 37 + const w = this.proxy(worker); 38 + 39 + this.consult = w.consult; 40 + this.contextualize = w.contextualize; 41 + this.groupConsult = w.groupConsult; 42 + this.list = w.list; 43 + this.resolve = w.resolve; 44 + 45 + this.demo = w.demo; 46 + 47 + // Provide a channel to the worker 48 + this.port = portProvider(worker); 49 + } 50 + 51 + /** 52 + * @param {string} [group] 53 + */ 54 + worker(group) { 55 + const name = `diffuse/input/s3/${group || crypto.randomUUID()}`; 56 + const url = import.meta.resolve( 57 + "./components/input/s3/worker.js", 58 + ); 59 + 60 + return new Worker(url, { name, type: "module" }); 61 + } 62 + } 63 + 64 + export default S3Input; 65 + 66 + //////////////////////////////////////////// 67 + // REGISTER 68 + //////////////////////////////////////////// 69 + 70 + export const CLASS = S3Input; 71 + export const NAME = "di-s3"; 72 + 73 + customElements.define(NAME, CLASS);
+40 -1
src/components/input/s3/worker.js
··· 10 10 parseURI, 11 11 } from "./common.js"; 12 12 import { SCHEME } from "./constants.js"; 13 + import { announce, define, ostiary } from "@common/worker.js"; 14 + import { effect, signal } from "@common/signal.js"; 15 + 16 + import { saveBuckets } from "./common.js"; 13 17 14 18 /** 15 19 * @import { InputActions as Actions, Track } from "@common/types.d.ts"; 16 20 * @import { Bucket } from "./types.d.ts" 17 21 */ 22 + 23 + //////////////////////////////////////////// 24 + // STATE 25 + //////////////////////////////////////////// 26 + 27 + const $buckets = signal(/** @type {Record<string, Bucket>} */ ({})); 28 + 29 + effect(() => { 30 + saveBuckets($buckets.value); 31 + }); 18 32 19 33 //////////////////////////////////////////// 20 34 // ACTIONS ··· 39 53 * @type {Actions['contextualize']} 40 54 */ 41 55 export async function contextualize(tracks) { 42 - bucketsFromTracks(tracks); 56 + const buckets = bucketsFromTracks(tracks); 57 + $buckets.value = buckets; 43 58 } 44 59 45 60 /** ··· 160 175 return { expiresAt: expiresAtSeconds, url }; 161 176 } 162 177 178 + //////////////////////////////////////////// 163 179 // ADDITIONAL ACTIONS 180 + //////////////////////////////////////////// 164 181 165 182 export function demo() { 166 183 // Credentials are read-only, no worries. ··· 190 207 track, 191 208 }; 192 209 } 210 + 211 + //////////////////////////////////////////// 212 + // ⚡️ 213 + //////////////////////////////////////////// 214 + 215 + ostiary((port) => { 216 + // Setup RPC 217 + 218 + define("buckets", $buckets.get, port); 219 + 220 + define("consult", consult, port); 221 + define("contextualize", contextualize, port); 222 + define("groupConsult", groupConsult, port); 223 + define("list", list, port); 224 + define("resolve", resolve, port); 225 + 226 + define("demo", demo, port); 227 + 228 + // Communicate state 229 + 230 + effect(() => announce("buckets", $buckets.value, port)); 231 + });
+1 -1
src/themes/webamp/index.js
··· 5 5 import "@components/transformer/output/string/json/element.js"; 6 6 import "@components/transformer/output/refiner/default/element.js"; 7 7 8 - import * as Input from "@components/input/opensubsonic/element.js"; 8 + import * as Input from "@components/input/s3/element.js"; 9 9 import * as Queue from "@components/engine/queue/element.js"; 10 10 11 11 import { component } from "@common/element.js";
+4 -4
src/themes/webamp/index.vto
··· 35 35 <span slot="title-icon"><img src="../../images/icons/windows_98/directory_explorer-4.png" height="14" /></span> 36 36 <span slot="title">Browse collection</span> 37 37 <dtw-browser 38 - input-selector="di-opensubsonic" 38 + input-selector="#input" 39 39 output-selector="#output" 40 40 queue-selector="de-queue" 41 41 ></dtw-browser> ··· 78 78 <de-queue></de-queue> 79 79 80 80 <!-- Inputs, Output & Processors --> 81 - <di-opensubsonic></di-opensubsonic> 81 + <di-opensubsonic id="input"></di-opensubsonic> 82 82 <dop-indexed-db></dop-indexed-db> 83 83 <dp-metadata></dp-metadata> 84 84 ··· 88 88 89 89 <!-- Orchestrators --> 90 90 <do-process-tracks 91 - input-selector="di-opensubsonic" 91 + input-selector="#input" 92 92 metadata-processor-selector="dp-metadata" 93 93 output-selector="#output" 94 94 ></do-process-tracks> 95 95 96 96 <do-queue-tracks 97 - input-selector="di-opensubsonic" 97 + input-selector="#input" 98 98 output-selector="#output" 99 99 queue-engine-selector="de-queue" 100 100 ></do-queue-tracks>