@flow-industries/id 0.23.3 → 0.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -74,17 +74,26 @@ export function createProfileButton(options) {
|
|
|
74
74
|
fallback.rel = "noopener noreferrer";
|
|
75
75
|
fallback.textContent = "Open Flow ID";
|
|
76
76
|
fallback.hidden = true;
|
|
77
|
-
let
|
|
77
|
+
let lastUser = null;
|
|
78
|
+
let imageUrl = null;
|
|
79
|
+
avatar.textContent = "F";
|
|
78
80
|
let profileRequest = null;
|
|
79
|
-
function update() {
|
|
81
|
+
function update(refresh = false) {
|
|
80
82
|
const user = flow.getState().user;
|
|
81
83
|
name.textContent = user?.username ?? "Flow ID";
|
|
82
84
|
button.setAttribute("aria-label", `Open ${user?.username ?? "your"} Flow ID account in a new tab`);
|
|
83
|
-
|
|
85
|
+
const identityChanged = user?.id !== lastUser?.id ||
|
|
86
|
+
user?.username !== lastUser?.username ||
|
|
87
|
+
user?.isGuest !== lastUser?.isGuest;
|
|
88
|
+
if (identityChanged) {
|
|
89
|
+
profileRequest?.abort();
|
|
90
|
+
profileRequest = null;
|
|
91
|
+
imageUrl = null;
|
|
92
|
+
avatar.textContent = user?.username.slice(0, 1).toUpperCase() ?? "F";
|
|
93
|
+
lastUser = user;
|
|
94
|
+
}
|
|
95
|
+
else if (!refresh || profileRequest)
|
|
84
96
|
return;
|
|
85
|
-
lastUsername = user?.username;
|
|
86
|
-
profileRequest?.abort();
|
|
87
|
-
avatar.textContent = user?.username.slice(0, 1).toUpperCase() ?? "F";
|
|
88
97
|
if (!user || user.isGuest)
|
|
89
98
|
return;
|
|
90
99
|
const controller = new AbortController();
|
|
@@ -98,7 +107,14 @@ export function createProfileButton(options) {
|
|
|
98
107
|
return;
|
|
99
108
|
// SAFETY: Flow ID owns the public profile endpoint and its optional image field.
|
|
100
109
|
const profile = (await response.json());
|
|
101
|
-
if (controller.signal.aborted
|
|
110
|
+
if (controller.signal.aborted)
|
|
111
|
+
return;
|
|
112
|
+
if (profile.image === null) {
|
|
113
|
+
imageUrl = null;
|
|
114
|
+
avatar.textContent = user.username.slice(0, 1).toUpperCase();
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
if (!profile.image || profile.image === imageUrl)
|
|
102
118
|
return;
|
|
103
119
|
const image = document.createElement("img");
|
|
104
120
|
image.src = profile.image;
|
|
@@ -108,9 +124,17 @@ export function createProfileButton(options) {
|
|
|
108
124
|
height: "100%",
|
|
109
125
|
objectFit: "cover",
|
|
110
126
|
});
|
|
127
|
+
await image.decode();
|
|
128
|
+
if (controller.signal.aborted)
|
|
129
|
+
return;
|
|
130
|
+
imageUrl = profile.image;
|
|
111
131
|
avatar.replaceChildren(image);
|
|
112
132
|
})
|
|
113
|
-
.catch(() => { })
|
|
133
|
+
.catch(() => { })
|
|
134
|
+
.finally(() => {
|
|
135
|
+
if (profileRequest === controller)
|
|
136
|
+
profileRequest = null;
|
|
137
|
+
});
|
|
114
138
|
}
|
|
115
139
|
button.addEventListener("click", () => {
|
|
116
140
|
const opened = flow.openAccount();
|
|
@@ -120,8 +144,7 @@ export function createProfileButton(options) {
|
|
|
120
144
|
fallback.hidden = opened;
|
|
121
145
|
});
|
|
122
146
|
function refresh() {
|
|
123
|
-
|
|
124
|
-
update();
|
|
147
|
+
update(true);
|
|
125
148
|
}
|
|
126
149
|
window.addEventListener("focus", refresh);
|
|
127
150
|
function setTheme(theme) {
|
|
@@ -130,7 +153,7 @@ export function createProfileButton(options) {
|
|
|
130
153
|
setTheme(options.theme ?? "light dark");
|
|
131
154
|
container.append(button, notice, fallback);
|
|
132
155
|
update();
|
|
133
|
-
const unsubscribe = flow.subscribe(update);
|
|
156
|
+
const unsubscribe = flow.subscribe(() => update());
|
|
134
157
|
return {
|
|
135
158
|
setTheme,
|
|
136
159
|
destroy() {
|
|
@@ -81,12 +81,13 @@ export type CosmeticMaterial = (typeof COSMETIC_MATERIALS)[number];
|
|
|
81
81
|
* that shrank whenever a slot emptied would churn the contract every time
|
|
82
82
|
* content lands.
|
|
83
83
|
*/
|
|
84
|
-
export type CosmeticSlot = "hat" | "face" | "top" | "bottom" | "feet";
|
|
84
|
+
export type CosmeticSlot = "hat" | "hair" | "face" | "top" | "bottom" | "feet";
|
|
85
85
|
/** One item in the catalog. */
|
|
86
86
|
export interface CosmeticItem {
|
|
87
87
|
id: string;
|
|
88
88
|
slot: CosmeticSlot;
|
|
89
89
|
name: string;
|
|
90
|
+
description?: string;
|
|
90
91
|
/**
|
|
91
92
|
* ALWAYS plural, even for a single region, and the only shape there is: TF2
|
|
92
93
|
* carried a singular `equip_region` key alongside the plural one, and items
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flow-industries/id",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.24.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -140,7 +140,7 @@
|
|
|
140
140
|
],
|
|
141
141
|
"dependencies": {
|
|
142
142
|
"@aws-sdk/client-s3": "^3.1073.0",
|
|
143
|
-
"@flow-industries/ui": "^0.
|
|
143
|
+
"@flow-industries/ui": "^0.23.3",
|
|
144
144
|
"@hono/otel": "^1.1.2",
|
|
145
145
|
"@openobserve/browser-logs": "^0.3.1",
|
|
146
146
|
"@openobserve/browser-rum": "^0.3.1",
|