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

@ -59,6 +59,7 @@
#include "collab_common.h"
#include "collab_presence_core.h"
#include "collab_presence_style.h"
#include "pcbjam_libs_reload.h"
#include <algorithm>
using namespace emscripten;
@ -1195,6 +1196,38 @@ std::string schCollabTestMoveFirst( int aDx, int aDy )
}
// How many placed instances of a library symbol the open schematic holds —
// the JS lib-sync bridge asks after a remote lib update so the editor chrome
// can warn "a symbol you are using changed" (placed SCH_SYMBOLs keep their
// embedded copy across a lib reload, so the user must update explicitly).
// Counts across all unique screens of the hierarchy; 0 without a schematic
// frame (symbol editor / viewer sessions).
int schLibsSymbolUsage( std::string aLibNickname, std::string aSymbolName )
{
SCH_EDIT_FRAME* fr = schFrame();
if( !fr )
return 0;
const LIB_ID target( wxString::FromUTF8( aLibNickname.c_str() ),
wxString::FromUTF8( aSymbolName.c_str() ) );
int count = 0;
SCH_SCREENS screens( fr->Schematic().Root() );
for( SCH_SCREEN* screen = screens.GetFirst(); screen; screen = screens.GetNext() )
{
for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
{
if( static_cast<SCH_SYMBOL*>( item )->GetLibId() == target )
count++;
}
}
return count;
}
// Test helper: read an item's position by uuid as "x,y" (internal units).
std::string schCollabGetPos( std::string aId )
{
@ -1715,6 +1748,11 @@ EMSCRIPTEN_BINDINGS(eeschema) {
function("kicadCollabTestSelectFirst", &schCollabTestSelectFirst);
function("kicadCollabTestSelectComponent", &schCollabTestSelectComponent);
function("kicadCollabTestClearSelection", &schCollabTestClearSelection);
// Library reload after a remote (synced) lib edit — r2-idb-sync realtime.
function("kicadLibsReload", &pcbjam_libs::reloadLibrary);
// Placed-instance count for a library symbol (drives the "a symbol you are
// using was updated" toast after a remote lib edit).
function("kicadLibsSymbolUsage", &schLibsSymbolUsage);
#endif // !KICAD_MERGED_EMBIND
}
#endif