diff --git a/.agents/skills/flotilla-architecture/SKILL.md b/.agents/skills/flotilla-architecture/SKILL.md index 0f946883..6ad03b09 100644 --- a/.agents/skills/flotilla-architecture/SKILL.md +++ b/.agents/skills/flotilla-architecture/SKILL.md @@ -47,8 +47,9 @@ only gate. component that needs app behavior takes it as a prop, or moves to `src/app/components`, as `IconInput` and its picker buttons did. - **app → components.** `routes.ts` (`goToChat` opens `ChatEnable`, `goToEvent` opens - `NoteDetail`), `share.ts` (`Share`, `ShareEvent`), `deepLinks.ts` (`Search`) and `speech.ts` - (`OpenRouterEnable`) import a component so they can open a modal mid-flow. Push adapters and + `NoteDetail`), `share.ts` (`Share`, `ShareEvent`), `deepLinks.ts` (`Search`), `speech.ts` + (`OpenRouterEnable`) and `healthChecks.ts` (`KeyDownload`, the fix for the key backup check) + import a component so they can open a modal mid-flow. Push adapters and deep links reach those flows from outside any component, and the rest have several component callers, so each stays in one module. `editor/` holds `.svelte` files of its own (suggestion popovers), which `makeEditor` mounts. @@ -162,7 +163,7 @@ size from `localStorage` before first paint. Then, in order: 1. `restoreSession()` restores the saved session, if there is one, which builds a user-scoped `App` through `login`. 2. It awaits `.ready` on the `synced` stores boot reads (device, wallet, push and notification - settings, `shouldUnwrap`, `needsKeyBackup`). + settings, `shouldUnwrap`, `forceHealthChecks`). 3. It waits for storage, then `setupDeepLinks()` listens for warm-start links and handles a cold-start one. 4. Each long-running subscription goes onto one `unsubscribers` list: `setupHistory`, diff --git a/.agents/skills/flotilla-state/SKILL.md b/.agents/skills/flotilla-state/SKILL.md index 333b0e2a..88a959d2 100644 --- a/.agents/skills/flotilla-state/SKILL.md +++ b/.agents/skills/flotilla-state/SKILL.md @@ -247,7 +247,7 @@ A derivation that every row subscribes to, or that joins large sets, is built by | repository, tracker, relays, relay stats, handles, zappers, plaintext, wraps | IndexedDB | yes | deleted | | settings (`SettingsValues`) | an encrypted app-data event, cached in IndexedDB | yes | local copy deleted | | `session`, `wallet` | `ss` | no | cleared | -| `theme`, `flTheme`, `checked`, `shouldUnwrap`, `device`, `notificationSettings`, push state, `needsKeyBackup` | `kv` | no | cleared | +| `theme`, `flTheme`, `checked`, `shouldUnwrap`, `device`, `notificationSettings`, push state, `forceHealthChecks` | `kv` | no | cleared | | drafts, dictations | a module `Map`, lost on reload | no | page reloads | ### IndexedDB (`src/app/storage.ts`, `src/lib/indexeddb.ts`) @@ -288,13 +288,13 @@ or `withGetter(synced(...))` when callers need `.get()`, which keeps `.ready`. T `.ready` resolves once it has arrived: - `theme`, `flTheme` (`theme.ts`), `checked` (`notifications.ts`), `shouldUnwrap` (`sync.ts`), - `device` (`device.ts`), `needsKeyBackup` (`healthChecks.ts`) in `kv` + `device` (`device.ts`), `forceHealthChecks` (`healthChecks.ts`) in `kv` - `pushState` (key `notificationState`) and `notificationSettings` in `kv`, both in `push/adapters/common.ts` and re-exported from `@app/push` - `wallet` (`lightning.ts`) in `ss` The root layout awaits `.ready` for the stores boot code reads (`device`, `shouldUnwrap`, -`wallet`, `notificationSettings`, `pushState`, `needsKeyBackup`) before `Push.sync()` and +`wallet`, `notificationSettings`, `pushState`, `forceHealthChecks`) before `Push.sync()` and background sync start. A new store that boot reads joins that list. Never change a key, since it is where existing installs keep their value. diff --git a/src/app/components/HealthCheckReview.svelte b/src/app/components/HealthCheckReview.svelte index 4658a5b1..9eb94cc4 100644 --- a/src/app/components/HealthCheckReview.svelte +++ b/src/app/components/HealthCheckReview.svelte @@ -32,7 +32,8 @@ const back = () => history.back() const save = async (plan: HealthCheckPlan) => { - const error = await publish(await plan.apply()).waitForError() + const command = await plan.apply() + const error = command && (await publish(command).waitForError()) if (error) { pushToast({theme: "error", message: `Your relays couldn't be saved: ${errorMessage(error)}`}) diff --git a/src/app/components/HomeHealthChecks.svelte b/src/app/components/HomeHealthChecks.svelte index 95563bb3..ab67fa0a 100644 --- a/src/app/components/HomeHealthChecks.svelte +++ b/src/app/components/HomeHealthChecks.svelte @@ -7,52 +7,38 @@ import HomeSection from "@app/components/HomeSection.svelte" import HealthCheckItem from "@app/components/HealthCheckItem.svelte" import HealthCheckReview from "@app/components/HealthCheckReview.svelte" - import KeyDownload from "@app/components/KeyDownload.svelte" import type {HealthCheck} from "@app/healthChecks" - import {healthChecks, needsKeyBackup} from "@app/healthChecks" - import {session} from "@app/core" + import {healthChecks} from "@app/healthChecks" import {pushModal} from "@app/modal" const pending = $healthChecks.pending.$ - const count = $derived($pending.length + ($needsKeyBackup ? 1 : 0)) + // Changes are confirmed first, and fixes that change nothing to review run once they're saved. + const review = (checks: HealthCheck[]) => { + const plans = checks.map(check => $healthChecks.plan(check)) + const reviewed = plans.filter(plan => plan.changes.length > 0) + const applyRest = () => + plans.filter(plan => plan.changes.length === 0).forEach(plan => plan.apply()) - const finishKeyBackup = () => { - needsKeyBackup.set(false) - history.back() - } - - const backUpKey = () => - pushModal(KeyDownload, { - secret: ($session!.data as {secret: string}).secret, - next: finishKeyBackup, - submitText: "Done", - }) - - const review = (checks: HealthCheck[], next?: () => void) => { - const plans = checks - .map(check => $healthChecks.plan(check)) - .filter(plan => plan.changes.length > 0) - - if (plans.length > 0) { - pushModal(HealthCheckReview, {plans, next}) + if (reviewed.length > 0) { + pushModal(HealthCheckReview, {plans: reviewed, next: applyRest}) } else { - next?.() + applyRest() } } const fix = (healthCheck: HealthCheck) => () => review([healthCheck]) - const reviewAll = () => review($pending, $needsKeyBackup ? backUpKey : undefined) + const reviewAll = () => review($pending) {#snippet action()} - {#if count > 0} - {count} open + {#if $pending.length > 0} + {$pending.length} open {/if} {/snippet} - {#if count === 0} + {#if $pending.length === 0}

Your connection to the network looks healthy. @@ -65,13 +51,7 @@ description={healthCheck.description} onfix={fix(healthCheck)} /> {/each} - {#if $needsKeyBackup} - - {/if} - {#if count > 1} + {#if $pending.length > 1}