refac
This commit is contained in:
@@ -2814,7 +2814,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class=" pb-2 z-10">
|
<div class=" pb-2 {dragged ? 'z-0' : 'z-10'}">
|
||||||
<MessageInput
|
<MessageInput
|
||||||
bind:this={messageInput}
|
bind:this={messageInput}
|
||||||
{history}
|
{history}
|
||||||
|
|||||||
@@ -55,6 +55,7 @@
|
|||||||
import { uploadFile } from '$lib/apis/files';
|
import { uploadFile } from '$lib/apis/files';
|
||||||
import { generateAutoCompletion } from '$lib/apis';
|
import { generateAutoCompletion } from '$lib/apis';
|
||||||
import { deleteFileById } from '$lib/apis/files';
|
import { deleteFileById } from '$lib/apis/files';
|
||||||
|
import { getChatById } from '$lib/apis/chats';
|
||||||
import { getSessionUser } from '$lib/apis/auths';
|
import { getSessionUser } from '$lib/apis/auths';
|
||||||
import { getTools } from '$lib/apis/tools';
|
import { getTools } from '$lib/apis/tools';
|
||||||
|
|
||||||
@@ -806,8 +807,11 @@
|
|||||||
const onDragOver = (e: DragEvent) => {
|
const onDragOver = (e: DragEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
// Check if a file is being dragged.
|
// Check if a file or a sidebar chat item is being dragged.
|
||||||
if (e.dataTransfer?.types?.includes('Files')) {
|
if (
|
||||||
|
e.dataTransfer?.types?.includes('Files') ||
|
||||||
|
e.dataTransfer?.types?.includes('text/plain')
|
||||||
|
) {
|
||||||
dragged = true;
|
dragged = true;
|
||||||
} else {
|
} else {
|
||||||
dragged = false;
|
dragged = false;
|
||||||
@@ -825,6 +829,35 @@
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
console.log(e);
|
console.log(e);
|
||||||
|
|
||||||
|
// Check if the dropped data is a sidebar chat item
|
||||||
|
const textData = e.dataTransfer?.getData('text/plain');
|
||||||
|
if (textData) {
|
||||||
|
try {
|
||||||
|
const data = JSON.parse(textData);
|
||||||
|
if (data.type === 'chat' && data.id) {
|
||||||
|
// Fetch the chat to get its title, then add as a reference chat
|
||||||
|
const chat = await getChatById(localStorage.token, data.id);
|
||||||
|
if (chat) {
|
||||||
|
const chatItem = {
|
||||||
|
type: 'chat',
|
||||||
|
id: chat.id,
|
||||||
|
name: chat.title,
|
||||||
|
collection_name: '',
|
||||||
|
status: 'processed'
|
||||||
|
};
|
||||||
|
if (!files.find((f) => f.id === chatItem.id)) {
|
||||||
|
files = [...files, chatItem];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dragged = false;
|
||||||
|
e.stopPropagation();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (_) {
|
||||||
|
// Not valid JSON — fall through to file handling
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (e.dataTransfer?.files) {
|
if (e.dataTransfer?.files) {
|
||||||
const inputFiles = Array.from(e.dataTransfer?.files);
|
const inputFiles = Array.from(e.dataTransfer?.files);
|
||||||
if (inputFiles && inputFiles.length > 0) {
|
if (inputFiles && inputFiles.length > 0) {
|
||||||
@@ -1022,8 +1055,8 @@
|
|||||||
|
|
||||||
dropzoneElement = document.getElementById('chat-pane');
|
dropzoneElement = document.getElementById('chat-pane');
|
||||||
if (dropzoneElement) {
|
if (dropzoneElement) {
|
||||||
dropzoneElement.addEventListener('dragover', onDragOver);
|
dropzoneElement.addEventListener('dragover', onDragOver, true);
|
||||||
dropzoneElement.addEventListener('drop', onDrop);
|
dropzoneElement.addEventListener('drop', onDrop, true);
|
||||||
dropzoneElement.addEventListener('dragleave', onDragLeave);
|
dropzoneElement.addEventListener('dragleave', onDragLeave);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1041,8 +1074,8 @@
|
|||||||
window.removeEventListener('blur', onBlur);
|
window.removeEventListener('blur', onBlur);
|
||||||
|
|
||||||
if (dropzoneElement) {
|
if (dropzoneElement) {
|
||||||
dropzoneElement.removeEventListener('dragover', onDragOver);
|
dropzoneElement.removeEventListener('dragover', onDragOver, true);
|
||||||
dropzoneElement.removeEventListener('drop', onDrop);
|
dropzoneElement.removeEventListener('drop', onDrop, true);
|
||||||
dropzoneElement.removeEventListener('dragleave', onDragLeave);
|
dropzoneElement.removeEventListener('dragleave', onDragLeave);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
<div
|
<div
|
||||||
bind:this={popupElement}
|
bind:this={popupElement}
|
||||||
class="fixed top-0 left-0 w-screen h-[100dvh] z-50 touch-none pointer-events-none"
|
class="fixed top-0 left-0 w-screen h-[100dvh] z-[99999] touch-none pointer-events-none"
|
||||||
>
|
>
|
||||||
<div class=" absolute text-white z-99999" style="top: {y + 10}px; left: {x + 10}px;">
|
<div class=" absolute text-white z-99999" style="top: {y + 10}px; left: {x + 10}px;">
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
|
|||||||
@@ -801,8 +801,8 @@
|
|||||||
if (!editor || !editor.view || editor.isDestroyed) {
|
if (!editor || !editor.view || editor.isDestroyed) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// default logic
|
// Only show when editor is focused and text is selected
|
||||||
return from !== to;
|
return view.hasFocus() && from !== to;
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
FloatingMenu.configure({
|
FloatingMenu.configure({
|
||||||
@@ -905,6 +905,24 @@
|
|||||||
},
|
},
|
||||||
editorProps: {
|
editorProps: {
|
||||||
attributes: { id },
|
attributes: { id },
|
||||||
|
handleDrop: (view, event) => {
|
||||||
|
// Intercept sidebar chat item drops to prevent ProseMirror
|
||||||
|
// from inserting the raw JSON as text. The actual handling
|
||||||
|
// (adding as Reference Chat) is done by MessageInput's onDrop.
|
||||||
|
const textData = event.dataTransfer?.getData('text/plain');
|
||||||
|
if (textData) {
|
||||||
|
try {
|
||||||
|
const data = JSON.parse(textData);
|
||||||
|
if (data.type === 'chat' && data.id) {
|
||||||
|
// Swallow the drop — let the parent handler deal with it
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch (_) {
|
||||||
|
// Not JSON, let ProseMirror handle normally
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
handlePaste: (view, event) => {
|
handlePaste: (view, event) => {
|
||||||
// Force plain-text pasting when richText === false
|
// Force plain-text pasting when richText === false
|
||||||
if (!richText) {
|
if (!richText) {
|
||||||
@@ -1170,6 +1188,18 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
onSelectionUpdate: onSelectionUpdate,
|
onSelectionUpdate: onSelectionUpdate,
|
||||||
|
onBlur: () => {
|
||||||
|
// Force-hide floating menus when editor loses focus.
|
||||||
|
// shouldShow alone isn't enough because it only runs on transactions.
|
||||||
|
if (bubbleMenuElement) {
|
||||||
|
bubbleMenuElement.style.visibility = 'hidden';
|
||||||
|
bubbleMenuElement.style.opacity = '0';
|
||||||
|
}
|
||||||
|
if (floatingMenuElement) {
|
||||||
|
floatingMenuElement.style.visibility = 'hidden';
|
||||||
|
floatingMenuElement.style.opacity = '0';
|
||||||
|
}
|
||||||
|
},
|
||||||
enableInputRules: richText,
|
enableInputRules: richText,
|
||||||
enablePasteRules: richText
|
enablePasteRules: richText
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user