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: ephemeral tracks + output refiner transformer

+63 -3
+54
src/components/transformer/output/refiner/default/element.js
··· 1 + import { DiffuseElement, query } from "@common/element.js"; 2 + import { computed, signal } from "@common/signal.js"; 3 + 4 + /** 5 + * @import { OutputElement, OutputManager } from "../../../../output/types.d.ts" 6 + * @import { Track } from "@common/types.d.ts" 7 + */ 8 + 9 + class DefaultOutputRefinerTransformer extends DiffuseElement { 10 + constructor() { 11 + super(); 12 + 13 + /** @type {OutputElement<Track[]>} */ 14 + this.output = query(this, "output-selector"); 15 + 16 + // whenDefined signal 17 + const $defined = signal(false); 18 + 19 + customElements.whenDefined(this.output.localName).then( 20 + () => $defined.value = true, 21 + ); 22 + 23 + /** @type {OutputManager<Track[]>} */ 24 + const manager = { 25 + tracks: { 26 + collection: computed(() => { 27 + return $defined.value ? this.output.tracks?.collection() : []; 28 + }), 29 + reload: () => this.output.tracks.reload(), 30 + save: async (newTracks) => { 31 + const filtered = newTracks.filter((t) => !t.ephemeral); 32 + 33 + await customElements.whenDefined(this.output.localName); 34 + await this.output.tracks.save(filtered); 35 + }, 36 + state: computed(() => this.output.tracks.state()), 37 + }, 38 + }; 39 + 40 + // Assign manager properties to class 41 + this.tracks = manager.tracks; 42 + } 43 + } 44 + 45 + export default DefaultOutputRefinerTransformer; 46 + 47 + //////////////////////////////////////////// 48 + // REGISTER 49 + //////////////////////////////////////////// 50 + 51 + export const CLASS = DefaultOutputRefinerTransformer; 52 + export const NAME = "dtor-default"; 53 + 54 + customElements.define(NAME, CLASS);
+1
src/definitions/output/tracks.json
··· 10 10 "properties": { 11 11 "id": { "type": "string" }, 12 12 "createdAt": { "type": "string", "format": "datetime" }, 13 + "ephemeral": { "type": "boolean" }, 13 14 "kind": { 14 15 "type": "string", 15 16 "enum": ["audiobook", "miscellaneous", "music", "placeholder", "podcast"]
+3
src/index.vto
··· 91 91 - title: "Output / Bytes / JSON" 92 92 desc: "Raw data schema output ⇄ JSON Uint8Array." 93 93 todo: true 94 + - title: "Output / Refiner / Default" 95 + desc: "The task of a refiner transformer is to remove the output state that is not meant to be saved to storage. For example, ephemeral tracks; this transformer will keep them in memory, but they will not be present in the output. **Ideally this is part of every theme, but you may swap it out with another transformer that might provide better defaults.**" 96 + url: "components/transformer/output/refiner/default/element.js" 94 97 - title: "Output / String / JSON" 95 98 desc: "Raw data schema output ⇄ JSON UTF8 string." 96 99 url: "components/transformer/output/string/json/element.js"
+1
src/themes/webamp/index.js
··· 3 3 import "@components/output/polymorphic/indexed-db/element.js"; 4 4 import "@components/processor/metadata/element.js"; 5 5 import "@components/transformer/output/string/json/element.js"; 6 + import "@components/transformer/output/refiner/default/element.js"; 6 7 7 8 import * as Input from "@components/input/opensubsonic/element.js"; 8 9 import * as Queue from "@components/engine/queue/element.js";
+4 -3
src/themes/webamp/index.vto
··· 83 83 <dp-metadata></dp-metadata> 84 84 85 85 <!-- Transformers --> 86 - <dtos-json id="output" output-selector="dop-indexed-db"></dtos-json> 86 + <dtor-default id="output" output-selector="dtos-json"></dtor-default> 87 + <dtos-json output-selector="dop-indexed-db"></dtos-json> 87 88 88 89 <!-- Orchestrators --> 89 - <!--<do-process-tracks 90 + <do-process-tracks 90 91 input-selector="di-opensubsonic" 91 92 metadata-processor-selector="dp-metadata" 92 93 output-selector="#output" 93 - ></do-process-tracks>--> 94 + ></do-process-tracks> 94 95 95 96 <do-queue-tracks 96 97 input-selector="di-opensubsonic"