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
2026-07-09 18:21:21 +02:00
|
|
|
/*
|
|
|
|
|
* JS → editor library reload (r2-idb-sync realtime): drop a PCBJAM lib's
|
|
|
|
|
* in-plugin cache and re-sync the open editor's library tree after a remote
|
|
|
|
|
* (peer) edit landed in the page's SyncStack/IDB.
|
|
|
|
|
*
|
|
|
|
|
* The lib plugins (SCH_IO_PCBJAM_LIB / PCB_IO_PCBJAM_FP) cache parsed items for
|
|
|
|
|
* the plugin instance's lifetime and pin GetModifyHash()/GetLibraryTimestamp()
|
|
|
|
|
* to a constant, so nothing upstream ever re-reads the provider. The one full
|
|
|
|
|
* invalidation is LIBRARY_MANAGER::ReloadLibraryEntry — it erases the LIB_DATA
|
|
|
|
|
* entry INCLUDING the plugin instance (and with it the fat-load cache), the
|
|
|
|
|
* exact pattern the remote-symbol import flows already use
|
|
|
|
|
* (eeschema/widgets/panel_remote_symbol.cpp). LoadLibraryEntry then refetches
|
|
|
|
|
* synchronously (the fat "bodies" crossing — served from the now-fresh IDB, no
|
|
|
|
|
* network), and MAIL_RELOAD_LIB makes an open editor frame rebuild its tree.
|
|
|
|
|
*
|
|
|
|
|
* Header-only (the collab_common.h pattern); common-code includes only, so the
|
|
|
|
|
* merged kicad_editor TU (deliberately eeschema/pcbnew-header-free) can use it.
|
jspi cleanup: remove the asyncify-era residue — dead code, conditionals, pipeline scaffolding, stale prose
The runtime is JSPI-only; this removes everything that still pretended
otherwise. Three exhaustive sweeps (C++/JS+build+CI/tests+docs) drove
the inventory; every deletion verified by grep closure + full gates.
Broken-right-now fixes:
- deploy-staging.yml passed the retired opt_level input — the workflow
could not even start. Removed.
- env.sh carried dead exports with a live -sASYNCIFY=1 inside
(WASM_LDFLAGS/PTHREAD_LDFLAGS, zero consumers). Removed; the
WASM_LEGACY_EXCEPTIONS rationale rewritten to the real reason.
- docker/build.sh exported PCBJAM_ASYNC_BACKEND (read nowhere). Gone.
Dead weight removed:
- binaryen submodule (nothing builds or invokes it), wasm-opt-bench
workflow + scripts/bench/, get-wasm-opt.sh, diagnostics.js (242 lines
of Asyncify-API-only code), the KICAD_PIPELINE background-postprocess
scaffolding (existed to parallelize the deleted wasm-opt phase; the
postprocess is a seconds-long node script and now runs inline),
build-monitor's dead asyncify rows, sched-context orphan build
output, dead .gitignore entries, the .jspi-assets spike dir (the two
wf-result research JSONs moved to docs/features/async/migration-evidence/).
- bindings: fiber_park.h + its 12 embind registrations (broken-if-
called under JSPI), the kicadOpenFileStart/OPEN_JOB starter route,
main_stack_runner.h + 5 includes, the always-null context-sleep weak
hook in nanosleep_yield.c.
- shim: the backend field (installed-flag idempotency instead),
noteContextWait (dead both sides), the __wxAsyncifyDump alias (+ the
WasmTool fallback and string-dump normalize branch).
- web: the emscripten-6-ignored mainScriptUrlOrBlob option in boot.ts
(gerber-demo keeps it: it loads the deployed CDN release, which
predates emscripten 6 — noted inline).
Conditionals: all 'backend === jspi' checks reduced to scheduler-
presence checks; races_quiescent re-keyed from Asyncify.state (vacuous)
to real backlog quiescence (resumeReady/mutatorQueue — NOT _windowLive,
which is the probing activation's own window by definition).
Renames (identifiers only, no file renames): ASYNC_LINK_FLAGS→
JSPI_LINK_FLAGS and Makefile ASYNC_LDFLAGS→JSPI_LDFLAGS,
kicadCollabFiberBusy→kicadCollabBusy (embind + web + tests),
collab_common.h fiber*→apply*/coroutine naming, asyncifySignatures→
wasmTrapSignatures (lists byte-identical).
Tests: the two remaining vacuous [wx-asyncify]/fiber-resume-refused
asserts re-keyed to live JSPI beacons; eeschema-load's failure message
no longer sends the developer to a deleted script; wait-beacons' dead
families/parser deleted; lane-0 legacy-glue guards removed (lane 0 is
unconstructible); the embind test.fail re-gated with the JSPI reason
(plain embind invokers cannot suspend — verified still failing);
lint-determinism now scans tests/jspi (166 files clean);
eeschema-collab local-move gated to chromium (~50% flaky on FF even
solo; pcbnew twin covers both engines).
Docs: DEBUG.md rewritten as the JSPI debugging guide; build.md
describes the single-phase build; docs/features/async/README.md
banner-marked historical and repointed at the NEW
23-jspi-runtime.md (current architecture: export census, turnstile,
libcontext ownership + refusal contract, embind call shapes, the
em-pthread service-wrapper trick, exception policy, known gaps).
Gates on the cleaned tree: test:e2e 725 passed / 0 failed (after the
quiescence-probe fix; the 3 other reds were verified contention flakes
solo-green or the documented FF gate), web 76/0, jspi 18/18 both
engines, vitest 295/295 + 17/17, all lints green, live-app census
clean.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016X9eh1s5sTx1o9Em9KBuwR
2026-08-14 09:25:32 +02:00
|
|
|
* Runs on the apply coroutine: LoadLibraryEntry suspends in the JS bridge, so
|
|
|
|
|
* the reload must serialize with the collab applies and local edits.
|
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
2026-07-09 18:21:21 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
#ifdef __EMSCRIPTEN__
|
|
|
|
|
|
|
|
|
|
#include <string>
|
|
|
|
|
#include <wx/app.h>
|
|
|
|
|
#include <wx/string.h>
|
|
|
|
|
#include <kiway.h>
|
|
|
|
|
#include <kiway_player.h>
|
|
|
|
|
#include <libraries/library_manager.h>
|
2026-08-19 13:47:13 +02:00
|
|
|
#include <libraries/library_table.h>
|
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
2026-07-09 18:21:21 +02:00
|
|
|
#include <mail_type.h>
|
|
|
|
|
#include <pgm_base.h>
|
|
|
|
|
|
|
|
|
|
#include "collab_common.h"
|
|
|
|
|
|
|
|
|
|
namespace pcbjam_libs {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Reload one library from its provider and refresh any open editor tree.
|
|
|
|
|
* @param aKind "symbol" | "footprint" — which lib table the nickname lives in.
|
|
|
|
|
* @param aNickname the lib-table row name (LibInfo.name on the JS side).
|
|
|
|
|
*/
|
|
|
|
|
inline void reloadLibrary( std::string aKind, std::string aNickname )
|
|
|
|
|
{
|
|
|
|
|
KIWAY_PLAYER* top =
|
|
|
|
|
wxTheApp ? dynamic_cast<KIWAY_PLAYER*>( wxTheApp->GetTopWindow() ) : nullptr;
|
|
|
|
|
|
|
|
|
|
if( !top )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
const bool fp = aKind == "footprint";
|
|
|
|
|
const wxString nick = wxString::FromUTF8( aNickname.c_str() );
|
|
|
|
|
|
jspi cleanup: remove the asyncify-era residue — dead code, conditionals, pipeline scaffolding, stale prose
The runtime is JSPI-only; this removes everything that still pretended
otherwise. Three exhaustive sweeps (C++/JS+build+CI/tests+docs) drove
the inventory; every deletion verified by grep closure + full gates.
Broken-right-now fixes:
- deploy-staging.yml passed the retired opt_level input — the workflow
could not even start. Removed.
- env.sh carried dead exports with a live -sASYNCIFY=1 inside
(WASM_LDFLAGS/PTHREAD_LDFLAGS, zero consumers). Removed; the
WASM_LEGACY_EXCEPTIONS rationale rewritten to the real reason.
- docker/build.sh exported PCBJAM_ASYNC_BACKEND (read nowhere). Gone.
Dead weight removed:
- binaryen submodule (nothing builds or invokes it), wasm-opt-bench
workflow + scripts/bench/, get-wasm-opt.sh, diagnostics.js (242 lines
of Asyncify-API-only code), the KICAD_PIPELINE background-postprocess
scaffolding (existed to parallelize the deleted wasm-opt phase; the
postprocess is a seconds-long node script and now runs inline),
build-monitor's dead asyncify rows, sched-context orphan build
output, dead .gitignore entries, the .jspi-assets spike dir (the two
wf-result research JSONs moved to docs/features/async/migration-evidence/).
- bindings: fiber_park.h + its 12 embind registrations (broken-if-
called under JSPI), the kicadOpenFileStart/OPEN_JOB starter route,
main_stack_runner.h + 5 includes, the always-null context-sleep weak
hook in nanosleep_yield.c.
- shim: the backend field (installed-flag idempotency instead),
noteContextWait (dead both sides), the __wxAsyncifyDump alias (+ the
WasmTool fallback and string-dump normalize branch).
- web: the emscripten-6-ignored mainScriptUrlOrBlob option in boot.ts
(gerber-demo keeps it: it loads the deployed CDN release, which
predates emscripten 6 — noted inline).
Conditionals: all 'backend === jspi' checks reduced to scheduler-
presence checks; races_quiescent re-keyed from Asyncify.state (vacuous)
to real backlog quiescence (resumeReady/mutatorQueue — NOT _windowLive,
which is the probing activation's own window by definition).
Renames (identifiers only, no file renames): ASYNC_LINK_FLAGS→
JSPI_LINK_FLAGS and Makefile ASYNC_LDFLAGS→JSPI_LDFLAGS,
kicadCollabFiberBusy→kicadCollabBusy (embind + web + tests),
collab_common.h fiber*→apply*/coroutine naming, asyncifySignatures→
wasmTrapSignatures (lists byte-identical).
Tests: the two remaining vacuous [wx-asyncify]/fiber-resume-refused
asserts re-keyed to live JSPI beacons; eeschema-load's failure message
no longer sends the developer to a deleted script; wait-beacons' dead
families/parser deleted; lane-0 legacy-glue guards removed (lane 0 is
unconstructible); the embind test.fail re-gated with the JSPI reason
(plain embind invokers cannot suspend — verified still failing);
lint-determinism now scans tests/jspi (166 files clean);
eeschema-collab local-move gated to chromium (~50% flaky on FF even
solo; pcbnew twin covers both engines).
Docs: DEBUG.md rewritten as the JSPI debugging guide; build.md
describes the single-phase build; docs/features/async/README.md
banner-marked historical and repointed at the NEW
23-jspi-runtime.md (current architecture: export census, turnstile,
libcontext ownership + refusal contract, embind call shapes, the
em-pthread service-wrapper trick, exception policy, known gaps).
Gates on the cleaned tree: test:e2e 725 passed / 0 failed (after the
quiescence-probe fix; the 3 other reds were verified contention flakes
solo-green or the documented FF gate), web 76/0, jspi 18/18 both
engines, vitest 295/295 + 17/17, all lints green, live-app census
clean.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016X9eh1s5sTx1o9Em9KBuwR
2026-08-14 09:25:32 +02:00
|
|
|
pcbjam_collab::runOnCoroutine( top, [top, fp, nick]()
|
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
2026-07-09 18:21:21 +02:00
|
|
|
{
|
|
|
|
|
LIBRARY_MANAGER& mgr = Pgm().GetLibraryManager();
|
|
|
|
|
const LIBRARY_TABLE_TYPE type =
|
|
|
|
|
fp ? LIBRARY_TABLE_TYPE::FOOTPRINT : LIBRARY_TABLE_TYPE::SYMBOL;
|
|
|
|
|
|
|
|
|
|
// Drop the LIB_DATA entry (plugin instance + its fat-load cache)…
|
|
|
|
|
mgr.ReloadLibraryEntry( type, nick );
|
|
|
|
|
// …and bring the lib back to LOADED synchronously, so the tree sync
|
|
|
|
|
// below reads fresh items instead of re-listing a LOADING stub.
|
|
|
|
|
mgr.LoadLibraryEntry( type, nick );
|
|
|
|
|
|
|
|
|
|
// An open editor frame re-syncs its tree from the (now fresh) adapter.
|
|
|
|
|
// The payload names the lib to FORCE-refresh: the symbol tree gates
|
|
|
|
|
// re-enumeration on a modify hash that is a pinned constant for PCBJAM
|
|
|
|
|
// plugins (and its mtime component never moves for a remote edit), so a
|
|
|
|
|
// plain sync would skip the lib; the named node is rebuilt instead.
|
|
|
|
|
// ExpressMail only delivers to frames that exist — no frame is created.
|
|
|
|
|
std::string payload( nick.utf8_str() );
|
|
|
|
|
top->Kiway().ExpressMail( fp ? FRAME_FOOTPRINT_EDITOR : FRAME_SCH_SYMBOL_EDITOR,
|
|
|
|
|
MAIL_RELOAD_LIB, payload );
|
|
|
|
|
} );
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-26 13:29:29 +02:00
|
|
|
/**
|
|
|
|
|
* Cheap counterpart of reloadLibrary (libs 0019): drop the lib's LIB_DATA
|
|
|
|
|
* entry (plugin instance + parsed cache) so the NEXT access re-reads the
|
|
|
|
|
* provider — no eager LoadLibraryEntry fat-load, no tree mail. A remote edit
|
|
|
|
|
* calls this; the fat-load happens lazily when the user looks at the lib,
|
|
|
|
|
* or explicitly through reloadLibrary from "Update from library".
|
|
|
|
|
* (pcbnew's FOOTPRINT_LIBRARY_ADAPTER::PreloadedFootprints is invalidated by
|
|
|
|
|
* the pcbnew-side caller — this header stays common-code only.)
|
|
|
|
|
*/
|
|
|
|
|
inline void invalidateLibrary( std::string aKind, std::string aNickname )
|
|
|
|
|
{
|
|
|
|
|
KIWAY_PLAYER* top =
|
|
|
|
|
wxTheApp ? dynamic_cast<KIWAY_PLAYER*>( wxTheApp->GetTopWindow() ) : nullptr;
|
|
|
|
|
|
|
|
|
|
if( !top )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
const bool fp = aKind == "footprint";
|
|
|
|
|
const wxString nick = wxString::FromUTF8( aNickname.c_str() );
|
|
|
|
|
|
|
|
|
|
pcbjam_collab::runOnCoroutine( top, [fp, nick]()
|
|
|
|
|
{
|
|
|
|
|
Pgm().GetLibraryManager().ReloadLibraryEntry(
|
|
|
|
|
fp ? LIBRARY_TABLE_TYPE::FOOTPRINT : LIBRARY_TABLE_TYPE::SYMBOL, nick );
|
|
|
|
|
} );
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-19 13:47:13 +02:00
|
|
|
/**
|
|
|
|
|
* Add one PCBJAM lib-table row at RUNTIME and load it — the lib SET is
|
|
|
|
|
* otherwise frozen at boot (sym/fp-lib-table are written once in preRun).
|
|
|
|
|
* Used by the "a new team library appeared" flow: the JS side has already
|
|
|
|
|
* created the `/mnt/pcbjam/<id>` MEMFS placeholder; this inserts the row into
|
|
|
|
|
* the LIVE in-memory global table (the table FILE is only re-read by
|
|
|
|
|
* LoadGlobalTables, which would drop every adapter cache — deliberately not
|
|
|
|
|
* used), loads the entry through the provider bridge, and re-syncs any open
|
|
|
|
|
* editor tree. Idempotent: an existing nickname is a no-op.
|
|
|
|
|
*
|
|
|
|
|
* @param aKind "symbol" | "footprint" — which lib table gets the row.
|
|
|
|
|
* @param aNickname the lib-table row name (LibInfo.name on the JS side).
|
|
|
|
|
* @param aUri the virtual mount uri ("/mnt/pcbjam/<libId>").
|
|
|
|
|
*/
|
|
|
|
|
inline void addLibraryEntry( std::string aKind, std::string aNickname, std::string aUri )
|
|
|
|
|
{
|
|
|
|
|
KIWAY_PLAYER* top =
|
|
|
|
|
wxTheApp ? dynamic_cast<KIWAY_PLAYER*>( wxTheApp->GetTopWindow() ) : nullptr;
|
|
|
|
|
|
|
|
|
|
if( !top )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
const bool fp = aKind == "footprint";
|
|
|
|
|
const wxString nick = wxString::FromUTF8( aNickname.c_str() );
|
|
|
|
|
const wxString uri = wxString::FromUTF8( aUri.c_str() );
|
|
|
|
|
|
|
|
|
|
pcbjam_collab::runOnCoroutine( top, [top, fp, nick, uri]()
|
|
|
|
|
{
|
|
|
|
|
LIBRARY_MANAGER& mgr = Pgm().GetLibraryManager();
|
|
|
|
|
const LIBRARY_TABLE_TYPE type =
|
|
|
|
|
fp ? LIBRARY_TABLE_TYPE::FOOTPRINT : LIBRARY_TABLE_TYPE::SYMBOL;
|
|
|
|
|
|
|
|
|
|
if( std::optional<LIBRARY_MANAGER_ADAPTER*> adapter = mgr.Adapter( type ); adapter )
|
|
|
|
|
{
|
|
|
|
|
LIBRARY_TABLE* table = ( *adapter )->GlobalTable();
|
|
|
|
|
|
|
|
|
|
if( !table )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
// Idempotent-cheap: a nickname that already has a row is done —
|
|
|
|
|
// content refresh is kicadLibsReload's job, and doing it here
|
|
|
|
|
// would let a re-announce trigger a pointless re-fat-load.
|
|
|
|
|
if( table->HasRow( nick ) )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
LIBRARY_TABLE_ROW& row = table->InsertRow();
|
|
|
|
|
row.SetNickname( nick );
|
|
|
|
|
row.SetURI( uri );
|
|
|
|
|
row.SetType( fp ? wxS( "PCBJAM_FP" ) : wxS( "PCBJAM" ) );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Bring the new row to LOADED through the JS provider bridge (GetRow
|
|
|
|
|
// walks the table on a cache miss, so the inserted row is found).
|
|
|
|
|
mgr.LoadLibraryEntry( type, nick );
|
|
|
|
|
|
|
|
|
|
// Open editor frames re-sync their tree; the nickname payload forces
|
|
|
|
|
// the named node's rebuild past the pinned-modify-hash gate (same
|
|
|
|
|
// reasoning as reloadLibrary above).
|
|
|
|
|
std::string payload( nick.utf8_str() );
|
|
|
|
|
top->Kiway().ExpressMail( fp ? FRAME_FOOTPRINT_EDITOR : FRAME_SCH_SYMBOL_EDITOR,
|
|
|
|
|
MAIL_RELOAD_LIB, payload );
|
|
|
|
|
} );
|
|
|
|
|
}
|
|
|
|
|
|
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
2026-07-09 18:21:21 +02:00
|
|
|
} // namespace pcbjam_libs
|
|
|
|
|
|
|
|
|
|
#endif // __EMSCRIPTEN__
|