Commit c79e85c3 by Яков

fix drag and drop

parent dd70d3d0
......@@ -29,7 +29,7 @@ import Uploader from './components/Uploader'
import Video from './extensions/Video'
import Iframe from './extensions/Iframe'
// import CustomLink from './extensions/CustomLink'
import DragAndDrop from './extensions/DragAndDrop'
import { DragAndDrop } from './extensions/DragAndDrop'
import { useReactMediaRecorder } from 'react-media-recorder'
import axios from 'axios'
import ReactStopwatch from 'react-stopwatch'
......
import { Extension } from "@tiptap/core";
import { Plugin, PluginKey } from 'prosemirror-state'
import axios from 'axios'
import { Extension } from '@tiptap/core';
import { Plugin, PluginKey } from 'prosemirror-state';
import { EditorView } from 'prosemirror-view';
import axios from 'axios';
const upload = async (file) => {
let formData = new FormData();
export const DragAndDrop = Extension.create({
name: 'dragAndDrop',
addOptions() {
return {
uploadUrl: '', // URL для загрузки файлов
uploadHandler: null, // Альтернативный обработчик загрузки
types: ['image'], // Поддерживаемые типы файлов
headers: {}, // Дополнительные заголовки
};
},
addProseMirrorPlugins() {
if (!this.options.uploadUrl && !this.options.uploadHandler) {
return [];
}
const isRealFile = (item) => {
// Игнорируем текстовые форматы и специфичные для Word
if (item.type.startsWith('text/') ||
item.type.startsWith('application/x-mso') ||
item.type === 'text/html' ||
item.type === 'text/rtf') {
return false;
}
// Разрешенные файловые типы
return [
'image/', 'video/', 'audio/',
'application/octet-stream',
'application/pdf',
'application/zip'
].some(type => item.type.startsWith(type));
};
const uploadFile = async (file) => {
if (this.options.uploadHandler) {
return await this.options.uploadHandler(file);
}
const formData = new FormData();
formData.append('file', file);
const headers = {'Content-Type': 'multipart/form-data'};
const response = await axios.post(global.uploadUrl, formData, {headers: headers} );
const headers = {
'Content-Type': 'multipart/form-data',
...this.options.headers
};
const response = await axios.post(
this.options.uploadUrl,
formData,
{ headers }
);
if (!response.data) throw new Error('Upload failed');
return response.data.file_path;
};
};
const handleUpload = async (file, view, pos) => {
try {
const filePath = await uploadFile(file);
if (!filePath) return;
const { state } = view;
const { tr } = state;
let node;
if (file.type.startsWith('image/') && this.options.types.includes('image')) {
node = state.schema.nodes.image?.create({ src: filePath });
} else if (file.type.startsWith('video/') && this.options.types.includes('video')) {
node = state.schema.nodes.video?.create({ src: filePath });
} else if (file.type.startsWith('audio/') && this.options.types.includes('audio')) {
node = state.schema.nodes.audio?.create({ src: filePath });
}
if (node) {
view.dispatch(tr.insert(pos, node));
}
} catch (error) {
console.error('Upload error:', error);
}
};
const DragAndDrop = Extension.create({
name: 'customDragAndDrop',
addProseMirrorPlugins() {
return [
new Plugin({
key: new PluginKey('customDragAndDrop'),
key: new PluginKey('dragAndDrop'),
props: {
handleDOMEvents: {
async paste (view, event) {
console.log('Clipboard types:', event.clipboardData.types);
console.log('HTML data length:', event.clipboardData.getData('text/html').length);
// let items = (event.clipboardData || event.originalEvent.clipboardData).items;
//
// for (let i = 0; i < items.length; i++){
// const { schema } = view.state;
// const image = items[i].getAsFile();
//
// if (!image) {
// return
// }
//
// // event.preventDefault();
// const imageSrc = await upload(image);
//
// const node = schema.nodes.image.create({
// src: imageSrc,
// });
// const transaction = view.state.tr.replaceSelectionWith(node);
// view.dispatch(transaction)
// }
},
async drop (view, event) {
const hasFiles = event.dataTransfer.files.length > 0;
// Другой способ достать текст
// console.log(event.dataTransfer.items[0].getAsString( (i) => {
// console.log(i)
// }));
// console.log(hasFiles)
if (hasFiles) {
// event.preventDefault();
const images = event.dataTransfer.files;
const {schema} = view.state;
const coordinates = view.posAtCoords({left: event.clientX, top: event.clientY});
for (let i = 0; i < images.length; i++) {
const imageSrc = await upload(images[i]);
if (imageSrc) {
const node = schema.nodes.image.create({
src: imageSrc
drop(view, event) {
const files = event.dataTransfer?.files;
if (!files || files.length === 0) return false;
const coordinates = view.posAtCoords({
left: event.clientX,
top: event.clientY,
});
const transaction = view.state.tr.insert(coordinates.pos, node);
view.dispatch(transaction)
}
}
}
}
}
}
})
]
if (!coordinates) return false;
event.preventDefault();
Array.from(files).forEach(file => {
if (isRealFile({ kind: 'file', type: file.type })) {
handleUpload(file, view, coordinates.pos);
}
});
});
export default DragAndDrop;
return true;
},
},
handlePaste(view, event) {
const items = event.clipboardData?.items;
if (!items) return false;
// Проверяем наличие реальных файлов
const files = Array.from(items)
.filter(item => item.kind === 'file' && isRealFile(item))
.map(item => item.getAsFile())
.filter(Boolean);
if (files.length === 0) return false;
event.preventDefault();
const { state } = view;
const pos = state.selection.$from.pos;
files.forEach(file => {
handleUpload(file, view, pos);
});
return true;
},
},
}),
];
},
});
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment