From e92267f2b765d7c587dff24a4025a9b71f646d40 Mon Sep 17 00:00:00 2001 From: zhaokun Date: Wed, 22 Oct 2025 15:57:49 +0800 Subject: [PATCH] [Bug] Export as image only exports a portion: capture full content in side-by-side and grid by expanding nested scrollables and using width/height for html-to-image --- src/renderer/src/utils/image.ts | 71 ++++++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 2 deletions(-) diff --git a/src/renderer/src/utils/image.ts b/src/renderer/src/utils/image.ts index a42f372f3c..e98b48918d 100644 --- a/src/renderer/src/utils/image.ts +++ b/src/renderer/src/utils/image.ts @@ -71,6 +71,10 @@ export const captureScrollable = async (elRef: React.RefObject> + const modifiedElements: Array<{ node: HTMLElement; style: SavedStyle }> = [] + // Hide scrollbars during capture el.classList.add('hide-scrollbar') @@ -80,6 +84,49 @@ export const captureScrollable = async (elRef: React.RefObject { + const all = Array.from(el.querySelectorAll('*')) + for (const node of all) { + const cs = getComputedStyle(node) + const save = (fields: Array) => { + const saved: SavedStyle = {} + for (const f of fields) saved[f] = (node.style as any)[f] + modifiedElements.push({ node, style: saved }) + } + + // Expand vertical scroll regions + if (cs.overflowY === 'auto' || cs.overflowY === 'scroll' || cs.overflowY === 'hidden') { + save(['overflow', 'overflowY', 'height', 'maxHeight']) + node.style.overflowY = 'visible' + node.style.overflow = 'visible' + node.style.maxHeight = 'none' + node.style.height = 'auto' + } + + // Expand horizontal scroll regions + if (cs.overflowX === 'auto' || cs.overflowX === 'scroll' || cs.overflowX === 'hidden') { + save(['overflow', 'overflowX', 'width']) + node.style.overflowX = 'visible' + node.style.overflow = 'visible' + // Ensure full width for horizontally-scrolling containers + const sw = Math.max(node.scrollWidth, node.clientWidth) + if (sw > 0) node.style.width = `${sw}px` + } + + // Special case: message content containers in horizontal layout + if (node.classList.contains('message-content-container')) { + save(['maxHeight', 'overflow', 'overflowY', 'height']) + node.style.maxHeight = 'none' + node.style.overflow = 'visible' + node.style.overflowY = 'visible' + node.style.height = 'auto' + } + } + } + + expandNestedScrollables() + // calculate the size of the element const totalWidth = el.scrollWidth const totalHeight = el.scrollHeight @@ -93,6 +140,16 @@ export const captureScrollable = async (elRef: React.RefObject { el.scrollTop = originalScrollTop @@ -109,8 +166,8 @@ export const captureScrollable = async (elRef: React.RefObject