libs: peer lib edits reach the running editor + "placed symbol updated" toast

synced-source subscribes to its SyncStack: remote changes (self-save echoes
consumed via a selfPushed flag) debounce per kind into kicadLibsReload — a
new embind export (pcbjam_libs_reload.h, all three TUs) that drops the lib's
plugin cache (LIBRARY_MANAGER::ReloadLibraryEntry), reloads it, and mails
MAIL_RELOAD_LIB with the nickname so the symbol tree force-refreshes (the
plugin's modify hash is a pinned constant, so a plain sync would skip it).

After the reload, kicadLibsSymbolUsage (new eeschema embind: placed
SCH_SYMBOL count across unique screens) gates LIB_ITEM_UPDATED_EVENT, and
WasmTool shows an amber toast when a PLACED symbol changed — placed copies
keep the previous version until updated from the library.

syncedScopeLibsSource gives PROJECT sessions the synced source under
VITE_LIBS_SOURCE=synced (remote contract for lib listing/createLib, lazy
per-lib SyncStacks for item ops/presync) so realtime reaches open
schematics; previously project sessions silently fell back to the per-item
remote source. Unit tests cover reload debounce, self-echo skip, per-kind
routing, usage-gated event, and the no-Module no-op.

Bumps kicad (MAIL_RELOAD_LIB force-refresh payload).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013QRWoXiM9uuo1enXGhAYku
This commit is contained in:
Gergő Törcsvári 2026-07-09 18:21:21 +02:00
commit 9315f56760
No known key found for this signature in database
GPG key ID: 8E75F2CDE64E5322
10 changed files with 649 additions and 11 deletions

View file

@ -110,7 +110,10 @@ import {
withSpikeWritableLib,
} from "@/wasm/libs/spike-writable";
import { staticLibsSource } from "@/wasm/libs/static-source";
import { syncedLibsSource } from "@/wasm/libs/synced-source";
import {
syncedLibsSource,
syncedScopeLibsSource,
} from "@/wasm/libs/synced-source";
/**
* Which Yjs collab provider this deployment uses (one active per env), and its
@ -151,6 +154,9 @@ export function docSourceConfig(): DocSource {
* "remote" (default) — fetch from the backend at `API_BASE_URL` over the
* shared contract (origins served by the registry, or the
* GPL example backend).
* "synced" — remote listing + per-lib r2-idb-sync stacks (IDB cache,
* realtime peer updates + editor reload). Also switches
* `libsSourceForLib` to the single-lib synced source.
* "static" — built-in offline example symbols (no backend).
* "off" — disable libs (empty sym-lib-table).
*/
@ -248,7 +254,20 @@ export function libsSourceConfig(projectId?: string): LibsSource | null {
? CDN_LIBS_MANIFEST_URL
? cdnLibsSource(CDN_LIBS_MANIFEST_URL)
: staticLibsSource() // misconfigured cdn ⇒ offline fallback
: remoteLibsSource(API_BASE_URL, currentScope(), userSlug(), project);
: kind === "synced"
? // Remote listing + per-lib sync stacks (IDB cache, realtime,
// editor reload on peer edits) — see syncedScopeLibsSource.
syncedScopeLibsSource(
remoteLibsSource(API_BASE_URL, currentScope(), userSlug(), project),
{
apiBase: API_BASE_URL,
scope: currentScope(),
user: userSlug(),
project,
log: (m) => console.log(m),
},
)
: remoteLibsSource(API_BASE_URL, currentScope(), userSlug(), project);
// 0004-A spike: `?libwrite=1` adds one in-memory writable user SYMBOL lib so the
// editor save path works with no backend (a dev/test aid). The real remote