170 lines
4.8 KiB
TypeScript
170 lines
4.8 KiB
TypeScript
import chokidar, { FSWatcher } from "chokidar";
|
|
import { BrowserWindow, Notification } from "electron";
|
|
import log from "electron-log/main";
|
|
import fs from "fs";
|
|
import path from "path";
|
|
import errorTypeCheck from "../../util/errorTypeCheck";
|
|
import ipcTypes from "../../util/ipcTypes.json";
|
|
import ImportJob from "../decoder/decoder";
|
|
import store from "../store/store";
|
|
let watcher: FSWatcher | null;
|
|
|
|
async function StartWatcher(): Promise<boolean> {
|
|
const filePaths: string[] = store.get("settings.filepaths") || [];
|
|
|
|
if (filePaths.length === 0) {
|
|
new Notification({
|
|
//TODO: Add Translations
|
|
title: "Watcher cannot start",
|
|
body: "Please set the appropriate file paths and try again.",
|
|
}).show();
|
|
log.warn("Cannot start watcher. No file paths set.");
|
|
return false;
|
|
}
|
|
|
|
if (watcher) {
|
|
try {
|
|
log.info("Trying to close watcher - it already existed.");
|
|
await watcher.close();
|
|
|
|
log.info("Watcher closed successfully!");
|
|
} catch (error) {
|
|
log.error("Error trying to close Watcher.", error);
|
|
}
|
|
}
|
|
|
|
const pollingSettings =
|
|
(store.get("settings.polling") as {
|
|
enabled?: boolean;
|
|
interval?: number;
|
|
}) || {};
|
|
|
|
watcher = chokidar.watch(filePaths, {
|
|
ignored: (filepath, stats) => {
|
|
const p = path.parse(filepath);
|
|
return (
|
|
(!stats?.isFile() && p.ext !== "" && p.ext.toUpperCase() !== ".ENV") ||
|
|
p.name?.toUpperCase() === ".DS_STORE"
|
|
); //Only watch for .ENV files.
|
|
},
|
|
usePolling: pollingSettings.enabled || false,
|
|
interval: pollingSettings.interval || 30000,
|
|
persistent: true,
|
|
ignoreInitial: true,
|
|
awaitWriteFinish: {
|
|
pollInterval: 500,
|
|
stabilityThreshold: 2000,
|
|
},
|
|
});
|
|
|
|
watcher
|
|
.on("add", async function (path) {
|
|
console.log("File", path, "has been added");
|
|
HandleNewFile(path);
|
|
})
|
|
// .on("addDir", function (path) {
|
|
// console.log("Directory", path, "has been added");
|
|
// })
|
|
.on("change", async function (path) {
|
|
console.log("File", path, "has been changed");
|
|
HandleNewFile(path);
|
|
})
|
|
// .on("unlink", function (path) {
|
|
// console.log("File", path, "has been removed");
|
|
// })
|
|
// .on("unlinkDir", function (path) {
|
|
// console.log("Directory", path, "has been removed");
|
|
// })
|
|
.on("error", function (error) {
|
|
log.error("Error in Watcher", errorTypeCheck(error));
|
|
// mainWindow.webContents.send(
|
|
// ipcTypes.toRenderer.watcher.error,
|
|
// errorTypeCheck(error)
|
|
// );
|
|
})
|
|
.on("ready", onWatcherReady);
|
|
// .on("raw", function (event, path, details) {
|
|
// // This event should be triggered everytime something happens.
|
|
// // console.log("Raw event info:", event, path, details);
|
|
// });
|
|
|
|
return true;
|
|
}
|
|
|
|
function removeWatcherPath(path: string): void {
|
|
if (watcher) {
|
|
watcher.unwatch(path);
|
|
log.debug(`Stopped watching path: ${path}`);
|
|
}
|
|
}
|
|
|
|
function addWatcherPath(path: string | string[]): void {
|
|
if (watcher) {
|
|
watcher.add(path);
|
|
log.debug(`Started watching path: ${path}`);
|
|
}
|
|
}
|
|
|
|
function onWatcherReady(): void {
|
|
if (watcher) {
|
|
const mainWindow = BrowserWindow.getAllWindows()[0]; //TODO: Filter to only main window once a proper key has been set.
|
|
new Notification({
|
|
title: "Watcher Started",
|
|
body: "Newly exported estimates will be automatically uploaded.",
|
|
}).show();
|
|
log.info("Confirmed watched paths:", watcher.getWatched());
|
|
mainWindow.webContents.send(ipcTypes.toRenderer.watcher.started);
|
|
}
|
|
}
|
|
|
|
async function StopWatcher(): Promise<boolean> {
|
|
const mainWindow = BrowserWindow.getAllWindows()[0]; //TODO: Filter to only main window once a proper key has been set.
|
|
|
|
if (watcher) {
|
|
await watcher.close();
|
|
log.info("Watcher stopped.");
|
|
mainWindow.webContents.send(ipcTypes.toRenderer.watcher.stopped);
|
|
|
|
new Notification({
|
|
title: "Watcher Stopped",
|
|
body: "Estimates will not be automatically uploaded.",
|
|
}).show();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
async function HandleNewFile(path): Promise<void> {
|
|
log.log("Received a new file", path);
|
|
await ImportJob(path);
|
|
}
|
|
|
|
function GetAllEnvFiles(): string[] {
|
|
const directories = store.get("settings.filepaths") as string[];
|
|
const files: string[] = [];
|
|
directories.forEach((directory) => {
|
|
try {
|
|
const envFiles = fs
|
|
.readdirSync(directory)
|
|
.filter((file: string) => file.toLowerCase().endsWith(".env"));
|
|
envFiles.forEach((file) => {
|
|
const fullPath = path.join(directory, file);
|
|
files.push(fullPath);
|
|
});
|
|
} catch (error) {
|
|
log.error(`Failed to read directory ${directory}:`, error);
|
|
throw error;
|
|
}
|
|
});
|
|
return files;
|
|
}
|
|
|
|
export {
|
|
addWatcherPath,
|
|
GetAllEnvFiles,
|
|
removeWatcherPath,
|
|
StartWatcher,
|
|
StopWatcher,
|
|
watcher,
|
|
};
|