← Commit history

demo: the Library card explains its leftover window (show_library loads no part by design, so the editor keeps whatever was open - a stale ADOM_MECHANICAL_PIN read as if the card had opened it), plus anonymous-first wiki fetch with a wiki_fetch fallback for private parts

John Lauer ·c567ca33cc ·2mo ago ·parent efc69c4
1 file changed +39−3
web-control-demo.html+39−3
@@ -1445,8 +1445,44 @@ for (const w of mine) {     };   }   var PART = partFrom(PARTS[3]);            // IN-S42ATR: small, fast, known-good default-  function fetchPartText(f) { return fetch(PART.filesBase + f).then(function (r) { if (!r.ok) throw new Error("wiki fetch " + f + ": HTTP " + r.status); return r.text(); }); }-  function fetchPartBytes(f) { return fetch(PART.filesBase + f).then(function (r) { if (!r.ok) throw new Error("wiki fetch " + f + ": HTTP " + r.status); return r.arrayBuffer(); }); }+  // ANONYMOUS FIRST, then ask ab to fetch it as the signed-in user.+  //+  // The browser has no Adom session for wiki.adom.inc, so a part page that is+  // PRIVATE to the user simply 404s here - which is what made 3 of the 10 picker+  // parts fail with a mystery "blocked" until the anonymous-vs-authenticated+  // difference was spotted. ab IS signed in, so wiki_fetch (ab 2.0.74) can read+  // it on the page's behalf.+  //+  // Anonymous stays the DEFAULT deliberately: the credential is used only for the+  // reads that actually need it, and the fallback pops the normal consent prompt+  // naming the URL, so nothing reads your private wiki without you saying yes.+  function wikiFetch(f, asBytes) {+    var url = PART.filesBase + f;+    return fetch(url).then(function (r) {+      if (r.ok) return asBytes ? r.arrayBuffer() : r.text();+      if (r.status !== 404 && r.status !== 403) throw new Error("wiki fetch " + f + ": HTTP " + r.status);+      // Private to this user: ask ab, which is signed in.+      return postSelf("wiki_fetch", { url: url }).then(function (res) {+        var j = res.j || {};+        if (!(res.s === 200 && j.success && j.base64)) {+          throw new Error("wiki fetch " + f + ": HTTP " + r.status + " anonymously" ++            (j.error ? ", and signed-in fetch said: " + j.error : "") );+        }+        var bin = atob(j.base64);+        if (!asBytes) {+          // base64 -> UTF-8 text+          var bytes = new Uint8Array(bin.length);+          for (var i = 0; i < bin.length; i++) bytes[i] = bin.charCodeAt(i);+          return new TextDecoder("utf-8").decode(bytes);+        }+        var buf = new ArrayBuffer(bin.length), view = new Uint8Array(buf);+        for (var k = 0; k < bin.length; k++) view[k] = bin.charCodeAt(k);+        return buf;+      });+    });+  }+  function fetchPartText(f) { return wikiFetch(f, false); }+  function fetchPartBytes(f) { return wikiFetch(f, true); }   function b64Text(s) { return btoa(unescape(encodeURIComponent(s))); }   function b64Bytes(buf) {     var u8 = new Uint8Array(buf), out = "", CH = 0x8000;@@ -1589,7 +1625,7 @@ for (const w of mine) {     { label: function () { return "Symbol (" + PART.name + ")"; }, cmd: "kicad_show_symbol", args: function () { return { symbolName: PART.kicadSymbolName || PART.name, libraryName: PART.kicadLib }; }, stage: stageKicadPart, pick: "symbol editor", note: "installs the part from its wiki page, then shows JUST the symbol" },     { label: function () { return "Footprint (" + PART.name + ")"; }, cmd: "kicad_show_footprint", args: function () { return { footprintName: PART.name, library: PART.kicadLib }; }, stage: stageKicadPart, pick: "footprint editor", note: "just the land pattern: pads + courtyard" },     { label: function () { return "3D chip (" + PART.name + ")"; }, cmd: "kicad_show_3d_chip", args: function () { return { footprintName: PART.name, library: PART.kicadLib }; }, stage: stageKicadPart, pick: "3d viewer", note: "the part's STEP model on its footprint" },-    { label: function () { return "Library (" + PART.name + " in '" + PART.kicadLib + "')"; }, cmd: "kicad_show_library", args: function () { return { libraryName: PART.kicadLib }; }, stage: stageKicadPart, pick: "symbol editor", note: "the library holding the symbol + footprint + 3D model" },+    { label: function () { return "Library (" + PART.name + " in '" + PART.kicadLib + "')"; }, cmd: "kicad_show_library", args: function () { return { libraryName: PART.kicadLib }; }, stage: stageKicadPart, pick: "symbol editor", note: "browses the library TREE - by design this verb loads NO part (kicad_show_library: \"no part loaded\"), so the editor window keeps showing whichever symbol was already open. A leftover name in the shot below is that, not this part." },     { label: function () { return "Schematic (just the " + PART.name + ")"; }, cmd: "kicad_show_schematic", args: function () { return { filePath: (PART.kicadProject || {}).schPath }; }, stage: stageKicadProject, pick: "schematic editor", note: "the generated single-component schematic (kicad_make_part_project)" },     { label: "2D board (part placed, tight edge cuts)", cmd: "kicad_show_2d_board", args: function () { return { filePath: (PART.kicadProject || {}).pcbPath }; }, stage: stageKicadProject, pick: "pcb editor", note: "the part-dominant board" },     { label: "3D board (real 3D body on the board)", cmd: "kicad_show_3d_board", args: function () { return { filePath: (PART.kicadProject || {}).pcbPath }; }, stage: stageKicadProject, pick: "3d viewer", note: "the populated board in 3D - the whole ladder underneath it" },