diff --git a/electron/main/common/windowManager.ts b/electron/main/common/windowManager.ts index 36c559a7..849c0a4b 100644 --- a/electron/main/common/windowManager.ts +++ b/electron/main/common/windowManager.ts @@ -87,7 +87,18 @@ class WindowsManager { } appendNewErrorToDisplayInWindow(errorString: string) { - this.errorStringsToSendWindow.push(errorString) + let errorSent = false + const activeWindows = BrowserWindow.getAllWindows() + activeWindows.forEach((window) => { + if (!window.webContents.isLoading()) { + window.webContents.send('error-to-display-in-window', errorString) + errorSent = true + } + }) + + if (!errorSent) { + this.errorStringsToSendWindow.push(errorString) + } } getAndClearErrorStrings(): string[] { diff --git a/electron/main/filesystem/filesystem.ts b/electron/main/filesystem/filesystem.ts index fc64a5ab..c5618b8c 100644 --- a/electron/main/filesystem/filesystem.ts +++ b/electron/main/filesystem/filesystem.ts @@ -178,7 +178,7 @@ export function readFile(filePath: string): string { return data } -export const moveFileOrDirectoryInFileSystem = async (sourcePath: string, destinationPath: string): Promise => { +export const moveFileOrDirectory = async (sourcePath: string, destinationPath: string): Promise => { await fsPromises.access(sourcePath) let destinationStats @@ -187,6 +187,7 @@ export const moveFileOrDirectoryInFileSystem = async (sourcePath: string, destin } catch (error) { // Error means destination path does not exist, which is fine } + let resolvedDestinationPath = destinationPath if (destinationStats && destinationStats.isFile()) { resolvedDestinationPath = path.dirname(destinationPath) @@ -195,7 +196,17 @@ export const moveFileOrDirectoryInFileSystem = async (sourcePath: string, destin await fsPromises.mkdir(resolvedDestinationPath, { recursive: true }) const newPath = path.join(resolvedDestinationPath, path.basename(sourcePath)) - await fsPromises.rename(sourcePath, newPath) + + try { + await fsPromises.access(newPath) + throw new Error(`A file already exists at destination: ${newPath}`) + } catch (error) { + if ((error as NodeJS.ErrnoException).code === 'ENOENT') { + await fsPromises.rename(sourcePath, newPath) + } else { + throw error + } + } return newPath } diff --git a/electron/main/vector-database/tableHelperFunctions.ts b/electron/main/vector-database/tableHelperFunctions.ts index 26b1c637..0679e602 100644 --- a/electron/main/vector-database/tableHelperFunctions.ts +++ b/electron/main/vector-database/tableHelperFunctions.ts @@ -5,7 +5,7 @@ import { GetFilesInfoList, GetFilesInfoTree, flattenFileInfoTree, - moveFileOrDirectoryInFileSystem, + moveFileOrDirectory, readFile, } from '../filesystem/filesystem' import { FileInfo, FileInfoTree } from '../filesystem/types' @@ -160,11 +160,11 @@ export const addFileTreeToDBTable = async (dbTable: LanceDBTableWrapper, fileTre export const orchestrateEntryMove = async (table: LanceDBTableWrapper, sourcePath: string, destinationPath: string) => { const fileSystemTree = GetFilesInfoTree(sourcePath) await removeFileTreeFromDBTable(table, fileSystemTree) - moveFileOrDirectoryInFileSystem(sourcePath, destinationPath).then((newDestinationPath) => { - if (newDestinationPath) { - addFileTreeToDBTable(table, GetFilesInfoTree(newDestinationPath)) - } - }) + + const newDestinationPath = await moveFileOrDirectory(sourcePath, destinationPath) + if (newDestinationPath) { + await addFileTreeToDBTable(table, GetFilesInfoTree(newDestinationPath)) + } } export function formatTimestampForLanceDB(date: Date): string { diff --git a/src/components/Sidebars/FileSideBar/FileSidebar.tsx b/src/components/Sidebars/FileSideBar/FileSidebar.tsx index b9bf2034..5c52ce6b 100644 --- a/src/components/Sidebars/FileSideBar/FileSidebar.tsx +++ b/src/components/Sidebars/FileSideBar/FileSidebar.tsx @@ -4,6 +4,7 @@ import { FixedSizeList } from 'react-window' import { isFileNodeDirectory } from '@shared/utils' import { useFileContext } from '@/contexts/FileContext' import FileItemRows from './FileItemRows' +import { moveFile } from '@/lib/file' const getFilesAndIndentationsForSidebar = ( files: FileInfoTree, @@ -33,6 +34,19 @@ const FileSidebar: React.FC = ({ lheight }) => { const [listHeight, setListHeight] = useState(lheight ?? window.innerHeight - 50) const { vaultFilesTree, expandedDirectories } = useFileContext() + const handleDrop = async (e: React.DragEvent) => { + e.preventDefault() + e.stopPropagation() + const sourcePath = e.dataTransfer.getData('text/plain') + const destinationPath = await window.electronStore.getVaultDirectoryForWindow() + moveFile(sourcePath, destinationPath) + } + + const handleDragOver = (e: React.DragEvent) => { + e.preventDefault() + e.stopPropagation() + } + useEffect(() => { const updateHeight = () => { setListHeight(lheight ?? window.innerHeight - 50) @@ -47,13 +61,12 @@ const FileSidebar: React.FC = ({ lheight }) => { const itemCount = filesAndIndentations.length return ( -
+