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.

chore: no dom interactions in constructors (transformers)

+64 -26
+32 -13
src/components/transformer/output/refiner/default/element.js
··· 10 10 constructor() { 11 11 super(); 12 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 13 /** @type {OutputManager<Track[]>} */ 24 14 const manager = { 25 15 tracks: { 26 16 collection: computed(() => { 27 - return $defined.value ? this.output.tracks?.collection() : []; 17 + return this.#defined.value 18 + ? this.output?.tracks?.collection() ?? [] 19 + : []; 28 20 }), 29 - reload: () => this.output.tracks.reload(), 21 + reload: () => this.output?.tracks?.reload() ?? Promise.resolve(), 30 22 save: async (newTracks) => { 31 23 const filtered = newTracks.filter((t) => !t.ephemeral); 24 + 25 + if (!this.output) return; 32 26 33 27 await customElements.whenDefined(this.output.localName); 34 28 await this.output.tracks.save(filtered); 35 29 }, 36 - state: computed(() => this.output.tracks.state()), 30 + state: computed(() => this.output?.tracks.state() ?? "loading"), 37 31 }, 38 32 }; 39 33 40 34 // Assign manager properties to class 41 35 this.tracks = manager.tracks; 36 + } 37 + 38 + /** @type {OutputElement<Track[]> | undefined} */ 39 + output = undefined; 40 + 41 + // SIGNALS 42 + 43 + #defined = signal(false); 44 + 45 + // LIFECYCLE 46 + 47 + /** 48 + * @override 49 + */ 50 + connectedCallback() { 51 + super.connectedCallback(); 52 + 53 + /** @type {OutputElement<Track[]>} */ 54 + const output = query(this, "output-selector"); 55 + this.output = output; 56 + 57 + // When defined 58 + customElements.whenDefined(this.output.localName).then( 59 + () => this.#defined.value = true, 60 + ); 42 61 } 43 62 } 44 63
+32 -13
src/components/transformer/output/string/json/element.js
··· 10 10 constructor() { 11 11 super(); 12 12 13 - /** @type {OutputElement<string>} */ 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 13 /** @type {OutputManager<Track[]>} */ 24 14 const manager = { 25 15 tracks: { 26 16 collection: computed(() => { 27 - const json = $defined.value ? this.output.tracks?.collection() : []; 17 + const json = this.#defined.value 18 + ? this.output?.tracks?.collection() ?? [] 19 + : []; 28 20 29 21 // In addition to the above, Some polymorphic outputs 30 22 // use an empty array as the default return value. ··· 40 32 return []; 41 33 } 42 34 }), 43 - reload: () => this.output.tracks.reload(), 35 + reload: () => this.output?.tracks?.reload() ?? Promise.resolve(), 44 36 save: async (newTracks) => { 45 37 const json = JSON.stringify(newTracks); 38 + 39 + if (!this.output) return; 46 40 47 41 await customElements.whenDefined(this.output.localName); 48 42 await this.output.tracks.save(json); 49 43 }, 50 - state: computed(() => this.output.tracks.state()), 44 + state: computed(() => this.output?.tracks?.state() ?? "loading"), 51 45 }, 52 46 }; 53 47 54 48 // Assign manager properties to class 55 49 this.tracks = manager.tracks; 50 + } 51 + 52 + /** @type {OutputElement<string> | undefined} */ 53 + output = undefined; 54 + 55 + // SIGNALS 56 + 57 + #defined = signal(false); 58 + 59 + // LIFECYCLE 60 + 61 + /** 62 + * @override 63 + */ 64 + connectedCallback() { 65 + super.connectedCallback(); 66 + 67 + /** @type {OutputElement<string>} */ 68 + const output = query(this, "output-selector"); 69 + this.output = output; 70 + 71 + // When defined 72 + customElements.whenDefined(this.output.localName).then( 73 + () => this.#defined.value = true, 74 + ); 56 75 } 57 76 } 58 77