@frockbot/plugin-flock 0.3.8 → 0.3.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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@frockbot/plugin-flock",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.10",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -27,16 +27,16 @@
|
|
|
27
27
|
"typecheck": "vue-tsc --noEmit -p tsconfig.json"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@frockbot/client-core": "0.3.
|
|
31
|
-
"@frockbot/client-ui": "0.3.
|
|
32
|
-
"@frockbot/configuration-core": "0.3.
|
|
33
|
-
"@frockbot/kernel-contracts": "0.3.
|
|
34
|
-
"@frockbot/plugin-shell": "0.3.
|
|
30
|
+
"@frockbot/client-core": "0.3.10",
|
|
31
|
+
"@frockbot/client-ui": "0.3.10",
|
|
32
|
+
"@frockbot/configuration-core": "0.3.10",
|
|
33
|
+
"@frockbot/kernel-contracts": "0.3.10",
|
|
34
|
+
"@frockbot/plugin-shell": "0.3.10",
|
|
35
35
|
"cordis": "4.0.0-rc.8",
|
|
36
36
|
"vue": "3.5.41"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
|
-
"@frockbot/plugin-testkit": "0.3.
|
|
39
|
+
"@frockbot/plugin-testkit": "0.3.10",
|
|
40
40
|
"@types/bun": "1.4.0",
|
|
41
41
|
"@vitejs/plugin-vue": "6.0.8",
|
|
42
42
|
"css-tree": "2.3.1",
|
|
@@ -89,7 +89,13 @@ onMounted(() => void flock.value.load());
|
|
|
89
89
|
{{ flock.showArchived ? "Hide archived" : "Manage" }}
|
|
90
90
|
</button>
|
|
91
91
|
</div>
|
|
92
|
-
|
|
92
|
+
<!--
|
|
93
|
+
The skeleton is for a list nobody has yet, not for every request: the first
|
|
94
|
+
paint happens before `load()` is even called, and a reload after creating a
|
|
95
|
+
Bot must keep the list already on screen rather than blanking it. "No Bots
|
|
96
|
+
yet." is a fact about the account, so it waits for an answer.
|
|
97
|
+
-->
|
|
98
|
+
<div v-if="!flock.loaded" class="flock-skeleton" aria-busy="true">
|
|
93
99
|
<span class="flock-skeleton-label">Loading your flock…</span>
|
|
94
100
|
<div v-for="row in 3" :key="row" class="flock-skeleton-row">
|
|
95
101
|
<UiSkeleton shape="circle" />
|
package/src/client/index.test.ts
CHANGED
|
@@ -376,6 +376,38 @@ describe("Flock client reconciliation", () => {
|
|
|
376
376
|
expect(state.value.overlay).toBeUndefined();
|
|
377
377
|
expect(selected).not.toHaveLength(0);
|
|
378
378
|
expect(selected.every((botId) => botId === createdBotId)).toBe(true);
|
|
379
|
+
// The User has just made a Bot; nothing on screen may say they have none.
|
|
380
|
+
// `loaded` is what the sidebar reads before it renders "No Bots yet.", and
|
|
381
|
+
// the created Bot is in the list by the time the dialog is gone.
|
|
382
|
+
expect(state.value.loaded).toBe(true);
|
|
383
|
+
expect(state.value.directory.bots.map((bot) => bot.botId)).toEqual([
|
|
384
|
+
createdBotId,
|
|
385
|
+
]);
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
// The empty state is a fact about the account, and before the first read the
|
|
389
|
+
// account is unknown: the sidebar used to claim "No Bots yet." on the first
|
|
390
|
+
// paint, before `load()` had even been called.
|
|
391
|
+
test("does not claim an empty flock before the first read lands", async () => {
|
|
392
|
+
installStorage();
|
|
393
|
+
const state = mount((path) => {
|
|
394
|
+
if (path === "/api/bots")
|
|
395
|
+
return Promise.resolve({ schemaVersion: 1, revision: 1, bots: [] });
|
|
396
|
+
if (path === "/api/bots/lifecycles")
|
|
397
|
+
return Promise.resolve({ schemaVersion: 1, lifecycles: [] });
|
|
398
|
+
if (path === "/api/bots/identities")
|
|
399
|
+
return Promise.resolve({ schemaVersion: 1, identities: [] });
|
|
400
|
+
return Promise.reject(new Error(`unexpected request: ${path}`));
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
// Before any read: the account is unknown, so the sidebar keeps its
|
|
404
|
+
// skeleton rather than asserting the User has no Bots.
|
|
405
|
+
expect(state.value.loaded).toBe(false);
|
|
406
|
+
|
|
407
|
+
await state.value.load();
|
|
408
|
+
|
|
409
|
+
expect(state.value.loaded).toBe(true);
|
|
410
|
+
expect(state.value.directory.bots).toEqual([]);
|
|
379
411
|
});
|
|
380
412
|
|
|
381
413
|
test("archives with confirmation, hides archived Bots, and selects a fallback", async () => {
|
package/src/client/index.ts
CHANGED
|
@@ -115,6 +115,7 @@ export const flockClientPlugin: ClientPlugin = (ctx) => {
|
|
|
115
115
|
showArchived: false,
|
|
116
116
|
showHidden: false,
|
|
117
117
|
loading: false,
|
|
118
|
+
loaded: false,
|
|
118
119
|
draftName: "",
|
|
119
120
|
draftSheep: randomSheepRecipeV1(),
|
|
120
121
|
bindShell(value) {
|
|
@@ -153,6 +154,7 @@ export const flockClientPlugin: ClientPlugin = (ctx) => {
|
|
|
153
154
|
if (generation !== loadGeneration) return;
|
|
154
155
|
authenticatedUserId = userId;
|
|
155
156
|
state.value.directory = directory;
|
|
157
|
+
state.value.loaded = true;
|
|
156
158
|
state.value.lifecycles = Object.fromEntries(
|
|
157
159
|
lifecycleDirectory.lifecycles.map((item) => [
|
|
158
160
|
item.botId,
|
|
@@ -503,9 +505,12 @@ export const flockClientPlugin: ClientPlugin = (ctx) => {
|
|
|
503
505
|
}
|
|
504
506
|
clearPendingCreate(userId);
|
|
505
507
|
replacePreferredBot(command.botId);
|
|
506
|
-
|
|
508
|
+
// The list first, the dialog last. Tearing the dialog down before the
|
|
509
|
+
// reload landed showed the User the first-run empty state — "No Bots
|
|
510
|
+
// yet. Add your first sheep." — for the Bot they had just added.
|
|
507
511
|
await state.value.load();
|
|
508
512
|
await state.value.select(command.botId);
|
|
513
|
+
state.value.overlay = undefined;
|
|
509
514
|
} catch (error) {
|
|
510
515
|
if (isDefinitiveFlockFailure(error) && authenticatedUserId)
|
|
511
516
|
clearPendingCreate(authenticatedUserId);
|
package/src/client/state.ts
CHANGED
|
@@ -20,6 +20,14 @@ export interface FlockWebData {
|
|
|
20
20
|
/** Per-Bot unread, as the Bot Durable Objects derive it. Never computed here. */
|
|
21
21
|
unread: Record<string, BotUnreadViewV1>;
|
|
22
22
|
loading: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Whether a directory read has ever completed.
|
|
25
|
+
*
|
|
26
|
+
* "No Bots yet." is a fact about the User's account, and it can only be
|
|
27
|
+
* stated once the account has been read. Before that — the first paint, and
|
|
28
|
+
* the reload after a Bot is created — the list is unknown, not empty.
|
|
29
|
+
*/
|
|
30
|
+
loaded: boolean;
|
|
23
31
|
error?: string;
|
|
24
32
|
overlay?: "create" | "edit" | "archive";
|
|
25
33
|
lifecycles: Record<string, BotLifecycleStatusV1>;
|