diff --git a/electron/main/Files/Filesystem.ts b/electron/main/Files/Filesystem.ts index 171b8279..f0591882 100644 --- a/electron/main/Files/Filesystem.ts +++ b/electron/main/Files/Filesystem.ts @@ -9,6 +9,14 @@ import { removeTreeFromTable, } from "../database/Table"; +export const markdownExtensions = [ + ".md", + ".markdown", + ".mdown", + ".mkdn", + ".mkd", +]; + export function GetFilesInfoList( directory: string, extensionsToFilterFor?: string[] diff --git a/electron/main/Files/registerFilesHandler.ts b/electron/main/Files/registerFilesHandler.ts new file mode 100644 index 00000000..7d3fb84b --- /dev/null +++ b/electron/main/Files/registerFilesHandler.ts @@ -0,0 +1,82 @@ +import { BrowserWindow, ipcMain, IpcMainInvokeEvent } from "electron"; +import { AIModelConfig, StoreKeys, StoreSchema } from "../Store/storeConfig"; +import Store from "electron-store"; +import { validateAIModelConfig } from "../llm/llmConfig"; +import { FSWatcher } from "fs"; +import * as path from "path"; +import { FileInfoTree } from "./Types"; +import { + GetFilesInfoTree, + markdownExtensions, + orchestrateEntryMove, + writeFileSyncRecursive, +} from "./Filesystem"; +import * as fs from "fs"; +import { RagnoteTable, updateNoteInTable } from "../database/Table"; + +export const registerFileHandlers = ( + store: Store, + dbTable: RagnoteTable, + win: BrowserWindow +) => { + ipcMain.handle("join-path", (event, ...args) => { + return path.join(...args); + }); + + ipcMain.handle("get-files", async (): Promise => { + const directoryPath: string = store.get(StoreKeys.UserDirectory); + if (!directoryPath) return []; + + const files: FileInfoTree = GetFilesInfoTree(directoryPath); + return files; + }); + + ipcMain.handle( + "read-file", + async (event, filePath: string): Promise => { + return fs.readFileSync(filePath, "utf-8"); + } + ); + + ipcMain.handle( + "write-file", + async (event, filePath: string, content: string): Promise => { + console.log("writing file", filePath); + // so here we can use the table we've created to add and remove things from the database. And all of the methods can be async to not hold up any threads + await updateNoteInTable(dbTable, filePath, content); + await fs.writeFileSync(filePath, content, "utf-8"); + win?.webContents.send("vector-database-update"); + } + ); + + ipcMain.handle( + "create-file", + async (event, filePath: string, content: string): Promise => { + console.log("Creating file", filePath); + if (!fs.existsSync(filePath)) { + // If the file does not exist, create it + writeFileSyncRecursive(filePath, content, "utf-8"); + } else { + // If the file exists, log a message and do nothing + console.log("File already exists:", filePath); + } + } + ); + + ipcMain.handle( + "move-file-or-dir", + async (event, sourcePath: string, destinationPath: string) => { + try { + orchestrateEntryMove( + dbTable, + sourcePath, + destinationPath, + markdownExtensions + ); + } catch (error) { + console.error("Error moving file or directory:", error); + return { success: false, error: error }; + } + } + ); +}; diff --git a/electron/main/index.ts b/electron/main/index.ts index 679a1c3c..2c0a9da0 100644 --- a/electron/main/index.ts +++ b/electron/main/index.ts @@ -4,7 +4,6 @@ import { join } from "node:path"; import { update } from "./update"; import Store from "electron-store"; import * as path from "path"; -import * as fs from "fs"; import { AIModelConfig, StoreKeys, StoreSchema } from "./Store/storeConfig"; import * as lancedb from "vectordb"; @@ -17,6 +16,7 @@ import { import { FSWatcher } from "fs"; import { GetFilesInfoTree, + markdownExtensions, orchestrateEntryMove, startWatchingDirectory, updateFileListForRenderer, @@ -27,6 +27,7 @@ import { FileInfoTree } from "./Files/Types"; import { registerDBSessionHandlers } from "./database/dbSessionHandlers"; import { validateAIModelConfig } from "./llm/llmConfig"; import { registerStoreHandlers } from "./Store/storeHandlers"; +import { registerFileHandlers } from "./Files/registerFilesHandler"; const store = new Store(); // const user = store.get("user"); @@ -58,8 +59,6 @@ if (!app.requestSingleInstanceLock()) { process.exit(0); } -const markdownExtensions = [".md", ".markdown", ".mdown", ".mkdn", ".mkd"]; - // Remove electron security warnings // This warning only shows in development mode // Read more on https://www.electronjs.org/docs/latest/tutorial/security @@ -126,6 +125,7 @@ async function createWindow() { registerLLMSessionHandlers(store); registerDBSessionHandlers(dbTable); registerStoreHandlers(store, fileWatcher); + registerFileHandlers(store, dbTable, win); } app.whenReady().then(async () => { @@ -213,65 +213,3 @@ ipcMain.on("index-files-in-directory", async (event, userDirectory: string) => { } event.sender.send("indexing-complete", "success"); }); - -ipcMain.handle("join-path", (event, ...args) => { - return path.join(...args); -}); - -ipcMain.handle("get-files", async (): Promise => { - const directoryPath: string = store.get(StoreKeys.UserDirectory); - if (!directoryPath) return []; - - const files: FileInfoTree = GetFilesInfoTree(directoryPath); - return files; -}); - -ipcMain.handle( - "read-file", - async (event, filePath: string): Promise => { - return fs.readFileSync(filePath, "utf-8"); - } -); - -ipcMain.handle( - "write-file", - async (event, filePath: string, content: string): Promise => { - console.log("writing file", filePath); - // so here we can use the table we've created to add and remove things from the database. And all of the methods can be async to not hold up any threads - await updateNoteInTable(dbTable, filePath, content); - await fs.writeFileSync(filePath, content, "utf-8"); - win?.webContents.send("vector-database-update"); - } -); - -// create new file handler: -ipcMain.handle( - "create-file", - async (event, filePath: string, content: string): Promise => { - console.log("Creating file", filePath); - if (!fs.existsSync(filePath)) { - // If the file does not exist, create it - writeFileSyncRecursive(filePath, content, "utf-8"); - } else { - // If the file exists, log a message and do nothing - console.log("File already exists:", filePath); - } - } -); - -ipcMain.handle( - "move-file-or-dir", - async (event, sourcePath: string, destinationPath: string) => { - try { - orchestrateEntryMove( - dbTable, - sourcePath, - destinationPath, - markdownExtensions - ); - } catch (error) { - console.error("Error moving file or directory:", error); - return { success: false, error: error }; - } - } -); diff --git a/src/components/File/NewNote.tsx b/src/components/File/NewNote.tsx index 84938dec..775ea5d4 100644 --- a/src/components/File/NewNote.tsx +++ b/src/components/File/NewNote.tsx @@ -17,6 +17,9 @@ const NewNoteComponent: React.FC = ({ const [fileName, setFileName] = useState(""); const sendNewNoteMsg = async () => { + if (!fileName) { + return; + } const notePath = await window.files.joinPath( window.electronStore.getUserDirectory(), fileName @@ -59,3 +62,16 @@ const NewNoteComponent: React.FC = ({ }; export default NewNoteComponent; + +// function appendExtensionIfMissing(filename: string, extensions: string[]): string { +// // Check if the filename ends with any of the provided extensions +// const hasExtension = extensions.some(ext => filename.endsWith(ext)); + +// // If the filename already has one of the extensions, return it as is +// if (hasExtension) { +// return filename; +// } + +// // If not, append the first extension from the list to the filename +// return filename + extensions[0]; +// }