A music player that connects to your cloud/distributed storage.
at v4 150 lines 4.6 kB view raw
1import { BroadcastableDiffuseElement } from "~/common/element.js"; 2import { signal } from "~/common/signal.js"; 3 4//////////////////////////////////////////// 5// ELEMENT 6//////////////////////////////////////////// 7 8class ScopeEngine extends BroadcastableDiffuseElement { 9 static NAME = "diffuse/engine/scope"; 10 11 // SIGNALS 12 13 #groupBy = signal(/** @type {string | undefined} */ (undefined)); 14 #playlist = signal(/** @type {string | undefined} */ (undefined)); 15 #searchTerm = signal(/** @type {string | undefined} */ (undefined)); 16 #sortBy = signal(/** @type {string[]} */ (["createdAt"])); 17 #sortDirection = signal(/** @type {"asc" | "desc" | undefined} */ ("desc")); 18 19 groupBy = this.#groupBy.get; 20 playlist = this.#playlist.get; 21 searchTerm = this.#searchTerm.get; 22 sortBy = this.#sortBy.get; 23 sortDirection = this.#sortDirection.get; 24 25 // LIFECYCLE 26 27 /** 28 * @override 29 */ 30 connectedCallback() { 31 // Broadcast if needed 32 if (this.hasAttribute("group")) { 33 const actions = this.broadcast(this.identifier, { 34 revertToDefaultSort: { 35 strategy: "replicate", 36 fn: this.revertToDefaultSort, 37 }, 38 setGroupBy: { strategy: "replicate", fn: this.setGroupBy }, 39 setPlaylist: { strategy: "replicate", fn: this.setPlaylist }, 40 setSearchTerm: { strategy: "replicate", fn: this.setSearchTerm }, 41 setSortBy: { strategy: "replicate", fn: this.setSortBy }, 42 setSortDirection: { strategy: "replicate", fn: this.setSortDirection }, 43 }); 44 45 if (actions) { 46 this.revertToDefaultSort = actions.revertToDefaultSort; 47 this.setGroupBy = actions.setGroupBy; 48 this.setPlaylist = actions.setPlaylist; 49 this.setSearchTerm = actions.setSearchTerm; 50 this.setSortBy = actions.setSortBy; 51 this.setSortDirection = actions.setSortDirection; 52 } 53 } 54 55 // Super 56 super.connectedCallback(); 57 58 // Signals 59 const storagePrefix = 60 `${this.constructor.prototype.constructor.NAME}/${this.group}`; 61 62 this.#groupBy.value = localStorage.getItem(`${storagePrefix}/groupBy`) ?? 63 undefined; 64 this.#playlist.value = 65 localStorage.getItem(`${storagePrefix}/playlistId`) ?? undefined; 66 this.#searchTerm.value = 67 localStorage.getItem(`${storagePrefix}/searchTerm`) ?? undefined; 68 this.#sortBy.value = JSON.parse( 69 localStorage.getItem(`${storagePrefix}/sortBy`) ?? `["createdAt"]`, 70 ); 71 this.#sortDirection.value = 72 /** @type {"desc" | "asc"} */ (localStorage.getItem( 73 `${storagePrefix}/sortDirection`, 74 ) ?? "desc"); 75 76 // Effects 77 this.effect(() => { 78 const key = `${storagePrefix}/groupBy`; 79 const val = this.#groupBy.value; 80 81 if (val) localStorage.setItem(key, val); 82 else localStorage.removeItem(key); 83 }); 84 85 this.effect(() => { 86 const key = `${storagePrefix}/playlistId`; 87 const val = this.#playlist.value; 88 89 if (val) localStorage.setItem(key, val); 90 else localStorage.removeItem(key); 91 }); 92 93 this.effect(() => { 94 const key = `${storagePrefix}/searchTerm`; 95 const val = this.#searchTerm.value; 96 97 if (val) localStorage.setItem(key, val); 98 else localStorage.removeItem(key); 99 }); 100 101 this.effect(() => { 102 const key = `${storagePrefix}/sortBy`; 103 const val = this.#sortBy.value; 104 105 if (val.length) localStorage.setItem(key, JSON.stringify(val)); 106 else localStorage.removeItem(key); 107 }); 108 109 this.effect(() => { 110 const key = `${storagePrefix}/sortDirection`; 111 const val = this.#sortDirection.value; 112 113 if (val) localStorage.setItem(key, val); 114 else localStorage.removeItem(key); 115 }); 116 } 117 118 // ACTIONS 119 120 revertToDefaultSort = async () => { 121 this.#sortBy.value = ["createdAt"]; 122 this.#sortDirection.value = "desc"; 123 }; 124 125 /** @param {string | undefined} val */ 126 setGroupBy = async (val) => this.#groupBy.value = val; 127 128 /** @param {string | undefined} val */ 129 setPlaylist = async (val) => this.#playlist.value = val; 130 131 /** @param {string | undefined} val */ 132 setSearchTerm = async (val) => this.#searchTerm.value = val; 133 134 /** @param {string[]} val */ 135 setSortBy = async (val) => this.#sortBy.value = val; 136 137 /** @param {"asc" | "desc" | undefined} val */ 138 setSortDirection = async (val) => this.#sortDirection.value = val; 139} 140 141export default ScopeEngine; 142 143//////////////////////////////////////////// 144// REGISTER 145//////////////////////////////////////////// 146 147export const CLASS = ScopeEngine; 148export const NAME = "de-scope"; 149 150customElements.define(NAME, CLASS);