- Move the read-only OpenAPI compat surface from /api/v2/assets to /mjr/am/compat/assets so it never squats ComfyUI core's /api namespace; the legacy alias is opt-in via MJR_AM_LEGACY_API_V2_ASSETS=1. - Allow Python 3.14 (requires-python <3.15) and add 3.14 to CI and tox. - Stop wrapping api.queuePrompt: progress tracking now resolves the running prompt from the core Jobs API (getJobDetail), then /queue and /history, driven by websocket events. Remove wrapHostQueuePrompt. - Add opt-in Majoor.Integration.HideNativeAssetsTab setting that hides ComfyUI's native Assets sidebar tab through the official getSidebarTabs/unregisterSidebarTab API and restores it when disabled. - Fix all 913 type errors in tsconfig.test.json and type-check tests in CI; drop a duplicated `stubs` key in asset_card_inner test; make addToastHistory's type argument optional for the object form. - Update audit report, changelog, API reference and env var docs.
92 lines
2.8 KiB
TypeScript
92 lines
2.8 KiB
TypeScript
/**
|
|
* Optional coexistence with ComfyUI's native "Assets" sidebar tab.
|
|
*
|
|
* Recent ComfyUI frontends ship their own media/assets sidebar tab. Majoor
|
|
* never touches it by default; users who prefer a single assets panel can opt
|
|
* in to hide the native one. Hiding goes through the official extension
|
|
* manager API (`getSidebarTabs` / `unregisterSidebarTab`) and the removed tab
|
|
* definition is kept so it can be re-registered verbatim when the option is
|
|
* turned off again.
|
|
*/
|
|
|
|
import {
|
|
listHostSidebarTabs,
|
|
registerSidebarTab,
|
|
unregisterHostSidebarTab,
|
|
} from "../../app/hostAdapter.js";
|
|
|
|
/** Known ids of the core frontend's assets/media sidebar tab across releases. */
|
|
const NATIVE_ASSETS_TAB_IDS = new Set(["assets", "media-assets", "assets-sidebar"]);
|
|
|
|
/**
|
|
* Core sidebar tabs are registered when the graph view mounts, which can be
|
|
* after extensions finish `setup()`. Re-apply a few times so an early opt-in
|
|
* still takes effect.
|
|
*/
|
|
const RETRY_DELAYS_MS = [500, 2000, 6000];
|
|
|
|
let _hideRequested = false;
|
|
const _hiddenTabs = new Map<string, any>();
|
|
let _retryTimers: ReturnType<typeof setTimeout>[] = [];
|
|
|
|
export function isNativeAssetsTab(tab: any): boolean {
|
|
const id = String(tab?.id || "")
|
|
.trim()
|
|
.toLowerCase();
|
|
if (!id || id.startsWith("majoor") || id.startsWith("mjr")) return false;
|
|
return NATIVE_ASSETS_TAB_IDS.has(id);
|
|
}
|
|
|
|
function _clearRetries(): void {
|
|
for (const timer of _retryTimers.splice(0)) clearTimeout(timer);
|
|
}
|
|
|
|
function _hideNow(): number {
|
|
let hidden = 0;
|
|
for (const tab of listHostSidebarTabs()) {
|
|
if (!isNativeAssetsTab(tab)) continue;
|
|
const id = String(tab.id);
|
|
if (unregisterHostSidebarTab(id)) {
|
|
_hiddenTabs.set(id, tab);
|
|
hidden += 1;
|
|
}
|
|
}
|
|
return hidden;
|
|
}
|
|
|
|
function _restoreNow(): void {
|
|
for (const [id, tab] of [..._hiddenTabs.entries()]) {
|
|
const alreadyBack = listHostSidebarTabs().some((t: any) => String(t?.id || "") === id);
|
|
if (alreadyBack || registerSidebarTab(tab)) _hiddenTabs.delete(id);
|
|
}
|
|
}
|
|
|
|
/** Apply the user's preference. Safe to call repeatedly. */
|
|
export function setNativeAssetsTabHidden(hidden: boolean): void {
|
|
_hideRequested = !!hidden;
|
|
_clearRetries();
|
|
if (!_hideRequested) {
|
|
_restoreNow();
|
|
return;
|
|
}
|
|
_hideNow();
|
|
for (const delay of RETRY_DELAYS_MS) {
|
|
_retryTimers.push(
|
|
setTimeout(() => {
|
|
if (_hideRequested) _hideNow();
|
|
}, delay),
|
|
);
|
|
}
|
|
}
|
|
|
|
/** Extension teardown: give the core tab back and stop pending retries. */
|
|
export function teardownNativeAssetsTab(): void {
|
|
_hideRequested = false;
|
|
_clearRetries();
|
|
_restoreNow();
|
|
}
|
|
|
|
export function getHiddenNativeAssetsTabIds(): string[] {
|
|
return [..._hiddenTabs.keys()];
|
|
}
|