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

feat: relative urls pls

+53 -31
+3 -3
src/_includes/layouts/diffuse.vto
··· 13 13 <title>{{title}}</title> 14 14 15 15 <!-- Favicons & Mobile --> 16 - <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" /> 17 - <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" /> 18 - <link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" /> 16 + <link rel="apple-touch-icon" sizes="180x180" href="apple-touch-icon.png" /> 17 + <link rel="icon" type="image/png" sizes="32x32" href="favicon-32x32.png" /> 18 + <link rel="icon" type="image/png" sizes="16x16" href="favicon-16x16.png" /> 19 19 <!-- TODO: <link rel="manifest" href="site.webmanifest" />--> 20 20 <link rel="mask-icon" href="safari-pinned-tab.svg" color="#8a90a9" /> 21 21 <meta name="msapplication-TileColor" content="#8a90a9" />
+3 -1
src/components/input/opensubsonic/element.js
··· 49 49 */ 50 50 worker(group) { 51 51 const name = `diffuse/input/opensubsonic/${group || crypto.randomUUID()}`; 52 - const url = "/components/input/opensubsonic/worker.js"; 52 + const url = import.meta.resolve( 53 + "./components/input/opensubsonic/worker.js", 54 + ); 53 55 54 56 return new Worker(url, { name, type: "module" }); 55 57 }
+12 -7
src/components/orchestrator/process-tracks/element.js
··· 25 25 26 26 // Setup worker 27 27 const name = `diffuse/orchestrator/process-tracks/${this.group}`; 28 - const url = "/components/orchestrator/process-tracks/worker.js"; 28 + const url = import.meta.resolve( 29 + "./components/orchestrator/process-tracks/worker.js", 30 + ); 31 + 29 32 const worker = new Worker(url, { name, type: "module" }); 30 33 31 34 /** @type {InputElement} */ ··· 38 41 this.metadataProcessor = query(this, "metadata-processor-selector"); 39 42 40 43 // Create new workers specially for track processing 41 - this.#external = { 44 + this.#external = Promise.all([ 45 + customElements.whenDefined(this.input.localName), 46 + customElements.whenDefined(this.metadataProcessor.localName), 47 + ]).then(() => ({ 42 48 input: portProvider(this.input.worker()), 43 49 metadataProcessor: portProvider(this.metadataProcessor.worker()), 44 - }; 50 + })); 45 51 46 52 // Worker proxy 47 53 this.#process = use("process", worker, { ··· 81 87 // ACTIONS 82 88 83 89 async process() { 84 - await customElements.whenDefined(this.input.localName); 85 - await customElements.whenDefined(this.metadataProcessor.localName); 90 + const ext = await this.#external; 86 91 87 92 // Start 88 93 this.#isProcessing.value = true; ··· 92 97 93 98 // Establish channel between external workers and our processing worker 94 99 const ports = { 95 - input: this.#external.input(), 96 - metadataProcessor: this.#external.metadataProcessor(), 100 + input: ext.input(), 101 + metadataProcessor: ext.metadataProcessor(), 97 102 }; 98 103 99 104 // Send everything to worker
+4 -1
src/components/output/polymorphic/indexed-db/element.js
··· 19 19 20 20 // Setup worker 21 21 const name = `diffuse/output/polymorphic/indexed-db/${this.group}`; 22 - const url = "/components/output/polymorphic/indexed-db/worker.js"; 22 + const url = import.meta.resolve( 23 + "./components/output/polymorphic/indexed-db/worker.js", 24 + ); 25 + 23 26 const worker = new Worker(url, { name, type: "module" }); 24 27 25 28 // Manager
+4 -1
src/components/processor/metadata/element.js
··· 34 34 */ 35 35 worker(group) { 36 36 const name = `diffuse/processor/metadata/${group || crypto.randomUUID()}`; 37 - const url = "/components/processor/metadata/worker.js"; 37 + const url = import.meta.resolve( 38 + "./components/processor/metadata/worker.js", 39 + ); 40 + 38 41 return new Worker(url, { name, type: "module" }); 39 42 } 40 43 }
+3 -1
src/components/processor/search/element.js
··· 18 18 19 19 // Setup worker 20 20 const name = `diffuse/processor/search/${this.group}`; 21 - const url = "/components/processor/search/worker.js"; 21 + const url = import.meta.resolve( 22 + "./components/processor/search/worker.js", 23 + ); 22 24 23 25 let port; 24 26
+10 -3
src/components/transformer/output/string/json/element.js
··· 1 1 import { DiffuseElement, query } from "@common/element.js"; 2 - import { computed } from "@common/signal.js"; 2 + import { computed, signal } from "@common/signal.js"; 3 3 4 4 /** 5 5 * @import { OutputElement, OutputManager } from "../../../../output/types.d.ts" ··· 13 13 /** @type {OutputElement<string>} */ 14 14 this.output = query(this, "output-selector"); 15 15 16 + // whenDefined signal 17 + const $defined = signal(false); 18 + 19 + customElements.whenDefined(this.output.localName).then( 20 + () => $defined.value = true, 21 + ); 22 + 16 23 /** @type {OutputManager<Track[]>} */ 17 24 const manager = { 18 25 tracks: { 19 26 collection: computed(() => { 20 - const json = this.output.tracks?.collection() || []; 27 + const json = $defined.value ? this.output.tracks?.collection() : []; 21 28 22 29 // In addition to the above, Some polymorphic outputs 23 30 // use an empty array as the default return value. ··· 40 47 await customElements.whenDefined(this.output.localName); 41 48 await this.output.tracks.save(json); 42 49 }, 43 - state: () => this.output.tracks.state(), 50 + state: computed(() => this.output.tracks.state()), 44 51 }, 45 52 }; 46 53
+1 -1
src/favicons/browserconfig.xml
··· 2 2 <browserconfig> 3 3 <msapplication> 4 4 <tile> 5 - <square150x150logo src="/mstile-150x150.png"/> 5 + <square150x150logo src="mstile-150x150.png"/> 6 6 <TileColor>#8a90a9</TileColor> 7 7 </tile> 8 8 </msapplication>
+2 -2
src/index.vto
··· 119 119 <svg viewBox="0 0 902 134" width="160"> 120 120 <title>Diffuse</title> 121 121 <use 122 - xlink:href="/images/diffuse-current.svg#diffuse" 123 - href="/images/diffuse-current.svg#diffuse"></use> 122 + xlink:href="images/diffuse-current.svg#diffuse" 123 + href="images/diffuse-current.svg#diffuse"></use> 124 124 </svg> 125 125 </h1> 126 126 <p>
+1 -1
src/themes/webamp/browser/element.js
··· 80 80 const tracks = this.output.tracks?.collection() || []; 81 81 82 82 return html` 83 - <link rel="stylesheet" href="/styles/vendor/98.css" /> 83 + <link rel="stylesheet" href="../../styles/vendor/98.css" /> 84 84 85 85 <style> 86 86 @import "./98-vars.css";
+2 -2
src/themes/webamp/index.css
··· 4 4 5 5 @font-face { 6 6 font-family: "Pixelated MS Sans Serif"; 7 - src: url("/fonts/ms_sans_serif.woff2") format("woff2"); 7 + src: url("../../fonts/ms_sans_serif.woff2") format("woff2"); 8 8 font-weight: normal; 9 9 font-style: normal; 10 10 } 11 11 12 12 @font-face { 13 13 font-family: "Pixelated MS Sans Serif"; 14 - src: url("/fonts/ms_sans_serif_bold.woff2") format("woff2"); 14 + src: url("../../fonts/ms_sans_serif_bold.woff2") format("woff2"); 15 15 font-weight: 700; 16 16 font-style: normal; 17 17 }
+7 -7
src/themes/webamp/index.vto
··· 18 18 <dtw-window-manager> 19 19 <!-- INPUT --> 20 20 <dtw-window id="input-window"> 21 - <span slot="title-icon"><img src="/images/icons/windows_98/cd_audio_cd_a-0.png" height="14" /></span> 21 + <span slot="title-icon"><img src="../../images/icons/windows_98/cd_audio_cd_a-0.png" height="14" /></span> 22 22 <span slot="title">Manage audio inputs</span> 23 23 <p>👀</p> 24 24 </dtw-window> 25 25 26 26 <!-- OUTPUT --> 27 27 <dtw-window id="output-window"> 28 - <span slot="title-icon"><img src="/images/icons/windows_98/computer_user_pencil-0.png" height="14" /></span> 28 + <span slot="title-icon"><img src="../../images/icons/windows_98/computer_user_pencil-0.png" height="14" /></span> 29 29 <span slot="title">Manage user data</span> 30 30 <p>👀</p> 31 31 </dtw-window> 32 32 33 33 <!-- BROWSER --> 34 34 <dtw-window id="browser-window" open> 35 - <span slot="title-icon"><img src="/images/icons/windows_98/directory_explorer-4.png" height="14" /></span> 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 38 input-selector="di-opensubsonic" ··· 45 45 <section class="desktop"> 46 46 <!-- WINAMP --> 47 47 <a class="button desktop__item" id="desktop-winamp"> 48 - <img src="/images/icons/windows_98/winamp2-32x32.png" height="32" /> 48 + <img src="../../images/icons/windows_98/winamp2-32x32.png" height="32" /> 49 49 <label>Winamp</label> 50 50 </a> 51 51 52 52 <!-- INPUT --> 53 53 <a class="button desktop__item"> 54 - <img src="/images/icons/windows_98/cd_audio_cd_a-4.png" height="32" /> 54 + <img src="../../images/icons/windows_98/cd_audio_cd_a-4.png" height="32" /> 55 55 <label for="input-window">Manage audio inputs</label> 56 56 </a> 57 57 58 58 <!-- OUTPUT --> 59 59 <a class="button desktop__item"> 60 - <img src="/images/icons/windows_98/computer_user_pencil-0.png" height="32" /> 60 + <img src="../../images/icons/windows_98/computer_user_pencil-0.png" height="32" /> 61 61 <label for="output-window">Manage user data</label> 62 62 </a> 63 63 64 64 <!-- BROWSE --> 65 65 <a class="button desktop__item"> 66 - <img src="/images/icons/windows_98/directory_explorer-5.png" height="32" /> 66 + <img src="../../images/icons/windows_98/directory_explorer-5.png" height="32" /> 67 67 <label for="browser-window">Browse collection</label> 68 68 </a> 69 69 </section>
+1 -1
src/themes/webamp/window/element.js
··· 35 35 */ 36 36 render({ html }) { 37 37 return html` 38 - <link rel="stylesheet" href="/styles/vendor/98.css" /> 38 + <link rel="stylesheet" href="../../styles/vendor/98.css" /> 39 39 40 40 <style> 41 41 dialog {