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
chore: some last.fm facet improvements
Steven Vandevelde
20 hours ago
849464f1
910dd8e3
+49
-20
4 changed files
expand all
collapse all
unified
split
src
components
supplement
last.fm
element.js
types.d.ts
facets
scrobble
last.fm
index.html
index.inline.js
+5
src/components/supplement/last.fm/element.js
···
42
42
43
43
#handle = signal(/** @type {string | null} */ (null));
44
44
#sessionKey = signal(/** @type {string | null} */ (null));
45
45
+
#isAuthenticating = signal(false);
45
46
46
47
// STATE
47
48
48
49
handle = this.#handle.get;
49
50
isAuthenticated = computed(() => this.#sessionKey.value !== null);
51
51
+
isAuthenticating = this.#isAuthenticating.get;
50
52
51
53
// LIFECYCLE
52
54
···
92
94
location.pathname + (newSearch ? "?" + newSearch : "") + location.hash,
93
95
);
94
96
97
97
+
this.#isAuthenticating.set(true);
95
98
try {
96
99
const session = await this.#getSession(urlToken);
97
100
this.#setSession(session);
98
101
} catch (err) {
99
102
console.warn("last.fm: failed to exchange token for session", err);
103
103
+
} finally {
104
104
+
this.#isAuthenticating.set(false);
100
105
}
101
106
102
107
return;
+1
src/components/supplement/types.d.ts
···
4
4
5
5
export type ScrobbleElement = DiffuseElement & ScrobbleActions & {
6
6
isAuthenticated: SignalReader<boolean>;
7
7
+
isAuthenticating: SignalReader<boolean>;
7
8
handle: SignalReader<string | null>;
8
9
};
9
10
+35
-19
src/facets/scrobble/last.fm/index.html
···
25
25
</wa-button>
26
26
</div>
27
27
</wa-card>
28
28
-
</main>
29
28
30
30
-
<wa-drawer id="credentials-drawer" label="API Credentials" placement="end">
31
31
-
<div class="drawer-body">
32
32
-
<wa-input id="api-key-input" label="API Key" placeholder="Default"></wa-input>
33
33
-
<wa-input
34
34
-
id="api-secret-input"
35
35
-
label="API Secret"
36
36
-
type="password"
37
37
-
placeholder="Default"
38
38
-
></wa-input>
39
39
-
</div>
40
40
-
<div slot="footer" class="drawer-footer">
41
41
-
<wa-button id="save-creds-btn" variant="brand" appearance="filled">Save</wa-button>
42
42
-
<wa-button id="reset-creds-btn" variant="neutral" appearance="outlined"
43
43
-
>Reset to defaults</wa-button
44
44
-
>
45
45
-
</div>
46
46
-
</wa-drawer>
29
29
+
<wa-drawer id="credentials-drawer" label="API Credentials" placement="end">
30
30
+
<div class="drawer-body">
31
31
+
<wa-input id="api-key-input" label="API Key" placeholder="Default"></wa-input>
32
32
+
<wa-input
33
33
+
id="api-secret-input"
34
34
+
label="API Secret"
35
35
+
type="password"
36
36
+
placeholder="Default"
37
37
+
></wa-input>
38
38
+
</div>
39
39
+
<div slot="footer" class="drawer-footer">
40
40
+
<wa-button id="save-creds-btn" variant="brand" appearance="filled">Save</wa-button>
41
41
+
<wa-button id="reset-creds-btn" variant="neutral" appearance="outlined"
42
42
+
>Reset to defaults</wa-button
43
43
+
>
44
44
+
</div>
45
45
+
</wa-drawer>
46
46
+
</main>
47
47
48
48
<style>
49
49
-
body {
49
49
+
#container {
50
50
display: flex;
51
51
align-items: center;
52
52
justify-content: center;
53
53
min-height: 100dvh;
54
54
margin: 0;
55
55
+
}
56
56
+
57
57
+
main {
58
58
+
opacity: 0;
59
59
+
pointer-events: none;
60
60
+
transition: opacity 750ms;
61
61
+
62
62
+
&.has-loaded {
63
63
+
opacity: 1;
64
64
+
pointer-events: auto;
65
65
+
}
55
66
}
56
67
57
68
wa-card {
···
91
102
</style>
92
103
93
104
<script type="module" src="./index.inline.js"></script>
105
105
+
106
106
+
<script type="module">
107
107
+
await customElements.whenDefined("wa-button");
108
108
+
document.querySelector("main")?.classList.add("has-loaded");
109
109
+
</script>
+8
-1
src/facets/scrobble/last.fm/index.inline.js
···
37
37
38
38
if (!lastFm) {
39
39
lastFm = new LastFmScrobbler();
40
40
-
lastFm.setAttribute("group", GROUP)
40
40
+
lastFm.setAttribute("group", GROUP);
41
41
42
42
const creds = loadCredentials();
43
43
if (creds) {
···
57
57
const stateConnect = /** @type {HTMLElement} */ (
58
58
document.querySelector("#state-connect")
59
59
);
60
60
+
60
61
const stateConnected = /** @type {HTMLElement} */ (
61
62
document.querySelector("#state-connected")
62
63
);
64
64
+
63
65
const handleParagraph = /** @type {HTMLElement} */ (
64
66
document.querySelector("#handle-paragraph")
65
67
);
68
68
+
66
69
const handleText = /** @type {HTMLElement} */ (
67
70
document.querySelector("#handle-text")
68
71
);
···
112
115
113
116
effect(() => {
114
117
const isAuthenticated = lastFm.isAuthenticated();
118
118
+
const isAuthenticating = lastFm.isAuthenticating();
115
119
const handle = lastFm.handle();
116
120
117
121
stateConnect.hidden = isAuthenticated;
···
120
124
handleParagraph.hidden = !handle;
121
125
signOutBtn.hidden = !isAuthenticated;
122
126
if (handle) handleText.textContent = handle;
127
127
+
128
128
+
// @ts-ignore
129
129
+
signInBtn.disabled = isAuthenticating;
123
130
});
124
131
125
132
////////////////////////////////////////////