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
81 lines
3.3 KiB
C++
81 lines
3.3 KiB
C++
/*
|
|
* 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.
|
|
* Runs on the fiber stack: LoadLibraryEntry Asyncify-suspends in the JS bridge,
|
|
* and the tree sync dispatches GAL/tree virtuals that trap off-fiber.
|
|
*/
|
|
|
|
#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>
|
|
#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() );
|
|
|
|
pcbjam_collab::runOnFiber( top, [top, fp, nick]()
|
|
{
|
|
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 );
|
|
} );
|
|
}
|
|
|
|
} // namespace pcbjam_libs
|
|
|
|
#endif // __EMSCRIPTEN__
|