feat(dragdrop): drag & drop complet de fichiers/dossiers & intégration IA (#89)
This commit is contained in:
@@ -965,6 +965,12 @@ class BooksLM {
|
||||
this._sendMessage();
|
||||
});
|
||||
|
||||
// Setup Drag & Drop for internal items and external files (#89)
|
||||
this._setupDropZones(panel);
|
||||
|
||||
// Save singleton reference on window
|
||||
window.BooksLMInstance = this;
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
@@ -981,6 +987,93 @@ class BooksLM {
|
||||
return Math.max(PANEL_MIN_WIDTH, Math.min(PANEL_MAX_WIDTH, width));
|
||||
}
|
||||
|
||||
_setupDropZones(panel) {
|
||||
const composer = panel.querySelector('.bookslm-composer') || panel;
|
||||
|
||||
const onDragOver = (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
e.dataTransfer.dropEffect = 'copy';
|
||||
composer.classList.add('bookslm-drop-over');
|
||||
};
|
||||
|
||||
const onDragLeave = (e) => {
|
||||
if (composer.contains(e.relatedTarget)) return;
|
||||
composer.classList.remove('bookslm-drop-over');
|
||||
};
|
||||
|
||||
const onDrop = async (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
composer.classList.remove('bookslm-drop-over');
|
||||
|
||||
// Check if internal tree drag
|
||||
const treeData = e.dataTransfer.getData('tree:path') || e.dataTransfer.getData('text/plain');
|
||||
const treeVault = e.dataTransfer.getData('tree:vault');
|
||||
const treeType = e.dataTransfer.getData('tree:type');
|
||||
|
||||
if (treeData && treeVault) {
|
||||
if (treeType === 'directory') {
|
||||
this._addAdhocDir(treeData, treeVault);
|
||||
} else {
|
||||
this._addAdhocFile(treeData, treeVault);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// External files
|
||||
const files = Array.from(e.dataTransfer.files || []);
|
||||
if (files.length > 0) {
|
||||
this.handleExternalDroppedItems(files.map((f) => ({ path: f.name, file: f, isDir: false })));
|
||||
}
|
||||
};
|
||||
|
||||
composer.addEventListener('dragover', onDragOver);
|
||||
composer.addEventListener('dragleave', onDragLeave);
|
||||
composer.addEventListener('drop', onDrop);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle files/folders dropped from outside into BooksLM (#89).
|
||||
*/
|
||||
async handleExternalDroppedItems(items) {
|
||||
if (!this._isOpen) {
|
||||
this.open();
|
||||
}
|
||||
|
||||
for (const item of items) {
|
||||
if (item.isDir) {
|
||||
continue;
|
||||
}
|
||||
const file = item.file;
|
||||
if (!file) continue;
|
||||
|
||||
if (file.type && file.type.startsWith('image/')) {
|
||||
this._addImageFile(file);
|
||||
} else {
|
||||
// Read text/markdown file content
|
||||
try {
|
||||
const text = await new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.onload = () => resolve(String(reader.result || ''));
|
||||
reader.onerror = reject;
|
||||
reader.readAsText(file);
|
||||
});
|
||||
|
||||
// Insert into context files or append to composer
|
||||
this._adhocFiles.push({
|
||||
path: item.path,
|
||||
vault: null,
|
||||
inlineContent: text,
|
||||
});
|
||||
this._renderAttachments();
|
||||
} catch (err) {
|
||||
console.warn('Could not read dropped file as text:', err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_startResize(e) {
|
||||
if (!this._panel || this._isFullscreen) return;
|
||||
e.preventDefault();
|
||||
|
||||
Reference in New Issue
Block a user