Files
DemonGatanjieu-Anomalous_Mo…/web/modules/ui_browser_navigation.js
T
DemonGatanjieuandClaude Opus 5.5 fb21e6c6e9 feat(scan): the scan page, scan runner and scanner changes (completes 5af9b6d)
5af9b6d was committed with only the removal of ui_scan_wizard.js staged;
this adds everything its message describes, so the branch works again:

- ui_scan_page.js / scan_runner.js / 18-scan-page.css: the scan page with
  matched / unmatched / not-scanned counts, one scan button, "look up the
  unmatched models again", progress in the page, Advanced options.
- api/scan_summary.py: GET /anomalous/scan_summary.
- scraper.py: --retry-unmatched (saved hash when the file is unchanged,
  covers kept); display names set in the editor survive scans.
- api/scanner.py: one request-to-switch mapping (_scraper_flags) and one
  cache-clearing helper for both scan routes.
- model_identity.py: sidecar_info / is_unmatched shared by scraper and API.
- Shell wiring (rail, Home, panel lists, close), the provenance switch in
  Settings -> Model settings, locale keys, docs and CHANGELOG.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 01:14:54 +08:00

121 lines
5.5 KiB
JavaScript

/** Main browser panel visibility and recoverable detail cleanup. */
import { stopAudioStudioPlayback } from './ui_audio_studio.js';
import { stopGalleryAudio } from './ui_audio_gallery.js';
import { leaveScanPage } from './ui_scan_page.js';
function restoreWorkspaceReturnPanel(owner) {
const state = owner.workspaceReturnState;
owner.workspaceReturnState = null;
const panels = [
['grid', owner.grid],
['detail', owner.detailPanel],
['gallery', owner.galleryPanel],
['doctor', owner.doctorPanel],
['assistant', owner.assistantPanel],
['audioStudio', owner.audioStudioPanel],
['audioGallery', owner.audioGalleryPanel],
['home', owner.homePanel],
['activity', owner.activityPanel],
['scan', owner.scanPanel],
];
if (state) {
for (const [key, panel] of panels) {
if (panel && Object.prototype.hasOwnProperty.call(state, key)) panel.style.display = state[key];
}
}
const hasVisiblePanel = panels.some(([, panel]) => panel && panel.style.display !== 'none');
if (!hasVisiblePanel && owner.grid) owner.grid.style.display = 'grid';
}
export function closeWorkspace() {
clearTimeout(this.materialSearchTimer);
this.materialListController?.abort();
this.materialListController = null;
this.materialDetailController?.abort();
this.recipeDetailFinish?.('closed');
const abandonedRecipeModel = typeof this.recipeModelReturn === 'function';
this.recipeModelReturn = null;
if (abandonedRecipeModel) {
this.recipeReturnState = null;
delete this.recipeDetailPayload;
if (this.recipeListContainer) this.recipeListContainer.style.display = '';
const actionbar = this.recipeView?.querySelector('.anomalous-recipe-actionbar');
if (actionbar) actionbar.style.display = '';
if (this.detailPanel) {
this.stopMediaInContainer?.(this.detailPanel);
this.detailPanel.replaceChildren();
this.detailPanel.style.display = 'none';
}
this.currentDetailModel = null;
this.historyStack = [];
}
if (this.paramPanel) this.paramPanel.style.display = 'none';
if (this.recipeView) this.recipeView.style.display = 'none';
if (this.materialView) this.materialView.style.display = 'none';
if (this.notebookBody) this.notebookBody.style.display = 'none';
if (this.materialContainer) this.materialContainer.style.display = 'none';
if (this.recipeContainer) this.recipeContainer.style.display = 'none';
if (this.nbPanel) this.nbPanel.style.display = 'none';
restoreWorkspaceReturnPanel(this);
}
/**
* Esc on the recipe / notes / material workspace does what a click beside it does:
* `closeWorkspace()`. Not while one of this plugin's dialogs or a ComfyUI dialog sits
* above it, and not while a text field has the key (Esc there belongs to the field).
* ComfyUI's own keybindings mark Esc as handled, so `defaultPrevented` says nothing here.
*/
export function bindWorkspaceEscape(owner) {
window.addEventListener('keydown', (e) => {
if (e.key !== 'Escape') return;
if (!owner.modal?.classList.contains('visible') || owner.nbPanel?.style.display !== 'flex') return;
if (e.target?.closest?.('input, textarea, select, [contenteditable="true"]')) return;
const layered = [...document.body.children, ...owner.nbPanel.children]
.some(el => [...el.classList].some(c => c.startsWith('anomalous-') && c.endsWith('overlay')) && el.getClientRects().length);
if (layered || document.querySelector('dialog[open], .p-dialog-mask')) return;
owner.closeWorkspace();
});
}
export function hideAllPanels() {
const abandonedRecipeModel = typeof this.recipeModelReturn === 'function';
this.recipeModelReturn = null;
if (abandonedRecipeModel) {
this.recipeReturnState = null;
delete this.recipeDetailPayload;
if (this.recipeListContainer) this.recipeListContainer.style.display = '';
const actionbar = this.recipeView?.querySelector('.anomalous-recipe-actionbar');
if (actionbar) actionbar.style.display = '';
if (this.detailPanel) {
this.stopMediaInContainer?.(this.detailPanel);
this.detailPanel.replaceChildren();
}
this.currentDetailModel = null;
this.historyStack = [];
}
this.grid.style.display = 'none';
this.detailPanel.style.display = 'none';
if (this.galleryPanel) this.galleryPanel.style.display = 'none';
if (this.nbPanel) this.nbPanel.style.display = 'none';
if (this.doctorPanel) this.doctorPanel.style.display = 'none';
if (this.assistantPanel) this.assistantPanel.style.display = 'none';
if (this.paramPanel) this.paramPanel.style.display = 'none';
if (this.audioStudioPanel) this.audioStudioPanel.style.display = 'none';
if (this.audioGalleryPanel) this.audioGalleryPanel.style.display = 'none';
if (this.homePanel) this.homePanel.style.display = 'none';
if (this.activityPanel) this.activityPanel.style.display = 'none';
if (this.scanPanel) this.scanPanel.style.display = 'none';
leaveScanPage();
stopAudioStudioPlayback();
stopGalleryAudio();
if (this.currentDetailObserver) {
this.currentDetailObserver.disconnect();
this.currentDetailObserver = null;
}
const tbModal = document.getElementById('anomalous-toolbox-modal');
if (tbModal) tbModal.style.display = 'none';
const setModal = document.getElementById('anomalous-settings-hub-modal');
if (setModal) setModal.style.display = 'none';
}