tangled
alpha
login
or
join now
tokono.ma
/
diffuse
5
fork
atom
A music player that connects to your cloud/distributed storage.
5
fork
atom
overview
issues
4
pulls
pipelines
feat: output configurator
Steven Vandevelde
2 months ago
49d7032c
3f753956
+101
-12
4 changed files
expand all
collapse all
unified
split
src
components
configurator
output
element.js
output
polymorphic
indexed-db
constants.js
themes
webamp
index.js
index.vto
+86
-4
src/components/configurator/output/element.js
···
2
2
import { computed, signal } from "@common/signal.js";
3
3
4
4
/**
5
5
-
* @import {ProxiedActions} from "@common/worker.d.ts"
6
5
* @import {Track} from "@definitions/types.d.ts"
7
6
* @import {OutputManager, OutputElement} from "@components/output/types.d.ts"
8
7
*/
9
8
9
9
+
/**
10
10
+
* @typedef {OutputElement<Track[]>} Output
11
11
+
*/
12
12
+
13
13
+
const STORAGE_PREFIX = "diffuse/configurator/output";
14
14
+
10
15
////////////////////////////////////////////
11
16
// ELEMENT
12
17
////////////////////////////////////////////
···
16
21
*/
17
22
class OutputConfigurator extends DiffuseElement {
18
23
static NAME = "diffuse/configurator/output";
19
19
-
static WORKER_URL = "components/configurator/output/worker.js";
20
24
21
25
constructor() {
22
26
super();
···
25
29
const manager = {
26
30
tracks: {
27
31
collection: computed(() => {
32
32
+
const out = this.#selectedOutput.value;
33
33
+
if (out) return out.tracks.collection();
28
34
return this.#memory.tracks.value;
29
35
}),
30
30
-
reload: async () => {},
36
36
+
reload: () => {
37
37
+
const out = this.#selectedOutput.value;
38
38
+
if (out) return out.tracks.reload();
39
39
+
return Promise.resolve();
40
40
+
},
31
41
save: async (newTracks) => {
42
42
+
const out = this.#selectedOutput.value;
43
43
+
if (out) return await out.tracks.save(newTracks);
32
44
this.#memory.tracks.value = newTracks;
33
45
},
34
34
-
state: () => "loaded",
46
46
+
state: computed(() => {
47
47
+
const out = this.#selectedOutput.value;
48
48
+
if (out) return out.tracks.state();
49
49
+
return out === undefined ? "loading" : "loaded";
50
50
+
}),
35
51
},
36
52
};
37
53
···
45
61
tracks: signal(/** @type {Track[]} */ ([])),
46
62
};
47
63
64
64
+
#selectedOutput = signal(
65
65
+
/** @type {Output | null | undefined} */ (undefined),
66
66
+
);
67
67
+
48
68
// LIFECYCLE
49
69
50
70
/**
···
52
72
*/
53
73
async connectedCallback() {
54
74
super.connectedCallback();
75
75
+
this.#selectedOutput.value = await this.#findSelectedOutput();
76
76
+
77
77
+
this.effect(() => {
78
78
+
console.log("selectedOutput changed", this.#selectedOutput.value);
79
79
+
});
80
80
+
81
81
+
this.effect(() => {
82
82
+
console.log("collection changed", this.tracks.collection());
83
83
+
});
84
84
+
85
85
+
this.effect(() => {
86
86
+
console.log("state changed", this.tracks.state());
87
87
+
});
88
88
+
}
89
89
+
90
90
+
// MISC
91
91
+
92
92
+
async #findSelectedOutput() {
93
93
+
const id = localStorage.getItem(`${STORAGE_PREFIX}/selected/id`);
94
94
+
const el = id ? this.root().querySelector(`#${id}`) : null;
95
95
+
96
96
+
if (!el) return null;
97
97
+
98
98
+
await customElements.whenDefined(el.localName);
99
99
+
100
100
+
if (
101
101
+
"nameWithGroup" in el === false ||
102
102
+
"tracks" in el === false
103
103
+
) {
104
104
+
return null;
105
105
+
}
106
106
+
107
107
+
return /** @type {Output} */ (/** @type {unknown} */ (el));
108
108
+
}
109
109
+
110
110
+
/**
111
111
+
* @override
112
112
+
*/
113
113
+
dependencies() {
114
114
+
return Object.fromEntries(
115
115
+
Array.from(this.children).flatMap((element) => {
116
116
+
if (element.hasAttribute("id") === false) {
117
117
+
console.warn(
118
118
+
"Missing `id` for output configurator child element with `localName` '" +
119
119
+
element.localName + "'",
120
120
+
);
121
121
+
return [];
122
122
+
}
123
123
+
124
124
+
const d = /** @type {DiffuseElement} */ (element);
125
125
+
return [[d.id, d]];
126
126
+
}),
127
127
+
);
128
128
+
}
129
129
+
130
130
+
// ADDITIONAL ACTIONS
131
131
+
132
132
+
/**
133
133
+
* @param {string} id
134
134
+
*/
135
135
+
selectOutput(id) {
136
136
+
localStorage.setItem(`${STORAGE_PREFIX}/selected/id`, id);
55
137
}
56
138
}
57
139
+1
-1
src/components/output/polymorphic/indexed-db/constants.js
···
1
1
-
export const IDB_PREFIX = "@components/output/polymorphic/indexed-db";
1
1
+
export const IDB_PREFIX = "diffuse/output/polymorphic/indexed-db";
+4
-2
src/themes/webamp/index.js
···
1
1
+
import "@components/configurator/output/element.js";
2
2
+
import "@components/input/opensubsonic/element.js";
3
3
+
import "@components/input/s3/element.js";
1
4
import "@components/orchestrator/process-tracks/element.js";
2
5
import "@components/orchestrator/queue-tracks/element.js";
3
3
-
import "@components/input/opensubsonic/element.js";
4
4
-
import "@components/input/s3/element.js";
5
6
import "@components/output/polymorphic/indexed-db/element.js";
6
7
import "@components/processor/metadata/element.js";
7
8
import "@components/transformer/output/string/json/element.js";
···
22
23
const queue = component(Queue);
23
24
24
25
globalThis.queue = queue;
26
26
+
globalThis.output = document.querySelector("#output");
25
27
26
28
////////////////////////////////////////////
27
29
// 📡
+10
-5
src/themes/webamp/index.vto
···
77
77
-->
78
78
<de-queue></de-queue>
79
79
80
80
-
<!-- Inputs, Output & Processors -->
81
81
-
<dop-indexed-db></dop-indexed-db>
80
80
+
<!-- Processors -->
82
81
<dp-metadata></dp-metadata>
83
82
83
83
+
<!-- Input -->
84
84
<dc-input id="input">
85
85
<di-opensubsonic></di-opensubsonic>
86
86
<di-s3></di-s3>
87
87
</dc-input>
88
88
89
89
-
<!-- Transformers -->
90
90
-
<dtor-default id="output" output-selector="dtos-json"></dtor-default>
91
91
-
<dtos-json output-selector="dop-indexed-db"></dtos-json>
89
89
+
<!-- Output -->
90
90
+
<dop-indexed-db id="idb-json-output" key="json"></dop-indexed-db>
91
91
+
92
92
+
<dc-output>
93
93
+
<dtos-json id="idb-json" output-selector="#idb-json-output"></dtos-json>
94
94
+
</dc-output>
95
95
+
96
96
+
<dtor-default id="output" output-selector="dc-output"></dtor-default>
92
97
93
98
<!-- Orchestrators -->
94
99
<do-process-tracks