Improve resolver docked-splitter responsiveness and external resize behavior
This commit is contained in:
@@ -329,6 +329,137 @@ test('missing browser splitter keeps a compositor preview between live layout fr
|
||||
/\.mr-missing-browser\.is-resizing \.mr-missing-(?:list|detail)-pane/
|
||||
);
|
||||
assert.doesNotMatch(missingBrowserMethodsSource, /deferMissingBrowserSplitReleaseUi/);
|
||||
assert.match(missingBrowserMethodsSource, /observedWidth\s*<\s*760/);
|
||||
assert.match(missingBrowserMethodsSource, /observedWidth\s*<\s*700/);
|
||||
assert.match(
|
||||
missingBrowserMethodsSource,
|
||||
/scheduleMissingBrowserExternalResizeRestore\(browser,\s*observedWidth\)/
|
||||
);
|
||||
assert.match(
|
||||
resolverMainCssSource,
|
||||
/\.mr-missing-browser\.is-detail-collapsed \.mr-missing-detail-pane\s*\{[^}]*display:\s*none/s
|
||||
);
|
||||
assert.doesNotMatch(missingBrowserMethodsSource, /startMissingBrowserExternalResizeLock/);
|
||||
assert.doesNotMatch(resolverMainCssSource, /mr-resolver-external-resizing/);
|
||||
assert.doesNotMatch(
|
||||
resolverMainCssSource,
|
||||
/@media\s*\(max-width:\s*980px\)\s*\{\s*\.mr-missing-browser/
|
||||
);
|
||||
});
|
||||
|
||||
test('docked ComfyUI splitter coalesces live layout while its gutter stays responsive', () => {
|
||||
const queueResize = eval(
|
||||
`(${extractMethod(dialogShellMethodsSource, 'queueSidebarSplitterResize')})`
|
||||
);
|
||||
const flushResize = eval(
|
||||
`(${extractMethod(dialogShellMethodsSource, 'flushSidebarSplitterResize')})`
|
||||
);
|
||||
const previousRequestAnimationFrame = globalThis.requestAnimationFrame;
|
||||
const previousWindow = globalThis.window;
|
||||
const frames = [];
|
||||
const originalCalls = [];
|
||||
|
||||
globalThis.requestAnimationFrame = callback => {
|
||||
frames.push(callback);
|
||||
return frames.length;
|
||||
};
|
||||
globalThis.window = {
|
||||
setTimeout(callback) {
|
||||
callback();
|
||||
return 1;
|
||||
},
|
||||
};
|
||||
|
||||
try {
|
||||
const gutter = {
|
||||
style: {
|
||||
transform: '',
|
||||
willChange: '',
|
||||
},
|
||||
};
|
||||
const state = {
|
||||
proxy: {},
|
||||
originalResize(...args) {
|
||||
originalCalls.push(args);
|
||||
},
|
||||
gutter,
|
||||
originalTransform: '',
|
||||
pendingArgs: null,
|
||||
animationFrame: null,
|
||||
delayTimer: null,
|
||||
lastLayoutAt: Number.NEGATIVE_INFINITY,
|
||||
minLayoutInterval: 40,
|
||||
appliedPageX: 100,
|
||||
appliedPageY: 0,
|
||||
vertical: false,
|
||||
hasMoved: false,
|
||||
};
|
||||
const context = {
|
||||
_sidebarSplitterDragState: state,
|
||||
flushSidebarSplitterResize: flushResize,
|
||||
};
|
||||
|
||||
queueResize.call(context, state, [{ pageX: 112, pageY: 0 }]);
|
||||
queueResize.call(context, state, [{ pageX: 128, pageY: 0 }]);
|
||||
|
||||
assert.equal(frames.length, 1);
|
||||
assert.equal(gutter.style.transform, 'translate3d(28px, 0px, 0)');
|
||||
assert.equal(originalCalls.length, 0);
|
||||
|
||||
frames.shift()();
|
||||
assert.equal(originalCalls.length, 1);
|
||||
assert.equal(originalCalls[0][0].pageX, 128);
|
||||
assert.equal(state.appliedPageX, 128);
|
||||
assert.equal(gutter.style.transform, '');
|
||||
} finally {
|
||||
globalThis.requestAnimationFrame = previousRequestAnimationFrame;
|
||||
globalThis.window = previousWindow;
|
||||
}
|
||||
|
||||
assert.match(dialogShellMethodsSource, /minLayoutInterval:\s*40/);
|
||||
assert.match(dialogShellMethodsSource, /setPointerCapture\(event\.pointerId\)/);
|
||||
assert.match(dialogShellMethodsSource, /translate3d\(/);
|
||||
assert.match(dialogShellMethodsSource, /requestAnimationFrame\(/);
|
||||
assert.doesNotMatch(dialogShellMethodsSource, /mr-resolver-external-resizing/);
|
||||
});
|
||||
|
||||
test('missing browser detail collapse follows container width with hysteresis', () => {
|
||||
const previousHTMLElement = globalThis.HTMLElement;
|
||||
class FakeHTMLElement {}
|
||||
globalThis.HTMLElement = FakeHTMLElement;
|
||||
|
||||
try {
|
||||
const classes = new Set();
|
||||
const browser = new FakeHTMLElement();
|
||||
browser.classList = {
|
||||
contains(name) {
|
||||
return classes.has(name);
|
||||
},
|
||||
toggle(name, enabled) {
|
||||
if (enabled) classes.add(name);
|
||||
else classes.delete(name);
|
||||
},
|
||||
};
|
||||
|
||||
const context = {
|
||||
_missingBrowserRestoreFrame: null,
|
||||
cancelMissingBrowserExternalResizeRestore() {},
|
||||
};
|
||||
const updateDetailCollapse = eval(
|
||||
`(${extractMethod(missingBrowserMethodsSource, 'updateMissingBrowserDetailCollapse')})`
|
||||
);
|
||||
|
||||
assert.equal(updateDetailCollapse.call(context, browser, 690), true);
|
||||
assert.equal(classes.has('is-detail-collapsed'), true);
|
||||
|
||||
assert.equal(updateDetailCollapse.call(context, browser, 730), false);
|
||||
assert.equal(classes.has('is-detail-collapsed'), true);
|
||||
|
||||
assert.equal(updateDetailCollapse.call(context, browser, 770), true);
|
||||
assert.equal(classes.has('is-detail-collapsed'), false);
|
||||
} finally {
|
||||
globalThis.HTMLElement = previousHTMLElement;
|
||||
}
|
||||
});
|
||||
|
||||
test('local and loaded model tooltips include preview image routes above full names', () => {
|
||||
|
||||
@@ -1156,26 +1156,15 @@
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
@media (max-width: 980px) {
|
||||
.mr-missing-browser {
|
||||
flex-direction: column;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.mr-missing-browser.is-detail-collapsed .mr-missing-browser-splitter,
|
||||
.mr-missing-browser.is-detail-collapsed .mr-missing-detail-pane {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.mr-missing-browser-splitter {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.mr-missing-list-pane {
|
||||
max-height: 46vh;
|
||||
border-right: 0;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
|
||||
}
|
||||
|
||||
.mr-missing-detail-pane {
|
||||
flex: 0 0 auto;
|
||||
overflow: visible;
|
||||
}
|
||||
.mr-missing-browser.is-detail-collapsed .mr-missing-list-pane {
|
||||
flex: 1 1 100% !important;
|
||||
width: 100%;
|
||||
border-right: 0;
|
||||
}
|
||||
|
||||
@media (max-width: 760px) {
|
||||
|
||||
@@ -73,6 +73,10 @@ export class ResolverManagerDialog extends ComfyDialog {
|
||||
this.sidebarTabId = "comfyui-model-resolver";
|
||||
this.sidebarOpenModeStorageKey = "model_resolver_sidebar_open_mode";
|
||||
this.missingBrowserSplitStorageKey = "model_resolver_missing_browser_detail_w";
|
||||
this._missingBrowserExternalResizeTimer = null;
|
||||
this._pendingMissingBrowserExternalResizeBrowser = null;
|
||||
this._pendingMissingBrowserExternalResizeWidth = null;
|
||||
this._missingBrowserObservedHostWidth = null;
|
||||
this.showResolvedModelsStorageKey = "model_resolver_show_resolved_models";
|
||||
this.showAutoDownloadModelsStorageKey = "model_resolver_show_auto_download_models";
|
||||
this.localMatchAlternativesCollapsedStorageKey = "model_resolver_local_match_alternatives_collapsed";
|
||||
@@ -100,6 +104,9 @@ export class ResolverManagerDialog extends ComfyDialog {
|
||||
this._dockedDragPendingRect = null;
|
||||
this._dockedDragAnimationFrame = null;
|
||||
this._dragUndockCandidate = false;
|
||||
this._sidebarSplitterPointerDownHandler = null;
|
||||
this._sidebarSplitterMouseDownHandler = null;
|
||||
this._sidebarSplitterDragState = null;
|
||||
this._analysisProgressToken = null;
|
||||
this._workflowDataLoadToken = null;
|
||||
this._loadedModelsLoadToken = null;
|
||||
|
||||
@@ -207,6 +207,210 @@ export const dialogShellMethods = {
|
||||
if (this.element.parentNode !== container) {
|
||||
container.appendChild(this.element);
|
||||
}
|
||||
this.installSidebarSplitterOptimization();
|
||||
},
|
||||
|
||||
installSidebarSplitterOptimization() {
|
||||
if (this._sidebarSplitterPointerDownHandler || this._sidebarSplitterMouseDownHandler) return;
|
||||
|
||||
this._sidebarSplitterPointerDownHandler = (event) => {
|
||||
if (event.button !== undefined && event.button !== 0) return;
|
||||
const gutter = this.getResolverSidebarGutter(event.target);
|
||||
if (!gutter || typeof gutter.setPointerCapture !== 'function') return;
|
||||
try {
|
||||
gutter.setPointerCapture(event.pointerId);
|
||||
} catch {
|
||||
// Pointer capture is an optional optimization and can fail for synthetic events.
|
||||
}
|
||||
};
|
||||
this._sidebarSplitterMouseDownHandler = (event) => {
|
||||
if (event.button !== undefined && event.button !== 0) return;
|
||||
const gutter = this.getResolverSidebarGutter(event.target);
|
||||
if (gutter) this.startSidebarSplitterDragOptimization(event, gutter);
|
||||
};
|
||||
|
||||
document.addEventListener('pointerdown', this._sidebarSplitterPointerDownHandler, true);
|
||||
document.addEventListener('mousedown', this._sidebarSplitterMouseDownHandler, true);
|
||||
},
|
||||
|
||||
removeSidebarSplitterOptimization() {
|
||||
this.finishSidebarSplitterDragOptimization({ flush: true });
|
||||
if (this._sidebarSplitterPointerDownHandler) {
|
||||
document.removeEventListener('pointerdown', this._sidebarSplitterPointerDownHandler, true);
|
||||
this._sidebarSplitterPointerDownHandler = null;
|
||||
}
|
||||
if (this._sidebarSplitterMouseDownHandler) {
|
||||
document.removeEventListener('mousedown', this._sidebarSplitterMouseDownHandler, true);
|
||||
this._sidebarSplitterMouseDownHandler = null;
|
||||
}
|
||||
},
|
||||
|
||||
getResolverSidebarGutter(target) {
|
||||
if (!this.docked || !(this.dockContainer instanceof HTMLElement) || !this.dockContainer.isConnected) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const element = target instanceof Element ? target : null;
|
||||
const gutter = element?.closest?.('.p-splitter-gutter');
|
||||
const panel = this.dockContainer.closest?.('[data-pc-name="splitterpanel"]');
|
||||
if (!(gutter instanceof HTMLElement) || !(panel instanceof HTMLElement)) return null;
|
||||
|
||||
return gutter.previousElementSibling === panel || gutter.nextElementSibling === panel
|
||||
? gutter
|
||||
: null;
|
||||
},
|
||||
|
||||
findPrimeVueSplitterResizeOwner(gutter) {
|
||||
if (!(gutter instanceof HTMLElement)) return null;
|
||||
|
||||
let instance = gutter.__vueParentComponent || gutter.parentElement?.__vueParentComponent || null;
|
||||
for (let depth = 0; instance && depth < 10; depth += 1, instance = instance.parent) {
|
||||
const owner = instance.ctx;
|
||||
if (
|
||||
owner
|
||||
&& typeof owner.onResize === 'function'
|
||||
&& typeof owner.onResizeStart === 'function'
|
||||
) {
|
||||
return {
|
||||
owner,
|
||||
proxy: instance.proxy || owner
|
||||
};
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
startSidebarSplitterDragOptimization(event, gutter) {
|
||||
if (this._sidebarSplitterDragState) {
|
||||
this.finishSidebarSplitterDragOptimization({ flush: true });
|
||||
}
|
||||
|
||||
const resizeTarget = this.findPrimeVueSplitterResizeOwner(gutter);
|
||||
if (!resizeTarget) return false;
|
||||
|
||||
const { owner, proxy } = resizeTarget;
|
||||
const originalResize = owner.onResize;
|
||||
const state = {
|
||||
owner,
|
||||
proxy,
|
||||
originalResize,
|
||||
wrappedResize: null,
|
||||
gutter,
|
||||
originalTransform: gutter.style.transform,
|
||||
originalWillChange: gutter.style.willChange,
|
||||
pendingArgs: null,
|
||||
animationFrame: null,
|
||||
delayTimer: null,
|
||||
lastLayoutAt: typeof performance === 'object' ? performance.now() : Date.now(),
|
||||
minLayoutInterval: 40,
|
||||
appliedPageX: Number(event.pageX ?? event.clientX) || 0,
|
||||
appliedPageY: Number(event.pageY ?? event.clientY) || 0,
|
||||
vertical: proxy?.horizontal === false,
|
||||
hasMoved: false,
|
||||
mouseUpHandler: null,
|
||||
blurHandler: null
|
||||
};
|
||||
|
||||
state.wrappedResize = (...args) => this.queueSidebarSplitterResize(state, args);
|
||||
try {
|
||||
owner.onResize = state.wrappedResize;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
if (owner.onResize !== state.wrappedResize) return false;
|
||||
|
||||
state.mouseUpHandler = (mouseEvent) => {
|
||||
this.finishSidebarSplitterDragOptimization({
|
||||
flush: true,
|
||||
finalEvent: mouseEvent
|
||||
});
|
||||
};
|
||||
state.blurHandler = () => this.finishSidebarSplitterDragOptimization({ flush: true });
|
||||
this._sidebarSplitterDragState = state;
|
||||
document.addEventListener('mouseup', state.mouseUpHandler, true);
|
||||
window.addEventListener('blur', state.blurHandler, { once: true });
|
||||
return true;
|
||||
},
|
||||
|
||||
queueSidebarSplitterResize(state, args) {
|
||||
if (!state || this._sidebarSplitterDragState !== state) {
|
||||
return state?.originalResize?.apply(state.proxy, args);
|
||||
}
|
||||
|
||||
const event = args?.[0];
|
||||
const pageX = Number(event?.pageX ?? event?.clientX);
|
||||
const pageY = Number(event?.pageY ?? event?.clientY);
|
||||
state.pendingArgs = args;
|
||||
state.hasMoved = true;
|
||||
|
||||
const offset = state.vertical
|
||||
? pageY - state.appliedPageY
|
||||
: pageX - state.appliedPageX;
|
||||
if (Number.isFinite(offset)) {
|
||||
state.gutter.style.willChange = 'transform';
|
||||
state.gutter.style.transform = offset
|
||||
? `translate3d(${state.vertical ? 0 : Math.round(offset)}px, ${state.vertical ? Math.round(offset) : 0}px, 0)`
|
||||
: state.originalTransform;
|
||||
}
|
||||
|
||||
if (state.animationFrame || state.delayTimer) return;
|
||||
const now = typeof performance === 'object' ? performance.now() : Date.now();
|
||||
const delay = Math.max(0, state.minLayoutInterval - (now - state.lastLayoutAt));
|
||||
const requestFlush = () => {
|
||||
state.delayTimer = null;
|
||||
state.animationFrame = requestAnimationFrame(() => {
|
||||
state.animationFrame = null;
|
||||
this.flushSidebarSplitterResize(state);
|
||||
});
|
||||
};
|
||||
|
||||
if (delay > 0) {
|
||||
state.delayTimer = window.setTimeout(requestFlush, delay);
|
||||
} else {
|
||||
requestFlush();
|
||||
}
|
||||
},
|
||||
|
||||
flushSidebarSplitterResize(state) {
|
||||
if (!state?.pendingArgs) return false;
|
||||
|
||||
const args = state.pendingArgs;
|
||||
state.pendingArgs = null;
|
||||
const event = args[0];
|
||||
state.originalResize.apply(state.proxy, args);
|
||||
state.appliedPageX = Number(event?.pageX ?? event?.clientX) || state.appliedPageX;
|
||||
state.appliedPageY = Number(event?.pageY ?? event?.clientY) || state.appliedPageY;
|
||||
state.lastLayoutAt = typeof performance === 'object' ? performance.now() : Date.now();
|
||||
state.gutter.style.transform = state.originalTransform;
|
||||
return true;
|
||||
},
|
||||
|
||||
finishSidebarSplitterDragOptimization({ flush = false, finalEvent = null } = {}) {
|
||||
const state = this._sidebarSplitterDragState;
|
||||
if (!state) return false;
|
||||
this._sidebarSplitterDragState = null;
|
||||
|
||||
if (state.delayTimer) {
|
||||
clearTimeout(state.delayTimer);
|
||||
state.delayTimer = null;
|
||||
}
|
||||
if (state.animationFrame) {
|
||||
cancelAnimationFrame(state.animationFrame);
|
||||
state.animationFrame = null;
|
||||
}
|
||||
if (flush && state.hasMoved && finalEvent) {
|
||||
state.pendingArgs = [finalEvent];
|
||||
}
|
||||
if (flush) this.flushSidebarSplitterResize(state);
|
||||
|
||||
if (state.owner.onResize === state.wrappedResize) {
|
||||
state.owner.onResize = state.originalResize;
|
||||
}
|
||||
state.gutter.style.transform = state.originalTransform;
|
||||
state.gutter.style.willChange = state.originalWillChange;
|
||||
document.removeEventListener('mouseup', state.mouseUpHandler, true);
|
||||
window.removeEventListener('blur', state.blurHandler);
|
||||
return true;
|
||||
},
|
||||
|
||||
dockToSidebar() {
|
||||
@@ -306,6 +510,7 @@ export const dialogShellMethods = {
|
||||
undockToFloating({ persist = true, closeSidebar = true } = {}) {
|
||||
if (!this.element) return;
|
||||
|
||||
this.removeSidebarSplitterOptimization();
|
||||
this.setDockDropPreviewActive(false);
|
||||
this.setUndockDropPreviewActive(false);
|
||||
this._pendingDragDockRect = null;
|
||||
|
||||
@@ -98,6 +98,7 @@ export const lifecycleGraphMethods = {
|
||||
close({ collapseSidebar = true } = {}) {
|
||||
const wasDocked = this.docked;
|
||||
const dockContainer = this.dockContainer;
|
||||
this.removeSidebarSplitterOptimization?.();
|
||||
this.setDockDropPreviewActive(false);
|
||||
this.setUndockDropPreviewActive(false);
|
||||
this.rememberSidebarOpenMode(this.docked ? 'docked' : 'floating');
|
||||
|
||||
@@ -959,20 +959,39 @@ export const missingBrowserMethods = {
|
||||
this.resizeMissingBrowserDetailBy(browser, event.key === 'ArrowLeft' ? 32 : -32);
|
||||
});
|
||||
|
||||
this.cancelMissingBrowserExternalResizeRestore();
|
||||
this._missingBrowserResizeObserver?.disconnect?.();
|
||||
if (typeof ResizeObserver === 'function') {
|
||||
const resizeHost = browser.parentElement instanceof HTMLElement
|
||||
? browser.parentElement
|
||||
: browser;
|
||||
this._missingBrowserObservedHostWidth = null;
|
||||
this._missingBrowserResizeObserver = new ResizeObserver((entries) => {
|
||||
const observedWidth = Number(entries?.[0]?.contentRect?.width);
|
||||
if (!Number.isFinite(observedWidth) || observedWidth <= 0) return;
|
||||
|
||||
const previousHostWidth = Number(this._missingBrowserObservedHostWidth);
|
||||
this._missingBrowserObservedHostWidth = observedWidth;
|
||||
this.rememberMissingBrowserWidth(observedWidth);
|
||||
|
||||
if (!Number.isFinite(previousHostWidth) || previousHostWidth <= 0) {
|
||||
this.updateMissingBrowserDetailCollapse(browser, observedWidth);
|
||||
return;
|
||||
}
|
||||
if (Math.abs(previousHostWidth - observedWidth) < 0.5) return;
|
||||
|
||||
const settlingUntil = Number(this._missingBrowserSplitSettlingUntil || 0);
|
||||
const isSettling = typeof performance === 'object'
|
||||
&& typeof performance.now === 'function'
|
||||
&& performance.now() < settlingUntil;
|
||||
if (!this._missingBrowserSplitDragging && !isSettling) {
|
||||
this.scheduleMissingBrowserSplitRestore(browser, observedWidth, { useDefault: false });
|
||||
if (
|
||||
!this._missingBrowserSplitDragging
|
||||
&& !isSettling
|
||||
) {
|
||||
this.scheduleMissingBrowserExternalResizeRestore(browser, observedWidth);
|
||||
}
|
||||
});
|
||||
this._missingBrowserResizeObserver.observe(browser);
|
||||
this._missingBrowserResizeObserver.observe(resizeHost);
|
||||
} else {
|
||||
this.cancelMissingBrowserPrewarmFrame();
|
||||
this._missingBrowserPrewarmFrame = requestAnimationFrame(() => {
|
||||
@@ -981,7 +1000,8 @@ export const missingBrowserMethods = {
|
||||
if (this._missingBrowserSplitDragging) return;
|
||||
const measuredWidth = Number(browser.clientWidth || browser.getBoundingClientRect().width);
|
||||
this.rememberMissingBrowserWidth(measuredWidth);
|
||||
if (!this._missingBrowserSplitDragging) {
|
||||
this.updateMissingBrowserDetailCollapse(browser, measuredWidth);
|
||||
if (!this._missingBrowserSplitDragging && !browser.classList.contains('is-detail-collapsed')) {
|
||||
this.scheduleMissingBrowserSplitRestore(browser, measuredWidth, { useDefault: false });
|
||||
}
|
||||
});
|
||||
@@ -994,6 +1014,68 @@ export const missingBrowserMethods = {
|
||||
this._missingBrowserPrewarmFrame = null;
|
||||
},
|
||||
|
||||
updateMissingBrowserDetailCollapse(browser, width) {
|
||||
if (!(browser instanceof HTMLElement)) return false;
|
||||
const observedWidth = Number(width);
|
||||
if (!Number.isFinite(observedWidth) || observedWidth <= 0) return false;
|
||||
|
||||
const wasCollapsed = browser.classList.contains('is-detail-collapsed');
|
||||
const shouldCollapse = wasCollapsed
|
||||
? observedWidth < 760
|
||||
: observedWidth < 700;
|
||||
if (shouldCollapse === wasCollapsed) return false;
|
||||
|
||||
browser.classList.toggle('is-detail-collapsed', shouldCollapse);
|
||||
if (shouldCollapse) {
|
||||
this.cancelMissingBrowserExternalResizeRestore();
|
||||
if (this._missingBrowserRestoreFrame) {
|
||||
cancelAnimationFrame(this._missingBrowserRestoreFrame);
|
||||
this._missingBrowserRestoreFrame = null;
|
||||
}
|
||||
this._pendingMissingBrowserRestoreBrowser = null;
|
||||
this._pendingMissingBrowserRestoreWidth = null;
|
||||
this._pendingMissingBrowserRestoreUseDefault = false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
cancelMissingBrowserExternalResizeRestore() {
|
||||
if (this._missingBrowserExternalResizeTimer) {
|
||||
clearTimeout(this._missingBrowserExternalResizeTimer);
|
||||
}
|
||||
this._missingBrowserExternalResizeTimer = null;
|
||||
this._pendingMissingBrowserExternalResizeBrowser = null;
|
||||
this._pendingMissingBrowserExternalResizeWidth = null;
|
||||
},
|
||||
|
||||
scheduleMissingBrowserExternalResizeRestore(browser, browserWidth, delay = 120) {
|
||||
if (!(browser instanceof HTMLElement)) return;
|
||||
|
||||
this._pendingMissingBrowserExternalResizeBrowser = browser;
|
||||
this._pendingMissingBrowserExternalResizeWidth = Number(browserWidth) || null;
|
||||
if (this._missingBrowserExternalResizeTimer) {
|
||||
clearTimeout(this._missingBrowserExternalResizeTimer);
|
||||
}
|
||||
|
||||
this._missingBrowserExternalResizeTimer = setTimeout(() => {
|
||||
this._missingBrowserExternalResizeTimer = null;
|
||||
const targetBrowser = this._pendingMissingBrowserExternalResizeBrowser;
|
||||
const targetWidth = this._pendingMissingBrowserExternalResizeWidth;
|
||||
this._pendingMissingBrowserExternalResizeBrowser = null;
|
||||
this._pendingMissingBrowserExternalResizeWidth = null;
|
||||
|
||||
if (
|
||||
!targetBrowser?.isConnected
|
||||
|| this._missingBrowserSplitDragging
|
||||
) {
|
||||
return;
|
||||
}
|
||||
this.updateMissingBrowserDetailCollapse(targetBrowser, targetWidth);
|
||||
if (targetBrowser.classList.contains('is-detail-collapsed')) return;
|
||||
this.scheduleMissingBrowserSplitRestore(targetBrowser, targetWidth, { useDefault: false });
|
||||
}, Math.max(0, Number(delay) || 0));
|
||||
},
|
||||
|
||||
getStoredMissingBrowserSplitWidth() {
|
||||
if (this._missingBrowserStoredSplitWidthLoaded) {
|
||||
return this._missingBrowserStoredSplitWidth || null;
|
||||
@@ -1060,7 +1142,7 @@ export const missingBrowserMethods = {
|
||||
},
|
||||
|
||||
scheduleMissingBrowserSplitRestore(browser, browserWidth = null, { useDefault = false } = {}) {
|
||||
if (!(browser instanceof HTMLElement)) return;
|
||||
if (!(browser instanceof HTMLElement) || browser.classList.contains('is-detail-collapsed')) return;
|
||||
|
||||
this._pendingMissingBrowserRestoreBrowser = browser;
|
||||
this._pendingMissingBrowserRestoreWidth = Number.isFinite(Number(browserWidth)) && Number(browserWidth) > 0
|
||||
@@ -1100,7 +1182,7 @@ export const missingBrowserMethods = {
|
||||
},
|
||||
|
||||
startMissingBrowserSplitDrag(event, browser, splitter = null, panes = {}) {
|
||||
if (!(browser instanceof HTMLElement)) return;
|
||||
if (!(browser instanceof HTMLElement) || browser.classList.contains('is-detail-collapsed')) return;
|
||||
|
||||
event.preventDefault();
|
||||
event.stopPropagation?.();
|
||||
|
||||
Reference in New Issue
Block a user