Scan page: a scan icon, quiet links for what is left out, narrow by width

The scan button gets a scan-frame icon (the radar read as a clock). The
models set to never be scanned and the files in other formats are quiet
links under the state chips, so "worth a look" only appears for damaged
files and voice-like models. The scan card stacks the ring above the
rest by the page's own width (docked in the sidebar too), and the More
arrow turns when unfolded.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
DemonGatanjieu
2026-10-11 15:32:53 +08:00
co-authored by Claude Opus 5.5
parent 97ae88bc0b
commit 949645bc9d
4 changed files with 47 additions and 13 deletions
+1 -1
View File
@@ -4,7 +4,7 @@
*/
const ICONS = {
radar: '<circle cx="12" cy="12" r="9"/><path d="M12 12l6-6" /><circle cx="12" cy="12" r="1.5" fill="currentColor"/><path d="M12 3v3M3 12h3" opacity="0.5"/>',
scan: '<path d="M4 8V5.5A1.5 1.5 0 0 1 5.5 4H8M16 4h2.5A1.5 1.5 0 0 1 20 5.5V8M20 16v2.5a1.5 1.5 0 0 1-1.5 1.5H16M8 20H5.5A1.5 1.5 0 0 1 4 18.5V16"/><path d="M4 12h16"/>',
pick: '<path d="M10 6h10M10 12h10M10 18h10"/><path d="M3.5 6l1.5 1.5 2.5-3M3.5 12l1.5 1.5 2.5-3"/><circle cx="5" cy="18" r="1.2"/>',
online: '<circle cx="12" cy="12" r="9"/><path d="M3 12h18"/><path d="M12 3c2.6 2.5 3.8 5.5 3.8 9s-1.2 6.5-3.8 9c-2.6-2.5-3.8-5.5-3.8-9S9.4 5.5 12 3z"/>',
offline: '<path d="M3 3l18 18"/><path d="M8.5 16.4a5 5 0 0 1 7 0"/><path d="M5 12.9a10 10 0 0 1 4.5-2.6M14.5 10.3a10 10 0 0 1 4.5 2.6"/><circle cx="12" cy="20" r="1" fill="currentColor"/>',
+16 -7
View File
@@ -6,9 +6,9 @@
* (the full counts unfold). Progress shows under it. Then the models' state as a bar with a chip
* per state (not found and not scanned open their list), and a chip for the components a
* drawing model loads (VAE, text encoders…), which are not in the counts since many are not on
* Civitai. Then, only when there is something, what needs a look: damaged files, new models that
* look like no drawing model (don't scan them, scan them, see them), models set to "don't scan",
* files in other formats. Then the settings (ui_scan_settings.js) and the last scan in one line.
* Civitai, with quiet links to the models set to "don't scan" and the files in other formats.
* Then, only when there is something, what needs a look: damaged files, new models that look
* like no drawing model (don't scan them, scan them, see them). Then the settings (ui_scan_settings.js) and the last scan in one line.
* Lists are pages of their own (ui_scan_lists.js) with a way back. Scans run through
* scan_runner.js; the progress box is scan_progress.js's panel, hosted here while the page is shown.
*/
@@ -166,7 +166,7 @@ function scanCard(owner, panel, summary, busy) {
: waiting ? t(options.offline ? 'scanPageScanNewOffline' : 'scanPageScanNew', { count: waiting })
: t('scanPageScanAgain');
const primary = button('anomalous-scan-primary', undefined, () => run(owner, panel));
primary.append(scanIcon('radar'), el('span', '', label));
primary.append(scanIcon('scan'), el('span', '', label));
primary.disabled = busy;
const pick = button('anomalous-scan-secondary', undefined, () => openScanPicker(options.picked, (next) => {
options.picked = next;
@@ -197,7 +197,10 @@ function scanCard(owner, panel, summary, busy) {
return card;
}
/** The models' state: a bar of found / not found / not scanned, a chip for each, and the components' chip. */
/**
* The models' state: a bar of found / not found / not scanned, a chip for each, the components'
* chip, and under them quiet links to the models left out (set to "don't scan", other formats).
*/
function stateRow(summary, open) {
const counts = mainCounts(summary);
const box = el('section', 'anomalous-scan-state');
@@ -231,6 +234,14 @@ function stateRow(summary, open) {
chips.append(node);
}
box.append(el('h2', 'anomalous-scan-section-title', t('scanStateTitle')), bar, chips);
const notes = el('div', 'anomalous-scan-state-notes');
for (const [count, icon, key, view] of [[summary.excluded, 'excluded', 'scanPageExcludedNote', 'excluded'], [summary.skipped, 'file', 'scanPageSkippedNote', 'skipped']]) {
if (!count) continue;
const link = button('anomalous-scan-quiet-link', undefined, open(view));
link.append(scanIcon(icon), el('span', '', t(key, { count })));
notes.append(link);
}
if (notes.childElementCount) box.append(notes);
return box;
}
@@ -255,8 +266,6 @@ function attention(owner, panel, summary, open) {
button('anomalous-pick-link', t('scanPageSeeThem'), open('notdrawing')),
]);
}
if (summary.excluded) line('excluded', t('scanPageExcludedNote', { count: summary.excluded }), 'quiet', open('excluded'));
if (summary.skipped) line('file', t('scanPageSkippedNote', { count: summary.skipped }), 'quiet', open('skipped'));
if (!rows.length) return null;
const box = el('section', 'anomalous-scan-attention');
const list = el('div', 'anomalous-scan-card anomalous-scan-attn-list');
+1 -1
View File
@@ -16,7 +16,7 @@
@import url("./styles/15-shell-rail.css?v=20261007-theme-2");
@import url("./styles/16-activity.css?v=20261007-theme-2");
@import url("./styles/17-model-types.css?v=20261007-theme-2");
@import url("./styles/18-scan-page.css?v=20261011-look");
@import url("./styles/18-scan-page.css?v=20261011-look-3");
@import url("./styles/19-model-doctor.css?v=20261007-theme-2");
@import url("./styles/20-current-node.css?v=20261007-theme-2");
@import url("./styles/21-prompt-studio.css?v=20261007-theme-2");
+29 -4
View File
@@ -18,6 +18,7 @@
margin: 0 auto;
padding: 32px 28px 40px;
box-sizing: border-box;
container: scanpage / inline-size;
}
.anomalous-scan-title {
@@ -271,6 +272,29 @@ button.anomalous-scan-state-chip:hover {
border-radius: 50%;
}
/* Under the chips: the models left out, as quiet links. */
.anomalous-scan-state-notes {
display: flex;
flex-wrap: wrap;
gap: 4px 16px;
}
.anomalous-scan-quiet-link {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 0;
border: none;
background: none;
color: var(--amb-text-muted);
font: inherit;
font-size: 12.5px;
cursor: pointer;
}
.anomalous-scan-quiet-link .anomalous-scan-icon { width: 14px; height: 14px; }
.anomalous-scan-quiet-link:hover { color: var(--amb-text-main); text-decoration: underline dotted; text-underline-offset: 3px; }
/* The components: apart from the counts, dashed, at the end of the row. */
.anomalous-scan-state-chip.anomalous-scan-parts-chip {
margin-left: auto;
@@ -305,7 +329,6 @@ button.anomalous-scan-attn:hover { background: rgba(var(--amb-ink-rgb), 0.04); }
.anomalous-scan-attn-text { flex: 1 1 220px; min-width: 0; line-height: 1.5; }
.anomalous-scan-attn > .anomalous-scan-icon:last-child { color: var(--amb-text-muted); }
.anomalous-scan-attn.is-danger { color: var(--amb-danger-text); }
.anomalous-scan-attn.is-quiet { color: var(--amb-text-muted); }
/* The settings: a tile each, with its icon and switch; the rarer ones folded under them. */
.anomalous-scan-tiles {
@@ -366,7 +389,7 @@ label.anomalous-scan-tile:hover { border-color: color-mix(in srgb, var(--amb-lin
}
.anomalous-scan-more-head::-webkit-details-marker { display: none; }
.anomalous-scan-more-head::before { content: '›'; color: var(--amb-text-muted); transition: transform 0.15s ease; }
.anomalous-scan-more-head::before { content: '›'; display: inline-block; color: var(--amb-text-muted); transition: transform 0.15s ease; }
.anomalous-scan-more-settings[open] > .anomalous-scan-more-head::before { transform: rotate(90deg); }
.anomalous-scan-more-settings > .anomalous-scan-setting-help { display: block; padding-bottom: 12px; }
@@ -392,8 +415,10 @@ label.anomalous-scan-tile:hover { border-color: color-mix(in srgb, var(--amb-lin
.anomalous-scan-last-text { flex: 1 1 260px; min-width: 0; }
.anomalous-scan-last-line .anomalous-pick-link { margin-left: 0; }
@media (max-width: 560px) {
.anomalous-scan-card.anomalous-scan-hero { flex-direction: column; align-items: center; }
/* Narrow (a phone, or docked in the sidebar): the ring above the rest. */
@container scanpage (max-width: 560px) {
.anomalous-scan-card.anomalous-scan-hero { flex-direction: column; align-items: stretch; }
.anomalous-scan-ring { align-self: center; }
.anomalous-scan-mode { margin-left: 0; }
.anomalous-scan-state-chip.anomalous-scan-parts-chip { margin-left: 0; }
}