const { dialog } = require('electron'); const path = require('node:path'); const express = require('express'); const bodyParser = require('body-parser'); const http = require('http'); const socketIO = require('socket.io'); const fetch = require('electron-fetch').default const fs = require('node:fs'); const os = require('os'); const chokidar = require('chokidar'); const HOME_DIR = os.homedir(); const BASE_PATH = '../build/app'; const CONFIG_PATH = path.join(HOME_DIR, "/.config/newton/"); const SETTINGS_CONFIG_PATH = path.join(CONFIG_PATH, "/settings.json"); const LSP_CONFIG_PATH = path.join(BASE_PATH, "/resources/lsp-servers-config.json"); const IPC_SERVER_IP = "127.0.0.1"; let window = null; let watcher = null; let ipcServer = null; let ipcServerPort = "4563"; let ipcServerURL = `http://${IPC_SERVER_IP}:${ipcServerPort}`; const getIconPath = () => { return path.join(CONFIG_PATH, "./icons/newton.png"); } const getSettingsConfigData = () => { return getFileContents(SETTINGS_CONFIG_PATH); } const getLspConfigData = () => { const config = getFileContents(LSP_CONFIG_PATH, useRelativePath = true); return config.replaceAll("{user.home}", HOME_DIR); } const getFileContents = (_path, useRelativePath = false) => { console.log(`Getting Contents For: ${_path}`); try { if (!useRelativePath) { return fs.readFileSync(_path, 'utf8'); } else { let fpath = path.join(__dirname, _path); watcher.add(fpath); return fs.readFileSync(fpath, 'utf8'); } } catch(err) { return `{"message": {"type": "error", "text": "Error: Could not read ${_path}"}}`; } } const setWindow = (win) => { window = win; } const saveFile = (fpath, content) => { fs.writeFile(fpath, content, (err) => { if (!err) return console.error("An error ocurred writing to the file " + err.message); }); } const saveFileAs = (content) => { dialog.showSaveDialog().then((response) => { if (response.canceled) { console.log("You didn't save the file"); return; } saveFile(response.filePath, content); watcher.add(response.filePath); }); } const openFiles = (startPath) => { dialog.showOpenDialog( { title: "Open File(s):", defaultPath: (startPath) ? startPath : HOME_DIR, filters: [ { name: "All Files", extensions: ["*"] }, { name: "c", extensions: [".h", ".c"] }, { name: "cpp", extensions: ["hpp", "cpp"] }, { name: "html", extensions: ["js", "css", "scss", "html", "ts"] }, { name: "java", extensions: ["java"] }, { name: "python", extensions: ["py", "pyc"] }, { name: "rust", extensions: ["r", "rc"] }, { name: "text", extensions: ["txt", "log", "md"] }, { name: "go", extensions: ["go"] }, ], properties: [ 'openFile', 'multiSelections' ] } ).then((response) => { if (response.canceled) { console.log("Canceled file open request..."); return; } window.webContents.send('load-files', response.filePaths); watcher.add(response.filePaths); }); } const loadFilesWatcher = () => { watcher = chokidar.watch([], {}); watcher.on('change', (fpath) => { console.debug("File (changed) : ", fpath); }).on('unlink', (fpath) => { console.debug("File (unlinked) : ", fpath); }); } const unwatchFile = async (fpath) => { console.log("File (unwatch) : ", fpath); await watcher.unwatch(fpath); } const closeFile = (fpath) => { unwatchFile(fpath); } const loadIPCServer = (fpath) => { const app = express(); ipcServer = http.createServer(app); const io = socketIO(ipcServer); app.use(bodyParser.json()); app.use( bodyParser.urlencoded({ extended: true, }), ); app.get("/is-up", (req, res) => { res.status(200).send('yes'); }); app.post("/load-files", (req, res) => { console.debug("Load File(s) : ", req.body); window.webContents.send('load-files', req.body); res.status(200).send(''); }); ipcServer.listen(ipcServerPort, () => { console.debug(`IPCServer is up on port ${ipcServerPort}`); }); } const isIPCServerUp = async () => { const response = await fetch(`${ipcServerURL}/is-up`).catch((err) => { console.debug(err); return { text: () => { return "no"; } } }); const body = await response.text(); return (body == "yes") ? true : false; } const sendFilesToIPC = async (files) => { let request = { method: "POST", body: JSON.stringify(files), headers: { 'Content-Type': 'application/json' } }; await fetch(`${ipcServerURL}/load-files`, request); } module.exports = { newtonFs: { openFiles: openFiles, saveFile: saveFile, saveFileAs: saveFileAs, closeFile: closeFile, getIconPath: getIconPath, getFileContents: getFileContents, getLspConfigData: getLspConfigData, getSettingsConfigData: getSettingsConfigData, loadIPCServer: loadIPCServer, isIPCServerUp: isIPCServerUp, sendFilesToIPC: sendFilesToIPC, setWindow: setWindow, loadFilesWatcher: loadFilesWatcher, unwatchFile: unwatchFile, } };