diff --git a/src/lib/components/chat/Messages/ResponseMessage.svelte b/src/lib/components/chat/Messages/ResponseMessage.svelte index 6a30f7c0f5..c9c9ef420c 100644 --- a/src/lib/components/chat/Messages/ResponseMessage.svelte +++ b/src/lib/components/chat/Messages/ResponseMessage.svelte @@ -2,7 +2,7 @@ import { toast } from 'svelte-sonner'; import dayjs from 'dayjs'; - import { createEventDispatcher } from 'svelte'; + import { createEventDispatcher, onDestroy } from 'svelte'; import { onMount, tick, getContext } from 'svelte'; import type { Writable } from 'svelte/store'; import type { i18n as i18nType, t } from 'i18next'; @@ -152,6 +152,8 @@ export let topPadding = false; let citationsElement: HTMLDivElement; + + let contentContainerElement: HTMLDivElement; let buttonsContainerElement: HTMLDivElement; let showDeleteConfirm = false; @@ -541,24 +543,70 @@ })(); } + const buttonsWheelHandler = (event: WheelEvent) => { + if (buttonsContainerElement) { + if (buttonsContainerElement.scrollWidth <= buttonsContainerElement.clientWidth) { + // If the container is not scrollable, horizontal scroll + return; + } else { + event.preventDefault(); + + if (event.deltaY !== 0) { + // Adjust horizontal scroll position based on vertical scroll + buttonsContainerElement.scrollLeft += event.deltaY; + } + } + } + }; + + const contentCopyHandler = (e) => { + if (contentContainerElement) { + e.preventDefault(); + // Get the selected HTML + const selection = window.getSelection(); + const range = selection.getRangeAt(0); + const tempDiv = document.createElement('div'); + + // Remove background, color, and font styles + tempDiv.appendChild(range.cloneContents()); + + tempDiv.querySelectorAll('table').forEach((table) => { + table.style.borderCollapse = 'collapse'; + table.style.width = 'auto'; + table.style.tableLayout = 'auto'; + }); + + tempDiv.querySelectorAll('th').forEach((th) => { + th.style.whiteSpace = 'nowrap'; + th.style.padding = '4px 8px'; + }); + + // Put cleaned HTML + plain text into clipboard + e.clipboardData.setData('text/html', tempDiv.innerHTML); + e.clipboardData.setData('text/plain', selection.toString()); + } + }; + onMount(async () => { // console.log('ResponseMessage mounted'); await tick(); if (buttonsContainerElement) { - buttonsContainerElement.addEventListener('wheel', function (event) { - if (buttonsContainerElement.scrollWidth <= buttonsContainerElement.clientWidth) { - // If the container is not scrollable, horizontal scroll - return; - } else { - event.preventDefault(); + buttonsContainerElement.addEventListener('wheel', buttonsWheelHandler); + } - if (event.deltaY !== 0) { - // Adjust horizontal scroll position based on vertical scroll - buttonsContainerElement.scrollLeft += event.deltaY; - } - } - }); + if (contentContainerElement) { + contentContainerElement.addEventListener('copy', contentCopyHandler); + } + }); + + onDestroy(() => { + if (buttonsContainerElement) { + buttonsContainerElement.removeEventListener('wheel', buttonsWheelHandler); + } + + if (contentContainerElement) { + contentContainerElement.removeEventListener('copy', contentCopyHandler); } }); @@ -719,72 +767,76 @@ - {:else} -