CMMS fork: Phase 6 polish — schema.html light theme + load-time IndexedDB wipe

- cmms-bridge.js: wipeProjectData() clears the project object stores (devices,
  boards, components, images, overlappedImages, nets, schemas, schemaComponents
  — not the KiCad symbol library) and resets studio.js's shared globals before
  the CMMS attachment ZIP is imported. The ZIP is the single source of truth for
  a CMMS board, so restoreDevice()'s merge path (which only de-dupes on a newer
  meta.lastModified, absent on CMMS-created boards) no longer accretes duplicate
  image/net rows across repeated opens. init() also stamps data-theme=light as
  well as =dark. All gated on PCBRETRACE_CONFIG — standalone untouched.
- schema.html: inline head script mirrors ?theme=light|dark (passed by studio.js
  on the iframe src) onto <html> and, for light, injects cmms-schema-light.css.
  Full no-op with no ?theme=.
- cmms-schema-light.css (new): [data-theme="light"]-gated override of
  schema.html's :root palette for the CMMS light theme. Canvas stays dark.
- studio.js: append ?theme=<active> to the schema.html iframe src.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Stuart 2026-09-09 22:08:45 +10:00
commit eeb2af1e15
4 changed files with 84 additions and 2 deletions

View file

@ -350,10 +350,45 @@
trace('ensureBoard: created a starter board');
}
// Working-data stores restoreDevice() / processImportData() write into. The
// KiCad symbol-library stores (kicadSymbols, symbolTypes, componentTypes*,
// pinDirections) are reference data and expensive to rebuild — leave them.
const CMMS_PROJECT_STORES = ['devices', 'boards', 'components', 'images',
'overlappedImages', 'nets', 'schemas', 'schemaComponents'];
// The .pcbretrace.zip attachment is the single source of truth for a CMMS
// board — there is no local working copy to preserve between sessions. Clear
// the project stores before importing so restoreDevice() starts from empty
// and can't accrete duplicate image / net rows across repeated opens in the
// same browser (its merge path only de-dupes when timestamps say the import
// is newer, and CMMS-created boards carry no lastModified).
async function wipeProjectData() {
if (!db || !db.db) return;
const stores = CMMS_PROJECT_STORES.filter(s => db.db.objectStoreNames.contains(s));
if (stores.length) {
await new Promise((res, rej) => {
const tx = db.db.transaction(stores, 'readwrite');
stores.forEach(s => tx.objectStore(s).clear());
tx.oncomplete = () => res();
tx.onerror = () => rej(tx.error);
tx.onabort = () => rej(tx.error || new Error('wipe aborted'));
});
}
// studio.js caches these in shared globals — reset so a fresh import (or
// ensureBoard) doesn't reuse a now-deleted device/board.
deviceList = []; bomList = []; bomData = []; bomImages = [];
currentDeviceId = null; currentBomId = null; currentImgId = null;
trace('wipeProjectData: cleared', stores.join(', ') || '(none)');
}
async function init() {
if (CFG.dark) document.documentElement.setAttribute('data-theme', 'dark');
// Set light explicitly too (not just dark) so studio.js can tell a CMMS
// embed from standalone use and pass the theme to the schema.html iframe.
document.documentElement.setAttribute('data-theme', CFG.dark ? 'dark' : 'light');
injectControls();
try { await wipeProjectData(); } catch (e) { trace('wipeProjectData threw:', e && e.message); }
if (CFG.loadUrl) {
status('Loading board…');
try {

View file

@ -0,0 +1,40 @@
/*
* CMMS light theme for pcb-retrace schema.html (the "Schema ReTrace" iframe).
*
* NOT part of the fork. schema.html is dark-only upstream, which clashes when
* the CMMS is in light mode. studio.js appends ?theme=light|dark to the iframe
* src (from the CMMS-set data-theme on the parent document); an inline script
* in schema.html mirrors it onto <html data-theme>. Every rule here is gated on
* [data-theme="light"] so standalone use and CMMS dark mode are untouched.
*
* The schematic canvas (#sch-canvas, painted by schema/draw.js with hardcoded
* colours) deliberately stays dark — it reads as a drawing surface, like an EDA
* canvas, not UI chrome. Only the surrounding panels/header/modals are themed.
*/
:root[data-theme="light"] {
--bg: #ffffff;
--surface: #f6f8fa;
--surface2: #eaeef2;
--border: #d0d7de;
--accent: #0a7d5f;
--accent2: #0969da;
--accent3: #cf400b;
--warn: #9a6700;
--text: #1f2328;
--text2: #656d76;
}
/* Canvas overlays hardcode the dark page bg — flip to a light scrim. */
[data-theme="light"] #coord-readout,
[data-theme="light"] #zoom-ind { background: rgba(255,255,255,.82); }
[data-theme="light"] #hint-bar { background: rgba(255,255,255,.9); color: var(--text2); }
/* Mobile drawer / toolbar shadows are tuned for a dark bg. */
[data-theme="light"] #left-panel { box-shadow: 4px 0 15px rgba(140,149,159,.35); }
[data-theme="light"] #right-panel { box-shadow: -4px 0 15px rgba(140,149,159,.35); }
[data-theme="light"] #canvas-toolbar .btn { box-shadow: 0 2px 8px rgba(140,149,159,.35); }
/* Selection tints read as near-invisible on white — lift them slightly. */
[data-theme="light"] .net-item.selected,
[data-theme="light"] .db-item.selected { background: rgba(10,125,95,.12); }
[data-theme="light"] .comp-item.selected { background: rgba(9,105,218,.12); }

View file

@ -9,6 +9,10 @@
<head>
<!-- CMMS fork: Google Tag / analytics removed (no external requests) -->
<meta charset="UTF-8">
<!-- CMMS fork: mirror the parent's ?theme= onto <html> before paint and, for
light, pull in the CMMS override sheet. Fully no-op standalone (no ?theme=),
so vanilla schema.html keeps its dark-only look with no dangling asset. -->
<script>try{var t=new URLSearchParams(location.search).get('theme');if(t==='light'||t==='dark'){document.documentElement.setAttribute('data-theme',t);if(t==='light'){var l=document.createElement('link');l.rel='stylesheet';l.href='cmms-schema-light.css';document.head.appendChild(l);}}}catch(e){}</script>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Schematic ReTrace</title>
<script src="vendor/zip.min.js"></script>

View file

@ -1528,7 +1528,10 @@ function switchView(v) {
// 'contentWindow.location:', frame.contentWindow?.location?.href);
frame.contentWindow.postMessage(msg, '*');
};
frame.src = 'schema.html';
// CMMS fork: hand the schema iframe the active theme so its
// light-mode override sheet can match the CMMS (no-op standalone).
const _t = document.documentElement.getAttribute('data-theme');
frame.src = 'schema.html' + (_t ? '?theme=' + encodeURIComponent(_t) : '');
// console.log('[studio] frame clientWidth:', frame.clientWidth,
// 'clientHeight:', frame.clientHeight,
// 'offsetWidth:', frame.offsetWidth,