@jiggai/kitchen-plugin-marketing 0.2.8 → 0.2.10
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.
- package/dist/api/handler.js +437 -117
- package/dist/tabs/accounts.js +197 -157
- package/dist/tabs/content-library.js +226 -92
- package/package.json +1 -1
package/dist/tabs/accounts.js
CHANGED
|
@@ -53,59 +53,59 @@
|
|
|
53
53
|
fontSize: "0.7rem",
|
|
54
54
|
fontWeight: 600,
|
|
55
55
|
color: "white"
|
|
56
|
+
}),
|
|
57
|
+
capPill: (active) => ({
|
|
58
|
+
display: "inline-block",
|
|
59
|
+
background: active ? "rgba(99,179,237,0.15)" : "rgba(255,255,255,0.03)",
|
|
60
|
+
border: `1px solid ${active ? "rgba(99,179,237,0.3)" : "var(--ck-border-subtle)"}`,
|
|
61
|
+
borderRadius: "999px",
|
|
62
|
+
padding: "0.1rem 0.4rem",
|
|
63
|
+
fontSize: "0.6rem",
|
|
64
|
+
color: active ? "rgba(210,235,255,0.9)" : "var(--ck-text-tertiary)"
|
|
56
65
|
})
|
|
57
66
|
};
|
|
58
|
-
const
|
|
59
|
-
x: "\u{1D54F}",
|
|
60
|
-
twitter: "\u{1D54F}",
|
|
61
|
-
instagram: "\u{1F4F7}",
|
|
62
|
-
linkedin: "\u{1F4BC}",
|
|
63
|
-
facebook: "\u{1F4D8}",
|
|
64
|
-
youtube: "\u25B6\uFE0F",
|
|
65
|
-
tiktok: "\u{1F3B5}",
|
|
66
|
-
bluesky: "\u{1F98B}",
|
|
67
|
-
mastodon: "\u{1F418}",
|
|
68
|
-
reddit: "\u{1F916}",
|
|
69
|
-
discord: "\u{1F4AC}",
|
|
70
|
-
telegram: "\u2708\uFE0F",
|
|
71
|
-
pinterest: "\u{1F4CC}",
|
|
72
|
-
threads: "\u{1F9F5}",
|
|
73
|
-
medium: "\u270D\uFE0F",
|
|
74
|
-
wordpress: "\u{1F4DD}"
|
|
75
|
-
};
|
|
76
|
-
const TYPE_COLORS = {
|
|
67
|
+
const BACKEND_COLORS = {
|
|
77
68
|
postiz: "rgba(99,179,237,0.7)",
|
|
78
69
|
gateway: "rgba(134,239,172,0.7)",
|
|
79
|
-
|
|
80
|
-
|
|
70
|
+
direct: "rgba(251,191,36,0.7)",
|
|
71
|
+
none: "rgba(100,100,100,0.5)"
|
|
72
|
+
};
|
|
73
|
+
const BACKEND_LABELS = {
|
|
74
|
+
postiz: "Postiz",
|
|
75
|
+
gateway: "OpenClaw",
|
|
76
|
+
direct: "Direct API",
|
|
77
|
+
none: "Not connected"
|
|
81
78
|
};
|
|
82
79
|
function Accounts(props) {
|
|
83
80
|
const teamId = String(props?.teamId || "default");
|
|
84
81
|
const apiBase = useMemo(() => `/api/plugins/marketing`, []);
|
|
85
|
-
const [
|
|
82
|
+
const [drivers, setDrivers] = useState([]);
|
|
86
83
|
const [manualAccounts, setManualAccounts] = useState([]);
|
|
87
84
|
const [loading, setLoading] = useState(true);
|
|
88
|
-
const [detecting, setDetecting] = useState(false);
|
|
89
85
|
const [error, setError] = useState(null);
|
|
90
86
|
const [postizKey, setPostizKey] = useState("");
|
|
91
87
|
const [postizUrl, setPostizUrl] = useState("https://api.postiz.com/public/v1");
|
|
92
88
|
const [showPostizSetup, setShowPostizSetup] = useState(false);
|
|
93
89
|
const [showManual, setShowManual] = useState(false);
|
|
94
|
-
const [manPlatform, setManPlatform] = useState("
|
|
90
|
+
const [manPlatform, setManPlatform] = useState("x");
|
|
95
91
|
const [manName, setManName] = useState("");
|
|
96
92
|
const [manUser, setManUser] = useState("");
|
|
97
93
|
const [manToken, setManToken] = useState("");
|
|
98
94
|
const [saving, setSaving] = useState(false);
|
|
99
|
-
|
|
95
|
+
const getStoredPostiz = () => {
|
|
100
96
|
try {
|
|
101
97
|
const stored = localStorage.getItem(`ck-postiz-${teamId}`);
|
|
102
|
-
if (stored)
|
|
103
|
-
const parsed = JSON.parse(stored);
|
|
104
|
-
setPostizKey(parsed.apiKey || "");
|
|
105
|
-
setPostizUrl(parsed.baseUrl || "https://api.postiz.com/public/v1");
|
|
106
|
-
}
|
|
98
|
+
if (stored) return JSON.parse(stored);
|
|
107
99
|
} catch {
|
|
108
100
|
}
|
|
101
|
+
return null;
|
|
102
|
+
};
|
|
103
|
+
useEffect(() => {
|
|
104
|
+
const stored = getStoredPostiz();
|
|
105
|
+
if (stored) {
|
|
106
|
+
setPostizKey(stored.apiKey || "");
|
|
107
|
+
setPostizUrl(stored.baseUrl || "https://api.postiz.com/public/v1");
|
|
108
|
+
}
|
|
109
109
|
}, [teamId]);
|
|
110
110
|
const savePostizConfig = () => {
|
|
111
111
|
try {
|
|
@@ -113,18 +113,9 @@
|
|
|
113
113
|
} catch {
|
|
114
114
|
}
|
|
115
115
|
setShowPostizSetup(false);
|
|
116
|
-
void
|
|
117
|
-
};
|
|
118
|
-
const getStoredPostiz = () => {
|
|
119
|
-
try {
|
|
120
|
-
const stored = localStorage.getItem(`ck-postiz-${teamId}`);
|
|
121
|
-
if (stored) return JSON.parse(stored);
|
|
122
|
-
} catch {
|
|
123
|
-
}
|
|
124
|
-
return null;
|
|
116
|
+
void loadDrivers();
|
|
125
117
|
};
|
|
126
|
-
const
|
|
127
|
-
setDetecting(true);
|
|
118
|
+
const loadDrivers = async () => {
|
|
128
119
|
setError(null);
|
|
129
120
|
try {
|
|
130
121
|
const stored = getStoredPostiz();
|
|
@@ -135,13 +126,11 @@
|
|
|
135
126
|
headers["x-postiz-api-key"] = key;
|
|
136
127
|
headers["x-postiz-base-url"] = url;
|
|
137
128
|
}
|
|
138
|
-
const res = await fetch(`${apiBase}/
|
|
129
|
+
const res = await fetch(`${apiBase}/drivers?team=${encodeURIComponent(teamId)}`, { headers });
|
|
139
130
|
const json = await res.json();
|
|
140
|
-
|
|
131
|
+
setDrivers(Array.isArray(json.drivers) ? json.drivers : []);
|
|
141
132
|
} catch (e) {
|
|
142
|
-
setError(e?.message || "Failed to
|
|
143
|
-
} finally {
|
|
144
|
-
setDetecting(false);
|
|
133
|
+
setError(e?.message || "Failed to load drivers");
|
|
145
134
|
}
|
|
146
135
|
};
|
|
147
136
|
const loadManual = async () => {
|
|
@@ -154,7 +143,7 @@
|
|
|
154
143
|
};
|
|
155
144
|
const refresh = async () => {
|
|
156
145
|
setLoading(true);
|
|
157
|
-
await Promise.all([
|
|
146
|
+
await Promise.all([loadDrivers(), loadManual()]);
|
|
158
147
|
setLoading(false);
|
|
159
148
|
};
|
|
160
149
|
useEffect(() => {
|
|
@@ -179,43 +168,17 @@
|
|
|
179
168
|
setManName("");
|
|
180
169
|
setManUser("");
|
|
181
170
|
setManToken("");
|
|
182
|
-
await loadManual();
|
|
171
|
+
await Promise.all([loadDrivers(), loadManual()]);
|
|
183
172
|
} catch (e) {
|
|
184
173
|
setError(e?.message || "Failed to connect");
|
|
185
174
|
} finally {
|
|
186
175
|
setSaving(false);
|
|
187
176
|
}
|
|
188
177
|
};
|
|
189
|
-
const
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
id: `manual:${ma.id}`,
|
|
194
|
-
type: "manual",
|
|
195
|
-
platform: ma.platform,
|
|
196
|
-
displayName: ma.displayName,
|
|
197
|
-
username: ma.username,
|
|
198
|
-
isActive: ma.isActive,
|
|
199
|
-
capabilities: ["post"]
|
|
200
|
-
});
|
|
201
|
-
}
|
|
202
|
-
return combined;
|
|
203
|
-
}, [providers, manualAccounts]);
|
|
204
|
-
const grouped = useMemo(() => {
|
|
205
|
-
const g = {};
|
|
206
|
-
for (const p of allProviders) {
|
|
207
|
-
const key = p.type;
|
|
208
|
-
if (!g[key]) g[key] = [];
|
|
209
|
-
g[key].push(p);
|
|
210
|
-
}
|
|
211
|
-
return g;
|
|
212
|
-
}, [allProviders]);
|
|
213
|
-
const typeLabels = {
|
|
214
|
-
postiz: "Postiz",
|
|
215
|
-
gateway: "OpenClaw Channels",
|
|
216
|
-
skill: "Skills",
|
|
217
|
-
manual: "Manual"
|
|
218
|
-
};
|
|
178
|
+
const connectedDrivers = useMemo(() => drivers.filter((d) => d.connected), [drivers]);
|
|
179
|
+
const disconnectedDrivers = useMemo(() => drivers.filter((d) => !d.connected), [drivers]);
|
|
180
|
+
const connectedCount = connectedDrivers.length;
|
|
181
|
+
const totalCount = drivers.length;
|
|
219
182
|
return h(
|
|
220
183
|
"div",
|
|
221
184
|
{ className: "space-y-3" },
|
|
@@ -229,11 +192,11 @@
|
|
|
229
192
|
h(
|
|
230
193
|
"div",
|
|
231
194
|
null,
|
|
232
|
-
h("div", { className: "text-sm font-medium", style: t.text }, "
|
|
195
|
+
h("div", { className: "text-sm font-medium", style: t.text }, "Platform Drivers"),
|
|
233
196
|
h(
|
|
234
197
|
"div",
|
|
235
198
|
{ className: "mt-1 text-xs", style: t.faint },
|
|
236
|
-
`${
|
|
199
|
+
`${connectedCount}/${totalCount} platforms connected`
|
|
237
200
|
)
|
|
238
201
|
),
|
|
239
202
|
h(
|
|
@@ -241,15 +204,15 @@
|
|
|
241
204
|
{ className: "flex flex-wrap gap-2" },
|
|
242
205
|
h(
|
|
243
206
|
"button",
|
|
244
|
-
{ type: "button", onClick: () => void refresh(), style: t.btnGhost, disabled:
|
|
245
|
-
|
|
207
|
+
{ type: "button", onClick: () => void refresh(), style: t.btnGhost, disabled: loading },
|
|
208
|
+
loading ? "Loading\u2026" : "\u21BB Refresh"
|
|
246
209
|
),
|
|
247
210
|
h(
|
|
248
211
|
"button",
|
|
249
212
|
{ type: "button", onClick: () => setShowPostizSetup(!showPostizSetup), style: t.btnGhost },
|
|
250
213
|
postizKey ? "\u2699 Postiz" : "+ Postiz"
|
|
251
214
|
),
|
|
252
|
-
h("button", { type: "button", onClick: () => setShowManual(!showManual), style: t.btnGhost }, "+
|
|
215
|
+
h("button", { type: "button", onClick: () => setShowManual(!showManual), style: t.btnGhost }, "+ Direct token")
|
|
253
216
|
)
|
|
254
217
|
),
|
|
255
218
|
error && h("div", { className: "mt-2 text-xs", style: { color: "rgba(248,113,113,0.95)" } }, error)
|
|
@@ -262,7 +225,7 @@
|
|
|
262
225
|
h(
|
|
263
226
|
"div",
|
|
264
227
|
{ className: "text-xs mb-3", style: t.faint },
|
|
265
|
-
"
|
|
228
|
+
"Postiz manages OAuth connections to social platforms. Get your API key from Postiz Settings \u2192 Developers \u2192 Public API."
|
|
266
229
|
),
|
|
267
230
|
h(
|
|
268
231
|
"div",
|
|
@@ -295,15 +258,15 @@
|
|
|
295
258
|
"div",
|
|
296
259
|
{ className: "mt-3 flex gap-2" },
|
|
297
260
|
h("button", { type: "button", onClick: () => setShowPostizSetup(false), style: t.btnGhost }, "Cancel"),
|
|
298
|
-
h("button", { type: "button", onClick: savePostizConfig, style: t.btnPrimary },
|
|
261
|
+
h("button", { type: "button", onClick: savePostizConfig, style: t.btnPrimary }, "Save & Detect")
|
|
299
262
|
)
|
|
300
263
|
),
|
|
301
|
-
// ---- Manual
|
|
264
|
+
// ---- Manual token form ----
|
|
302
265
|
showManual && h(
|
|
303
266
|
"div",
|
|
304
267
|
{ style: t.card },
|
|
305
|
-
h("div", { className: "text-sm font-medium mb-2", style: t.text }, "Add
|
|
306
|
-
h("div", { className: "text-xs mb-3", style: t.faint }, "For
|
|
268
|
+
h("div", { className: "text-sm font-medium mb-2", style: t.text }, "Add direct API token"),
|
|
269
|
+
h("div", { className: "text-xs mb-3", style: t.faint }, "For platforms where you have your own API credentials. Token is encrypted at rest."),
|
|
307
270
|
h(
|
|
308
271
|
"div",
|
|
309
272
|
{ className: "grid grid-cols-1 gap-2 sm:grid-cols-2" },
|
|
@@ -314,18 +277,14 @@
|
|
|
314
277
|
h(
|
|
315
278
|
"select",
|
|
316
279
|
{ value: manPlatform, onChange: (e) => setManPlatform(e.target.value), style: t.input },
|
|
317
|
-
h("option", { value:
|
|
318
|
-
h("option", { value: "instagram" }, "Instagram"),
|
|
319
|
-
h("option", { value: "linkedin" }, "LinkedIn"),
|
|
320
|
-
h("option", { value: "bluesky" }, "Bluesky"),
|
|
321
|
-
h("option", { value: "mastodon" }, "Mastodon")
|
|
280
|
+
...drivers.map((d) => h("option", { key: d.platform, value: d.platform }, d.label))
|
|
322
281
|
)
|
|
323
282
|
),
|
|
324
283
|
h(
|
|
325
284
|
"div",
|
|
326
285
|
null,
|
|
327
286
|
h("div", { className: "text-xs font-medium mb-1", style: t.faint }, "Display name"),
|
|
328
|
-
h("input", { value: manName, onChange: (e) => setManName(e.target.value), placeholder: "My
|
|
287
|
+
h("input", { value: manName, onChange: (e) => setManName(e.target.value), placeholder: "My account", style: t.input })
|
|
329
288
|
),
|
|
330
289
|
h(
|
|
331
290
|
"div",
|
|
@@ -347,87 +306,168 @@
|
|
|
347
306
|
h("button", { type: "button", onClick: () => void onManualConnect(), style: t.btnPrimary, disabled: saving }, saving ? "Saving\u2026" : "Connect")
|
|
348
307
|
)
|
|
349
308
|
),
|
|
350
|
-
// ----
|
|
351
|
-
|
|
352
|
-
"div",
|
|
353
|
-
{ style: t.card },
|
|
354
|
-
h("div", { className: "py-6 text-center text-sm", style: t.faint }, "Detecting providers\u2026")
|
|
355
|
-
),
|
|
356
|
-
// ---- Provider groups ----
|
|
357
|
-
!loading && allProviders.length === 0 && h(
|
|
309
|
+
// ---- Connected platforms ----
|
|
310
|
+
connectedDrivers.length > 0 && h(
|
|
358
311
|
"div",
|
|
359
312
|
{ style: t.card },
|
|
360
313
|
h(
|
|
361
314
|
"div",
|
|
362
|
-
{ className: "
|
|
363
|
-
h("div", { className: "text-sm", style: t.
|
|
364
|
-
h(
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
315
|
+
{ className: "flex items-center gap-2 mb-3" },
|
|
316
|
+
h("div", { className: "text-sm font-medium", style: t.text }, "Connected"),
|
|
317
|
+
h("span", { style: t.badge("rgba(74,222,128,0.7)") }, `${connectedCount}`)
|
|
318
|
+
),
|
|
319
|
+
h(
|
|
320
|
+
"div",
|
|
321
|
+
{ className: "space-y-2" },
|
|
322
|
+
...connectedDrivers.map(
|
|
323
|
+
(d) => h(
|
|
324
|
+
"div",
|
|
325
|
+
{ key: d.platform, style: { ...t.card, padding: "0.75rem", display: "flex", alignItems: "center", gap: "0.75rem" } },
|
|
326
|
+
d.avatar ? h("img", { src: d.avatar, alt: "", style: { width: 36, height: 36, borderRadius: "50%", objectFit: "cover" } }) : h("div", {
|
|
327
|
+
style: {
|
|
328
|
+
width: 36,
|
|
329
|
+
height: 36,
|
|
330
|
+
borderRadius: "50%",
|
|
331
|
+
background: "rgba(255,255,255,0.06)",
|
|
332
|
+
display: "flex",
|
|
333
|
+
alignItems: "center",
|
|
334
|
+
justifyContent: "center",
|
|
335
|
+
fontSize: "1.1rem"
|
|
336
|
+
}
|
|
337
|
+
}, d.icon),
|
|
338
|
+
h(
|
|
339
|
+
"div",
|
|
340
|
+
{ style: { flex: 1, minWidth: 0 } },
|
|
341
|
+
h("div", { className: "text-sm font-medium", style: t.text }, d.displayName),
|
|
342
|
+
h(
|
|
343
|
+
"div",
|
|
344
|
+
{ className: "text-xs", style: t.faint },
|
|
345
|
+
[d.username, d.platform].filter(Boolean).join(" \xB7 ")
|
|
346
|
+
)
|
|
347
|
+
),
|
|
348
|
+
h(
|
|
349
|
+
"div",
|
|
350
|
+
{ className: "flex items-center gap-2 shrink-0 flex-wrap" },
|
|
351
|
+
h("span", { style: t.badge(BACKEND_COLORS[d.backend] || BACKEND_COLORS.none) }, BACKEND_LABELS[d.backend] || d.backend),
|
|
352
|
+
d.capabilities.canPost && h("span", { style: t.capPill(true) }, "post"),
|
|
353
|
+
d.capabilities.canSchedule && h("span", { style: t.capPill(true) }, "schedule"),
|
|
354
|
+
d.capabilities.canUploadMedia && h("span", { style: t.capPill(true) }, "media"),
|
|
355
|
+
d.capabilities.maxLength && h("span", { style: t.capPill(false) }, `${d.capabilities.maxLength} chars`),
|
|
356
|
+
h("div", {
|
|
357
|
+
style: {
|
|
358
|
+
width: 8,
|
|
359
|
+
height: 8,
|
|
360
|
+
borderRadius: "50%",
|
|
361
|
+
background: "rgba(74,222,128,0.8)"
|
|
362
|
+
}
|
|
363
|
+
})
|
|
364
|
+
)
|
|
365
|
+
)
|
|
368
366
|
)
|
|
369
367
|
)
|
|
370
368
|
),
|
|
371
|
-
|
|
372
|
-
|
|
369
|
+
// ---- Disconnected platforms ----
|
|
370
|
+
disconnectedDrivers.length > 0 && h(
|
|
371
|
+
"div",
|
|
372
|
+
{ style: t.card },
|
|
373
|
+
h(
|
|
373
374
|
"div",
|
|
374
|
-
{
|
|
375
|
-
h(
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
375
|
+
{ className: "flex items-center gap-2 mb-3" },
|
|
376
|
+
h("div", { className: "text-sm font-medium", style: t.text }, "Available"),
|
|
377
|
+
h("span", { style: t.badge("rgba(100,100,100,0.5)") }, `${disconnectedDrivers.length}`)
|
|
378
|
+
),
|
|
379
|
+
h(
|
|
380
|
+
"div",
|
|
381
|
+
{ className: "text-xs mb-3", style: t.faint },
|
|
382
|
+
"Connect these via Postiz or by adding a direct API token above."
|
|
383
|
+
),
|
|
384
|
+
h(
|
|
385
|
+
"div",
|
|
386
|
+
{ className: "space-y-2" },
|
|
387
|
+
...disconnectedDrivers.map(
|
|
388
|
+
(d) => h(
|
|
389
|
+
"div",
|
|
390
|
+
{ key: d.platform, style: { ...t.card, padding: "0.75rem", display: "flex", alignItems: "center", gap: "0.75rem", opacity: 0.6 } },
|
|
391
|
+
h("div", {
|
|
392
|
+
style: {
|
|
393
|
+
width: 36,
|
|
394
|
+
height: 36,
|
|
395
|
+
borderRadius: "50%",
|
|
396
|
+
background: "rgba(255,255,255,0.04)",
|
|
397
|
+
display: "flex",
|
|
398
|
+
alignItems: "center",
|
|
399
|
+
justifyContent: "center",
|
|
400
|
+
fontSize: "1.1rem"
|
|
401
|
+
}
|
|
402
|
+
}, d.icon),
|
|
403
|
+
h(
|
|
386
404
|
"div",
|
|
387
|
-
{
|
|
388
|
-
|
|
389
|
-
|
|
405
|
+
{ style: { flex: 1, minWidth: 0 } },
|
|
406
|
+
h("div", { className: "text-sm font-medium", style: t.text }, d.label),
|
|
407
|
+
h("div", { className: "text-xs", style: t.faint }, "Not connected")
|
|
408
|
+
),
|
|
409
|
+
h(
|
|
410
|
+
"div",
|
|
411
|
+
{ className: "flex items-center gap-2 shrink-0" },
|
|
412
|
+
d.capabilities.maxLength && h("span", { style: t.capPill(false) }, `${d.capabilities.maxLength} chars`),
|
|
413
|
+
h("div", {
|
|
390
414
|
style: {
|
|
391
|
-
width:
|
|
392
|
-
height:
|
|
415
|
+
width: 8,
|
|
416
|
+
height: 8,
|
|
393
417
|
borderRadius: "50%",
|
|
394
|
-
background: "rgba(
|
|
395
|
-
display: "flex",
|
|
396
|
-
alignItems: "center",
|
|
397
|
-
justifyContent: "center",
|
|
398
|
-
fontSize: "1rem"
|
|
418
|
+
background: "rgba(100,100,100,0.4)"
|
|
399
419
|
}
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
420
|
+
})
|
|
421
|
+
)
|
|
422
|
+
)
|
|
423
|
+
)
|
|
424
|
+
)
|
|
425
|
+
),
|
|
426
|
+
// ---- Manual accounts (if any exist beyond drivers) ----
|
|
427
|
+
manualAccounts.length > 0 && h(
|
|
428
|
+
"div",
|
|
429
|
+
{ style: t.card },
|
|
430
|
+
h(
|
|
431
|
+
"div",
|
|
432
|
+
{ className: "flex items-center gap-2 mb-3" },
|
|
433
|
+
h("div", { className: "text-sm font-medium", style: t.text }, "Stored tokens"),
|
|
434
|
+
h("span", { style: t.badge("rgba(251,191,36,0.7)") }, `${manualAccounts.length}`)
|
|
435
|
+
),
|
|
436
|
+
h("div", { className: "text-xs mb-3", style: t.faint }, "Tokens stored locally, encrypted at rest. These feed into the direct backend for their platform driver."),
|
|
437
|
+
h(
|
|
438
|
+
"div",
|
|
439
|
+
{ className: "space-y-2" },
|
|
440
|
+
...manualAccounts.map(
|
|
441
|
+
(a) => h(
|
|
442
|
+
"div",
|
|
443
|
+
{ key: a.id, style: { ...t.card, padding: "0.75rem", display: "flex", alignItems: "center", gap: "0.75rem" } },
|
|
444
|
+
h(
|
|
445
|
+
"div",
|
|
446
|
+
{ style: { flex: 1, minWidth: 0 } },
|
|
447
|
+
h("div", { className: "text-sm", style: t.text }, a.displayName),
|
|
413
448
|
h(
|
|
414
449
|
"div",
|
|
415
|
-
{ className: "
|
|
416
|
-
|
|
417
|
-
p.capabilities?.includes("post") && h("span", { className: "text-xs", style: t.faint }, "\u{1F4E4}"),
|
|
418
|
-
h("div", {
|
|
419
|
-
style: {
|
|
420
|
-
width: 8,
|
|
421
|
-
height: 8,
|
|
422
|
-
borderRadius: "50%",
|
|
423
|
-
background: p.isActive ? "rgba(74,222,128,0.8)" : "rgba(248,113,113,0.6)"
|
|
424
|
-
}
|
|
425
|
-
})
|
|
450
|
+
{ className: "text-xs", style: t.faint },
|
|
451
|
+
[a.platform, a.username].filter(Boolean).join(" \xB7 ")
|
|
426
452
|
)
|
|
427
|
-
)
|
|
453
|
+
),
|
|
454
|
+
h("div", {
|
|
455
|
+
style: {
|
|
456
|
+
width: 8,
|
|
457
|
+
height: 8,
|
|
458
|
+
borderRadius: "50%",
|
|
459
|
+
background: a.isActive ? "rgba(74,222,128,0.8)" : "rgba(248,113,113,0.6)"
|
|
460
|
+
}
|
|
461
|
+
})
|
|
428
462
|
)
|
|
429
463
|
)
|
|
430
464
|
)
|
|
465
|
+
),
|
|
466
|
+
// ---- Loading ----
|
|
467
|
+
loading && drivers.length === 0 && h(
|
|
468
|
+
"div",
|
|
469
|
+
{ style: t.card },
|
|
470
|
+
h("div", { className: "py-6 text-center text-sm", style: t.faint }, "Detecting platform drivers\u2026")
|
|
431
471
|
)
|
|
432
472
|
);
|
|
433
473
|
}
|