@kopikocappu/mycelium 0.2.3 → 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +271 -29
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -16030,8 +16030,52 @@ var EMBEDDED_VIEWER = `<!DOCTYPE html>
|
|
|
16030
16030
|
flex-direction: column;
|
|
16031
16031
|
z-index: 10;
|
|
16032
16032
|
overflow: hidden;
|
|
16033
|
+
position: relative;
|
|
16033
16034
|
}
|
|
16034
16035
|
|
|
16036
|
+
.sidebar-tab {
|
|
16037
|
+
flex: 1;
|
|
16038
|
+
padding: 8px 4px;
|
|
16039
|
+
background: none;
|
|
16040
|
+
border: none;
|
|
16041
|
+
border-bottom: 2px solid transparent;
|
|
16042
|
+
color: var(--text-dim);
|
|
16043
|
+
cursor: pointer;
|
|
16044
|
+
font-family: inherit;
|
|
16045
|
+
font-size: 11px;
|
|
16046
|
+
letter-spacing: 0.05em;
|
|
16047
|
+
transition: color 0.15s, border-color 0.15s;
|
|
16048
|
+
}
|
|
16049
|
+
.sidebar-tab:hover { color: var(--text); }
|
|
16050
|
+
.sidebar-tab.active { color: var(--text); border-bottom-color: var(--accent); }
|
|
16051
|
+
|
|
16052
|
+
.tab-content { display: flex; flex-direction: column; flex: 1; overflow: hidden; }
|
|
16053
|
+
|
|
16054
|
+
/* \u2500\u2500 History items \u2500\u2500 */
|
|
16055
|
+
.history-item {
|
|
16056
|
+
padding: 10px 12px;
|
|
16057
|
+
border-bottom: 1px solid var(--border);
|
|
16058
|
+
font-size: 11px;
|
|
16059
|
+
}
|
|
16060
|
+
.history-item:hover { background: rgba(255,255,255,0.02); }
|
|
16061
|
+
.history-file { color: var(--text); margin-bottom: 3px; font-family: 'SF Mono', monospace; }
|
|
16062
|
+
.history-meta { color: var(--text-dim); display: flex; gap: 8px; flex-wrap: wrap; }
|
|
16063
|
+
.history-task { color: var(--accent2); }
|
|
16064
|
+
.history-agent { color: var(--accent3); }
|
|
16065
|
+
|
|
16066
|
+
/* \u2500\u2500 Ignore list items \u2500\u2500 */
|
|
16067
|
+
.ignore-item {
|
|
16068
|
+
display: flex; align-items: center; justify-content: space-between;
|
|
16069
|
+
padding: 4px 0; gap: 8px;
|
|
16070
|
+
}
|
|
16071
|
+
.ignore-item:hover { background: rgba(255,255,255,0.03); }
|
|
16072
|
+
.ignore-pattern { font-size: 11px; color: var(--text); flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-family: 'SF Mono', monospace; }
|
|
16073
|
+
.ignore-pattern.removed { color: var(--text-dim); text-decoration: line-through; }
|
|
16074
|
+
.ignore-pattern.custom { color: #6B8AFF; }
|
|
16075
|
+
.ignore-btn { background: none; border: 1px solid var(--border); color: var(--text-dim); cursor: pointer; font-family: inherit; font-size: 10px; padding: 2px 7px; flex-shrink: 0; }
|
|
16076
|
+
.ignore-btn:hover { color: var(--text); }
|
|
16077
|
+
.ignore-btn.danger:hover { color: #F28B82; border-color: #F28B82; }
|
|
16078
|
+
|
|
16035
16079
|
#sidebar-header {
|
|
16036
16080
|
padding: 16px;
|
|
16037
16081
|
border-bottom: 1px solid var(--border);
|
|
@@ -16608,12 +16652,12 @@ var EMBEDDED_VIEWER = `<!DOCTYPE html>
|
|
|
16608
16652
|
|
|
16609
16653
|
.link {
|
|
16610
16654
|
fill: none;
|
|
16611
|
-
stroke:
|
|
16612
|
-
stroke-opacity: 0.
|
|
16655
|
+
stroke: #4a8fff;
|
|
16656
|
+
stroke-opacity: 0.6;
|
|
16613
16657
|
}
|
|
16614
16658
|
|
|
16615
|
-
.link.imports-edge { stroke:
|
|
16616
|
-
.link.calls-edge { stroke:
|
|
16659
|
+
.link.imports-edge { stroke: #4a8fff; stroke-width: 1.5; stroke-opacity: 0.6; }
|
|
16660
|
+
.link.calls-edge { stroke: #f7916a; stroke-width: 1.5; stroke-dasharray: 5,4; stroke-opacity: 0.5; }
|
|
16617
16661
|
.link.contains-edge { stroke: #333344; stroke-width: 0.5; stroke-dasharray: 3,3; }
|
|
16618
16662
|
|
|
16619
16663
|
.link.highlighted { stroke-opacity: 1 !important; stroke-width: 3 !important; }
|
|
@@ -16639,41 +16683,136 @@ var EMBEDDED_VIEWER = `<!DOCTYPE html>
|
|
|
16639
16683
|
|
|
16640
16684
|
<!-- Sidebar -->
|
|
16641
16685
|
<div id="sidebar">
|
|
16642
|
-
<div id="sidebar-header">
|
|
16686
|
+
<div id="sidebar-header" style="display:flex;align-items:center;justify-content:space-between;padding:0 12px;">
|
|
16643
16687
|
<div class="logo">mycelium<span>.dev</span></div>
|
|
16688
|
+
<button id="settings-btn" title="Manage ignore list" style="background:none;border:1px solid var(--border);color:var(--text-dim);cursor:pointer;font-size:13px;padding:3px 8px;font-family:inherit;border-radius:3px;" onmouseenter="this.style.color='var(--text)'" onmouseleave="this.style.color='var(--text-dim)'">\u2699</button>
|
|
16644
16689
|
</div>
|
|
16645
|
-
|
|
16646
|
-
|
|
16647
|
-
|
|
16690
|
+
|
|
16691
|
+
<!-- Tab bar -->
|
|
16692
|
+
<div style="display:flex;border-bottom:1px solid var(--border);flex-shrink:0;">
|
|
16693
|
+
<button class="sidebar-tab active" id="tab-graph" onclick="switchTab('graph')">Graph</button>
|
|
16694
|
+
<button class="sidebar-tab" id="tab-history" onclick="switchTab('history')">History</button>
|
|
16695
|
+
<button class="sidebar-tab" id="tab-help" onclick="switchTab('help')">? Help</button>
|
|
16648
16696
|
</div>
|
|
16649
|
-
|
|
16650
|
-
|
|
16651
|
-
|
|
16652
|
-
|
|
16653
|
-
<
|
|
16654
|
-
<
|
|
16697
|
+
|
|
16698
|
+
<!-- GRAPH TAB -->
|
|
16699
|
+
<div id="tab-content-graph" class="tab-content">
|
|
16700
|
+
<div id="search-wrap">
|
|
16701
|
+
<span class="search-icon">\u2315</span>
|
|
16702
|
+
<input id="search" type="text" placeholder="Search files, functions, tags\u2026" autocomplete="off">
|
|
16655
16703
|
</div>
|
|
16656
|
-
<div
|
|
16657
|
-
<
|
|
16658
|
-
|
|
16659
|
-
<button class="toggle-btn active" id="
|
|
16660
|
-
<button class="toggle-btn" id="
|
|
16704
|
+
<div id="controls">
|
|
16705
|
+
<div class="control-row">
|
|
16706
|
+
<span>Edges:</span>
|
|
16707
|
+
<button class="toggle-btn active" id="toggle-imports" data-tip="Show/hide import edges Blue solid lines File A imports from File B">Imports</button>
|
|
16708
|
+
<button class="toggle-btn active" id="toggle-calls" data-tip="Show/hide call edges Orange dashed lines Function A calls Function B (needs codebase-memory-mcp)">Calls</button>
|
|
16709
|
+
<button class="toggle-btn" id="toggle-functions" data-tip="Show function nodes Symbols within each file Circles attached to parent file">Functions</button>
|
|
16710
|
+
</div>
|
|
16711
|
+
<div class="control-row">
|
|
16712
|
+
<span>Zoom level:</span>
|
|
16713
|
+
<div class="zoom-level-btns">
|
|
16714
|
+
<button class="toggle-btn active" id="zoom-files" data-tip="Files only (default) One dot = one file Best for codebase structure">Files</button>
|
|
16715
|
+
<button class="toggle-btn" id="zoom-symbols" data-tip="Show symbols Functions and classes appear orbiting their parent file">Symbols</button>
|
|
16716
|
+
</div>
|
|
16717
|
+
</div>
|
|
16718
|
+
<div class="control-row">
|
|
16719
|
+
<button class="toggle-btn" id="toggle-clusters" data-tip="Directory grouping Dashed outlines show which folder each node is in">Directory clusters</button>
|
|
16720
|
+
</div>
|
|
16721
|
+
</div>
|
|
16722
|
+
<div id="node-info">
|
|
16723
|
+
<div class="node-info-empty" style="line-height:1.8">Click any dot to see<br>what it imports, exports,<br>and connects to</div>
|
|
16724
|
+
</div>
|
|
16725
|
+
<div id="legend">
|
|
16726
|
+
<div id="dir-legend"></div>
|
|
16727
|
+
<div class="legend-item">
|
|
16728
|
+
<div class="legend-line" style="background:#4a8fff;height:2px;"></div>
|
|
16729
|
+
<span style="font-size:10px;">Import (blue)</span>
|
|
16730
|
+
</div>
|
|
16731
|
+
<div class="legend-item" style="margin-top:4px;">
|
|
16732
|
+
<div style="width:24px;height:2px;background:repeating-linear-gradient(90deg,#f7916a 0,#f7916a 4px,transparent 4px,transparent 8px);flex-shrink:0;"></div>
|
|
16733
|
+
<span style="font-size:10px;">Call (orange dashed)</span>
|
|
16661
16734
|
</div>
|
|
16662
16735
|
</div>
|
|
16663
|
-
|
|
16664
|
-
|
|
16736
|
+
</div>
|
|
16737
|
+
|
|
16738
|
+
<!-- HISTORY TAB -->
|
|
16739
|
+
<div id="tab-content-history" class="tab-content" style="display:none;overflow-y:auto;flex:1;">
|
|
16740
|
+
<div style="padding:12px;border-bottom:1px solid var(--border);">
|
|
16741
|
+
<div style="font-size:10px;letter-spacing:0.1em;text-transform:uppercase;color:var(--text-dim);margin-bottom:4px;">Active task</div>
|
|
16742
|
+
<div id="history-task" style="font-size:13px;color:var(--text);">Loading\u2026</div>
|
|
16743
|
+
</div>
|
|
16744
|
+
<div id="history-list" style="padding:8px 0;"></div>
|
|
16745
|
+
<div style="padding:12px;border-top:1px solid var(--border);">
|
|
16746
|
+
<button onclick="loadHistory()" style="background:none;border:1px solid var(--border);color:var(--text-dim);cursor:pointer;font-family:inherit;font-size:11px;padding:5px 10px;width:100%;">\u21BB Refresh</button>
|
|
16665
16747
|
</div>
|
|
16666
16748
|
</div>
|
|
16667
|
-
|
|
16668
|
-
|
|
16749
|
+
|
|
16750
|
+
<!-- HELP TAB -->
|
|
16751
|
+
<div id="tab-content-help" class="tab-content" style="display:none;overflow-y:auto;flex:1;padding:14px;font-size:12px;line-height:1.7;">
|
|
16752
|
+
<div style="font-family:inherit;font-weight:700;font-size:13px;margin-bottom:12px;color:var(--text);">What Mycelium does</div>
|
|
16753
|
+
|
|
16754
|
+
<div style="color:var(--text-dim);margin-bottom:16px;">One command gives AI agents persistent, queryable memory of your entire codebase. Agents call /preflight before touching any file \u2014 instead of reading 40 files, they read 4.</div>
|
|
16755
|
+
|
|
16756
|
+
<div style="font-size:10px;letter-spacing:0.1em;text-transform:uppercase;color:var(--text-dim);margin-bottom:8px;">Graph viewer</div>
|
|
16757
|
+
<div style="margin-bottom:14px;">
|
|
16758
|
+
<div style="margin-bottom:5px;"><span style="color:#4a8fff;">\u25CF</span> <strong>Blue solid lines</strong> \u2014 import edges. File A imports from File B.</div>
|
|
16759
|
+
<div style="margin-bottom:5px;"><span style="color:#f7916a;">\u25CF</span> <strong>Orange dashed lines</strong> \u2014 call edges. Function A calls Function B. Requires codebase-memory-mcp.</div>
|
|
16760
|
+
<div style="margin-bottom:5px;"><span style="color:#ffffff;opacity:0.5;">\u25CF</span> <strong>Node size</strong> \u2014 scales with file size (line count).</div>
|
|
16761
|
+
<div style="margin-bottom:5px;"><span style="color:#ffffff;opacity:0.5;">\u25CF</span> <strong>Node color</strong> \u2014 one color per directory.</div>
|
|
16762
|
+
<div style="margin-bottom:5px;"><strong>Click a node</strong> \u2014 see AI description, imports, callers.</div>
|
|
16763
|
+
<div style="margin-bottom:5px;"><strong>Scroll</strong> \u2014 zoom. <strong>Drag</strong> \u2014 pan. <strong>\u22A1</strong> \u2014 fit to screen.</div>
|
|
16764
|
+
</div>
|
|
16765
|
+
|
|
16766
|
+
<div style="font-size:10px;letter-spacing:0.1em;text-transform:uppercase;color:var(--text-dim);margin-bottom:8px;">Agent API endpoints</div>
|
|
16767
|
+
<div style="margin-bottom:14px;">
|
|
16768
|
+
<div style="margin-bottom:6px;"><code style="color:#6af7c4;">/preflight?task=</code><br><span style="color:var(--text-dim);">Natural language task \u2192 exact files to read. Saves 7k+ tokens per agent task.</span></div>
|
|
16769
|
+
<div style="margin-bottom:6px;"><code style="color:#6af7c4;">/search?q=</code><br><span style="color:var(--text-dim);">Semantic search across all file descriptions and tags.</span></div>
|
|
16770
|
+
<div style="margin-bottom:6px;"><code style="color:#6af7c4;">/dependencies?file=</code><br><span style="color:var(--text-dim);">What a file imports and what imports it.</span></div>
|
|
16771
|
+
<div style="margin-bottom:6px;"><code style="color:#6af7c4;">/xref?file=&fn=</code><br><span style="color:var(--text-dim);">Every caller and callee of a function. Know the blast radius before changing anything.</span></div>
|
|
16772
|
+
<div style="margin-bottom:6px;"><code style="color:#6af7c4;">/history</code><br><span style="color:var(--text-dim);">Every file save by task and agent identity.</span></div>
|
|
16773
|
+
<div style="margin-bottom:6px;"><code style="color:#6af7c4;">/graph</code><br><span style="color:var(--text-dim);">Full graph \u2014 all nodes and edges.</span></div>
|
|
16774
|
+
</div>
|
|
16775
|
+
|
|
16776
|
+
<div style="font-size:10px;letter-spacing:0.1em;text-transform:uppercase;color:var(--text-dim);margin-bottom:8px;">CLI commands</div>
|
|
16777
|
+
<div style="margin-bottom:14px;">
|
|
16778
|
+
<div style="margin-bottom:4px;"><code style="color:#6af7c4;">mycelium init</code> \u2014 scan, summarize, serve, watch</div>
|
|
16779
|
+
<div style="margin-bottom:4px;"><code style="color:#6af7c4;">mycelium serve</code> \u2014 start server from existing graph</div>
|
|
16780
|
+
<div style="margin-bottom:4px;"><code style="color:#6af7c4;">mycelium scan</code> \u2014 re-scan without starting server</div>
|
|
16781
|
+
<div style="margin-bottom:4px;"><code style="color:#6af7c4;">mycelium search</code> \u2014 search from terminal</div>
|
|
16782
|
+
<div style="margin-bottom:4px;"><code style="color:#6af7c4;">mycelium status</code> \u2014 graph stats</div>
|
|
16783
|
+
<div style="margin-bottom:4px;"><code style="color:#6af7c4;">mycelium key</code> \u2014 save Anthropic/OpenAI keys</div>
|
|
16784
|
+
<div style="margin-bottom:4px;"><code style="color:#6af7c4;">mycelium embed</code> \u2014 generate semantic embeddings</div>
|
|
16785
|
+
<div style="margin-bottom:4px;"><code style="color:#6af7c4;">mycelium history</code> \u2014 show change log</div>
|
|
16786
|
+
<div style="margin-bottom:4px;"><code style="color:#6af7c4;">mycelium task</code> \u2014 set active task for history</div>
|
|
16787
|
+
<div style="margin-bottom:4px;"><code style="color:#6af7c4;">mycelium ignore</code> \u2014 manage scan ignore list</div>
|
|
16788
|
+
</div>
|
|
16789
|
+
|
|
16790
|
+
<div style="font-size:10px;letter-spacing:0.1em;text-transform:uppercase;color:var(--text-dim);margin-bottom:8px;">CLAUDE.md</div>
|
|
16791
|
+
<div style="color:var(--text-dim);margin-bottom:16px;">Mycelium writes a 5-step checklist into CLAUDE.md automatically. Claude Code reads it and calls /preflight before touching any file.</div>
|
|
16792
|
+
|
|
16793
|
+
<div style="border-top:1px solid var(--border);padding-top:12px;">
|
|
16794
|
+
<a href="https://github.com/KopikoCappu/Mycelium" target="_blank" style="color:#6B8AFF;text-decoration:none;font-size:11px;">GitHub \u2197</a>
|
|
16795
|
+
|
|
16796
|
+
<a href="https://www.npmjs.com/package/@kopikocappu/mycelium" target="_blank" style="color:#6B8AFF;text-decoration:none;font-size:11px;">npm \u2197</a>
|
|
16797
|
+
</div>
|
|
16669
16798
|
</div>
|
|
16670
|
-
|
|
16671
|
-
|
|
16672
|
-
|
|
16673
|
-
|
|
16799
|
+
|
|
16800
|
+
<!-- SETTINGS PANEL (slides over everything) -->
|
|
16801
|
+
<div id="settings-panel" style="display:none;position:absolute;top:0;left:0;right:0;bottom:0;background:var(--surface);z-index:50;overflow-y:auto;padding:16px;flex-direction:column;">
|
|
16802
|
+
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:16px;padding-bottom:10px;border-bottom:1px solid var(--border);">
|
|
16803
|
+
<span style="font-weight:700;font-size:13px;">\u2699 Ignore List</span>
|
|
16804
|
+
<button id="settings-close" style="background:none;border:1px solid var(--border);color:var(--text-dim);cursor:pointer;font-size:12px;padding:3px 10px;font-family:inherit;">\u2715</button>
|
|
16674
16805
|
</div>
|
|
16675
|
-
<div
|
|
16676
|
-
|
|
16806
|
+
<div style="font-size:10px;letter-spacing:0.1em;text-transform:uppercase;color:var(--text-dim);margin-bottom:8px;">Default patterns</div>
|
|
16807
|
+
<div id="ignore-default-list"></div>
|
|
16808
|
+
<div style="font-size:10px;letter-spacing:0.1em;text-transform:uppercase;color:var(--text-dim);margin-top:14px;margin-bottom:8px;">Custom patterns</div>
|
|
16809
|
+
<div id="ignore-custom-list"><div style="font-size:11px;color:var(--text-dim);padding:4px 0;">None added yet</div></div>
|
|
16810
|
+
<div style="display:flex;gap:8px;margin-top:10px;">
|
|
16811
|
+
<input id="ignore-input" placeholder="e.g. android/** or **/*.test.ts" style="flex:1;background:var(--surface2);border:1px solid var(--border);color:var(--text);font-family:inherit;font-size:12px;padding:7px 10px;outline:none;" />
|
|
16812
|
+
<button id="ignore-add-btn" style="background:rgba(107,138,255,0.15);border:1px solid rgba(107,138,255,0.3);color:#6B8AFF;cursor:pointer;font-family:inherit;font-size:11px;padding:7px 14px;">+ Add</button>
|
|
16813
|
+
</div>
|
|
16814
|
+
<div style="font-size:10px;color:var(--text-dim);margin-top:12px;padding:8px;border:1px solid var(--border);line-height:1.6;">
|
|
16815
|
+
Changes apply on next scan.<br>Run <code>mycelium scan</code> or re-run <code>mycelium init</code>.
|
|
16677
16816
|
</div>
|
|
16678
16817
|
</div>
|
|
16679
16818
|
</div>
|
|
@@ -17455,6 +17594,109 @@ function hideLoading() {
|
|
|
17455
17594
|
initMinimap();
|
|
17456
17595
|
loadGraph();
|
|
17457
17596
|
|
|
17597
|
+
// \u2500\u2500 Tab switching \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
17598
|
+
function switchTab(name) {
|
|
17599
|
+
['graph','history','help'].forEach(t => {
|
|
17600
|
+
document.getElementById('tab-content-' + t).style.display = t === name ? 'flex' : 'none';
|
|
17601
|
+
const btn = document.getElementById('tab-' + t);
|
|
17602
|
+
if (btn) btn.classList.toggle('active', t === name);
|
|
17603
|
+
});
|
|
17604
|
+
if (name === 'history') loadHistory();
|
|
17605
|
+
}
|
|
17606
|
+
|
|
17607
|
+
// \u2500\u2500 History tab \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
17608
|
+
async function loadHistory() {
|
|
17609
|
+
const listEl = document.getElementById('history-list');
|
|
17610
|
+
const taskEl = document.getElementById('history-task');
|
|
17611
|
+
listEl.innerHTML = '<div style="padding:12px;font-size:11px;color:var(--text-dim)">Loading\u2026</div>';
|
|
17612
|
+
try {
|
|
17613
|
+
const res = await fetch(\`\${API_BASE}/history\`);
|
|
17614
|
+
const data = await res.json();
|
|
17615
|
+
taskEl.textContent = data.activeTask || 'General development';
|
|
17616
|
+
const changes = data.recentChanges || [];
|
|
17617
|
+
if (changes.length === 0) {
|
|
17618
|
+
listEl.innerHTML = '<div style="padding:12px;font-size:11px;color:var(--text-dim)">No changes yet.<br>Mycelium logs every file save during active sessions.</div>';
|
|
17619
|
+
return;
|
|
17620
|
+
}
|
|
17621
|
+
listEl.innerHTML = changes.slice(0, 50).map(c => {
|
|
17622
|
+
const time = new Date(c.timestamp || c.at || Date.now()).toLocaleTimeString([], {hour:'2-digit',minute:'2-digit'});
|
|
17623
|
+
const file = (c.file || c.path || '').split(/[\\/]/).pop();
|
|
17624
|
+
return \`<div class="history-item">
|
|
17625
|
+
<div class="history-file">\${file || c.file || '\u2014'}</div>
|
|
17626
|
+
<div class="history-meta">
|
|
17627
|
+
<span>\${time}</span>
|
|
17628
|
+
\${c.task ? '<span class="history-task">' + c.task + '</span>' : ''}
|
|
17629
|
+
\${c.agent ? '<span class="history-agent">' + c.agent + '</span>' : ''}
|
|
17630
|
+
</div>
|
|
17631
|
+
</div>\`;
|
|
17632
|
+
}).join('');
|
|
17633
|
+
} catch(e) {
|
|
17634
|
+
listEl.innerHTML = '<div style="padding:12px;font-size:11px;color:var(--text-dim)">Could not load history.<br>Is the server running?</div>';
|
|
17635
|
+
}
|
|
17636
|
+
}
|
|
17637
|
+
|
|
17638
|
+
// \u2500\u2500 Settings panel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
17639
|
+
document.getElementById('settings-btn').addEventListener('click', () => {
|
|
17640
|
+
document.getElementById('settings-panel').style.display = 'flex';
|
|
17641
|
+
loadIgnoreConfig();
|
|
17642
|
+
});
|
|
17643
|
+
document.getElementById('settings-close').addEventListener('click', () => {
|
|
17644
|
+
document.getElementById('settings-panel').style.display = 'none';
|
|
17645
|
+
});
|
|
17646
|
+
|
|
17647
|
+
async function loadIgnoreConfig() {
|
|
17648
|
+
try {
|
|
17649
|
+
const res = await fetch(\`\${API_BASE}/config\`);
|
|
17650
|
+
const data = await res.json();
|
|
17651
|
+
renderIgnoreList(data);
|
|
17652
|
+
} catch(e) {
|
|
17653
|
+
document.getElementById('ignore-default-list').innerHTML =
|
|
17654
|
+
'<div style="font-size:11px;color:var(--text-dim);padding:4px 0">Server not reachable</div>';
|
|
17655
|
+
}
|
|
17656
|
+
}
|
|
17657
|
+
|
|
17658
|
+
function renderIgnoreList(data) {
|
|
17659
|
+
const { defaultIgnore = [], userIgnore = [], userUnignore = [] } = data;
|
|
17660
|
+
document.getElementById('ignore-default-list').innerHTML = defaultIgnore.map(p => {
|
|
17661
|
+
const removed = userUnignore.includes(p);
|
|
17662
|
+
return \`<div class="ignore-item">
|
|
17663
|
+
<span class="ignore-pattern \${removed ? 'removed' : ''}">\${p}</span>
|
|
17664
|
+
\${removed
|
|
17665
|
+
? \`<button class="ignore-btn" onclick="ignoreAction('restore','\${p}')">restore</button>\`
|
|
17666
|
+
: \`<button class="ignore-btn danger" onclick="ignoreAction('remove','\${p}')">remove</button>\`}
|
|
17667
|
+
</div>\`;
|
|
17668
|
+
}).join('');
|
|
17669
|
+
const customEl = document.getElementById('ignore-custom-list');
|
|
17670
|
+
customEl.innerHTML = userIgnore.length === 0
|
|
17671
|
+
? '<div style="font-size:11px;color:var(--text-dim);padding:4px 0;">None added yet</div>'
|
|
17672
|
+
: userIgnore.map(p => \`<div class="ignore-item">
|
|
17673
|
+
<span class="ignore-pattern custom">\${p}</span>
|
|
17674
|
+
<button class="ignore-btn danger" onclick="ignoreAction('remove','\${p}')">remove</button>
|
|
17675
|
+
</div>\`).join('');
|
|
17676
|
+
}
|
|
17677
|
+
|
|
17678
|
+
async function ignoreAction(action, pattern) {
|
|
17679
|
+
try {
|
|
17680
|
+
await fetch(\`\${API_BASE}/config\`, {
|
|
17681
|
+
method: 'POST',
|
|
17682
|
+
headers: {'Content-Type':'application/json'},
|
|
17683
|
+
body: JSON.stringify({action, pattern}),
|
|
17684
|
+
});
|
|
17685
|
+
await loadIgnoreConfig();
|
|
17686
|
+
} catch(e) { alert('Could not update config.'); }
|
|
17687
|
+
}
|
|
17688
|
+
|
|
17689
|
+
document.getElementById('ignore-add-btn').addEventListener('click', async () => {
|
|
17690
|
+
const input = document.getElementById('ignore-input');
|
|
17691
|
+
const pattern = input.value.trim();
|
|
17692
|
+
if (!pattern) return;
|
|
17693
|
+
await ignoreAction('add', pattern);
|
|
17694
|
+
input.value = '';
|
|
17695
|
+
});
|
|
17696
|
+
document.getElementById('ignore-input').addEventListener('keydown', e => {
|
|
17697
|
+
if (e.key === 'Enter') document.getElementById('ignore-add-btn').click();
|
|
17698
|
+
});
|
|
17699
|
+
|
|
17458
17700
|
// \u2500\u2500 Settings / Ignore Panel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
17459
17701
|
const settingsBtn = document.getElementById('settings-btn');
|
|
17460
17702
|
const settingsPanel = document.getElementById('settings-panel');
|
package/package.json
CHANGED