Merge pull request #12 from DemonGatanjieu/fix/modal-keybinding-guard

fix(ui): restore ComfyUI command shortcuts
This commit is contained in:
DemonGatanjieu
2026-08-20 23:57:53 +08:00
committed by GitHub
2 changed files with 13 additions and 8 deletions
+6 -5
View File
@@ -6,6 +6,8 @@ Workspace lifecycle note: reopening an already initialized Workspace must restor
The floating trigger follows the browser modal lifecycle: opening the main browser hides the trigger, while every normal close path restores it. The hidden state uses a scoped class with pointer-events disabled; initialization errors keep the trigger available as the recovery entry point.
Hidden plugin dialogs must not advertise an active modal state. The model-card settings dialog remains mounted for reuse, but its `aria-modal` value follows the overlay lifecycle: `false` while hidden and `true` only while visibly open. This preserves accessibility semantics without tripping ComfyUI Frontend's global modal guard, which otherwise suppresses command-backed shortcuts such as Queue Prompt, Interrupt, and Escape-to-exit-subgraph. The plugin does not install replacement global keyboard handlers or mutate ComfyUI command bindings.
Origin refresh is an explicit enrichment mode passed into `_enrich_recipe`; it must not mutate the Python list of references with ad-hoc state. Origin refresh writes schema v5, while normal updates preserve previously imported identity/origin records when the current machine cannot re-resolve them.
Recipe identity badges use short, bounded labels in the card layout; detailed explanations belong in the help tooltip. Identity badges and model-name rows must remain shrinkable flex children so localized or imported text cannot expand the recipe card beyond its container.
@@ -64,7 +66,7 @@ The extension is a UI-only ComfyUI integration: `NODE_CLASS_MAPPINGS` is intenti
`web/modules/locales.js` is the canonical home for user-facing translation data. The current codebase still contains substantial inline `zh`/`en` branches across `main.js`, Sidebar, Detail, Gallery, Doctor, Notebook, Dialog, Grid, and the optional hash resolver. The first i18n migration snapshot now provides `supportedLocales`, `normalizeLocale`, `resolveLocale`, `formatTranslation`, `translate`, and `createTranslator`. `main.js` and `ui_dialog.js` use this contract; the remaining modules are intentionally unmigrated until their own reviewable snapshots. The refactor must preserve current Chinese and English behavior, keep model names/paths/node types/user data out of locale dictionaries, and keep translated HTML inside the existing `safe_dom.js` boundary. Missing translations must never prevent a panel or action from rendering. Language selection remains the existing zh/en toggle until a later phase introduces a registered locale selector.
Every i18n or licensing change is a local, reviewable snapshot. The implementation must update this document and `.agents/logs/ai_changelog.md` in the same change, run proportional syntax/runtime checks, and create a local Git commit. Remote pushes require explicit user authorization. The MIT license applies to project-owned code and documentation only; external service content and host-project dependencies retain their own terms.
Every i18n or licensing change is a local, reviewable snapshot. The implementation must update this document in the same change, run proportional syntax/runtime checks, and create a local Git commit. Remote pushes require explicit user authorization. The MIT license applies to project-owned code and documentation only; external service content and host-project dependencies retain their own terms.
The second migration snapshot extends the shared translation contract to `ui_grid.js` and `ui_gallery.js`. Gallery confirmation and cover-selection banners are assembled with DOM nodes and `textContent` rather than translated raw HTML; user-controlled model names remain text content. These modules resolve strings at render time through `translate`, so existing global language changes continue to be reflected without introducing a new locale selector.
@@ -84,7 +86,6 @@ The sixth migration snapshot completes the Stage 2 UI i18n pass for `ui_recipes.
Anomalous_Model_Browser/
├── .agents/ # Local, ignored AI handoff material
│ ├── logs/
│ │ ├── ai_changelog.md # Engineering snapshots, decisions, checks, and handoff notes
│ │ └── ai_lessons.md # Curated experience summary and recurring pitfalls
│ └── plans/ # Product/design proposals that are not runtime behavior
├── __init__.py # ComfyUI Extension Entry Point. Registers nodes and sets WEB_DIRECTORY = "./web"
@@ -271,15 +272,15 @@ Scans all nodes in `app.graph._nodes` that are colored red.
* **Variable Naming Collisions**: When moving UI elements, search for ALL references to the old `const` declaration. A single duplicate `const` in the same scope kills the entire module at parse time.
* **Data Scaling & Payload Limits**: When passing arrays/lists (e.g. hundreds of selected files), NEVER append them to URL query parameters (`GET` requests), or you will trigger `414 URI Too Long`. Use `POST` with a `JSON Body`. Similarly, NEVER pass massive arrays directly to `subprocess.run` via CLI arguments, as it will crash silently due to OS character limits (8191 on Windows). Always dump massive data to an intermediate `.json` file for the subprocess to read.
> For a complete list of past mistakes and detailed post-mortems, refer to `.agents/logs/ai_lessons.md`. Engineering snapshots and handoff notes belong in `.agents/logs/ai_changelog.md`.
> For a complete list of past mistakes and detailed post-mortems, refer to `.agents/logs/ai_lessons.md`. Engineering history and change tracking are managed via Git commits and ARCHITECTURE.md.
## 7. Mandatory Change Snapshot Protocol (强制变更快照流程)
Every product-code change in this plugin must finish as one coherent local Git snapshot:
1. Run checks proportional to the touched behavior before committing.
2. Update `.agents/logs/ai_changelog.md` in the same change with the implementation summary, architectural decision, checks run, and handoff notes.
3. Update this `ARCHITECTURE.md` in the same change so directory ownership, data flow, API contracts, naming boundaries, and non-negotiable rules remain accurate. If the code does not alter an architectural boundary, record that the existing boundary is intentionally unchanged rather than inventing a new abstraction.
2. Update this `ARCHITECTURE.md` in the same change so directory ownership, data flow, API contracts, naming boundaries, and non-negotiable rules remain accurate. If the code does not alter an architectural boundary, record that the existing boundary is intentionally unchanged rather than inventing a new abstraction.
3. If critical bugs or architectural pitfalls were resolved, record lessons learned into `.agents/logs/ai_lessons.md`.
4. Create a local Git commit after verification. Keep unrelated work out of the snapshot and do not push unless the user explicitly requests it.
5. Leave a clean worktree for the next agent, or document every intentional uncommitted file in the handoff.
+7 -3
View File
@@ -1152,7 +1152,7 @@ export function createDOM() {
const modelSettingsDialog = document.createElement('div');
modelSettingsDialog.className = 'anomalous-model-settings-dialog';
modelSettingsDialog.setAttribute('role', 'dialog');
modelSettingsDialog.setAttribute('aria-modal', 'true');
modelSettingsDialog.setAttribute('aria-modal', 'false');
const modelSettingsTitle = document.createElement('h2');
const modelSettingsDescription = document.createElement('p');
@@ -1218,11 +1218,15 @@ export function createDOM() {
};
refreshModelSettingsText();
const closeModelSettings = () => { modelSettingsOverlay.hidden = true; };
const setModelSettingsOpen = (isOpen) => {
modelSettingsOverlay.hidden = !isOpen;
modelSettingsDialog.setAttribute('aria-modal', String(isOpen));
};
const closeModelSettings = () => { setModelSettingsOpen(false); };
modelSettingsBtn.onclick = () => {
refreshModelSettingsText();
settingsHubModal.style.display = 'none';
modelSettingsOverlay.hidden = false;
setModelSettingsOpen(true);
videoSetting.select.focus();
};
modelSettingsClose.onclick = closeModelSettings;