mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-01-11 16:39:15 +08:00
[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
This commit is contained in:
parent
b26df0e614
commit
e92267f2b7
@ -71,6 +71,10 @@ export const captureScrollable = async (elRef: React.RefObject<HTMLElement | nul
|
|||||||
|
|
||||||
const originalScrollTop = el.scrollTop
|
const originalScrollTop = el.scrollTop
|
||||||
|
|
||||||
|
// Track nested elements we temporarily modify
|
||||||
|
type SavedStyle = Partial<Pick<CSSStyleDeclaration, 'overflow' | 'overflowX' | 'overflowY' | 'height' | 'maxHeight' | 'width'>>
|
||||||
|
const modifiedElements: Array<{ node: HTMLElement; style: SavedStyle }> = []
|
||||||
|
|
||||||
// Hide scrollbars during capture
|
// Hide scrollbars during capture
|
||||||
el.classList.add('hide-scrollbar')
|
el.classList.add('hide-scrollbar')
|
||||||
|
|
||||||
@ -80,6 +84,49 @@ export const captureScrollable = async (elRef: React.RefObject<HTMLElement | nul
|
|||||||
el.style.overflow = 'visible'
|
el.style.overflow = 'visible'
|
||||||
el.style.position = 'static'
|
el.style.position = 'static'
|
||||||
|
|
||||||
|
// Expand nested scrollable containers (horizontal groups, inner content areas, etc.)
|
||||||
|
const expandNestedScrollables = () => {
|
||||||
|
const all = Array.from(el.querySelectorAll<HTMLElement>('*'))
|
||||||
|
for (const node of all) {
|
||||||
|
const cs = getComputedStyle(node)
|
||||||
|
const save = (fields: Array<keyof SavedStyle>) => {
|
||||||
|
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
|
// calculate the size of the element
|
||||||
const totalWidth = el.scrollWidth
|
const totalWidth = el.scrollWidth
|
||||||
const totalHeight = el.scrollHeight
|
const totalHeight = el.scrollHeight
|
||||||
@ -93,6 +140,16 @@ export const captureScrollable = async (elRef: React.RefObject<HTMLElement | nul
|
|||||||
el.style.overflow = originalStyle.overflow
|
el.style.overflow = originalStyle.overflow
|
||||||
el.style.position = originalStyle.position
|
el.style.position = originalStyle.position
|
||||||
|
|
||||||
|
// restore nested modified elements
|
||||||
|
for (const { node, style } of modifiedElements.reverse()) {
|
||||||
|
if (style.overflow !== undefined) node.style.overflow = style.overflow
|
||||||
|
if (style.overflowX !== undefined) node.style.overflowX = style.overflowX
|
||||||
|
if (style.overflowY !== undefined) node.style.overflowY = style.overflowY
|
||||||
|
if (style.height !== undefined) node.style.height = style.height
|
||||||
|
if (style.maxHeight !== undefined) node.style.maxHeight = style.maxHeight
|
||||||
|
if (style.width !== undefined) node.style.width = style.width
|
||||||
|
}
|
||||||
|
|
||||||
// restore the original scroll position
|
// restore the original scroll position
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
el.scrollTop = originalScrollTop
|
el.scrollTop = originalScrollTop
|
||||||
@ -109,8 +166,8 @@ export const captureScrollable = async (elRef: React.RefObject<HTMLElement | nul
|
|||||||
cacheBust: true,
|
cacheBust: true,
|
||||||
pixelRatio: window.devicePixelRatio,
|
pixelRatio: window.devicePixelRatio,
|
||||||
skipAutoScale: true,
|
skipAutoScale: true,
|
||||||
canvasWidth: el.scrollWidth,
|
width: el.scrollWidth,
|
||||||
canvasHeight: el.scrollHeight,
|
height: el.scrollHeight,
|
||||||
style: {
|
style: {
|
||||||
backgroundColor: getComputedStyle(el).backgroundColor,
|
backgroundColor: getComputedStyle(el).backgroundColor,
|
||||||
color: getComputedStyle(el).color
|
color: getComputedStyle(el).color
|
||||||
@ -126,6 +183,16 @@ export const captureScrollable = async (elRef: React.RefObject<HTMLElement | nul
|
|||||||
el.style.overflow = originalStyle.overflow
|
el.style.overflow = originalStyle.overflow
|
||||||
el.style.position = originalStyle.position
|
el.style.position = originalStyle.position
|
||||||
|
|
||||||
|
// Restore nested modified elements
|
||||||
|
for (const { node, style } of modifiedElements.reverse()) {
|
||||||
|
if (style.overflow !== undefined) node.style.overflow = style.overflow
|
||||||
|
if (style.overflowX !== undefined) node.style.overflowX = style.overflowX
|
||||||
|
if (style.overflowY !== undefined) node.style.overflowY = style.overflowY
|
||||||
|
if (style.height !== undefined) node.style.height = style.height
|
||||||
|
if (style.maxHeight !== undefined) node.style.maxHeight = style.maxHeight
|
||||||
|
if (style.width !== undefined) node.style.width = style.width
|
||||||
|
}
|
||||||
|
|
||||||
const imageData = canvas
|
const imageData = canvas
|
||||||
|
|
||||||
// Restore original scroll position
|
// Restore original scroll position
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user