Work towards it

This commit is contained in:
Manav Rathi 2024-04-18 16:18:01 +05:30
parent 8a728abffe
commit 275b763648
No known key found for this signature in database
3 changed files with 82 additions and 40 deletions

View file

@ -5,7 +5,6 @@ import path from "node:path";
import { FolderWatch } from "../../types/ipc";
import log from "../log";
import { watchStore } from "../stores/watch";
import { getElectronFile } from "./fs";
/**
* Create and return a new file system watcher.
@ -16,42 +15,41 @@ import { getElectronFile } from "./fs";
* pertinent file system events.
*/
export const createWatcher = (mainWindow: BrowserWindow) => {
const mappings = getWatchMappings();
const folderPaths = mappings.map((mapping) => {
return mapping.folderPath;
});
const send = (eventName: string) => (path: string) =>
mainWindow.webContents.send(eventName, ...eventData(path));
const folderPaths = folderWatches().map((watch) => watch.folderPath);
const watcher = chokidar.watch(folderPaths, {
awaitWriteFinish: true,
});
watcher
.on("add", async (path) => {
mainWindow.webContents.send(
"watch-add",
await getElectronFile(normalizeToPOSIX(path)),
);
})
.on("unlink", (path) => {
mainWindow.webContents.send("watch-unlink", normalizeToPOSIX(path));
})
.on("unlinkDir", (path) => {
mainWindow.webContents.send(
"watch-unlink-dir",
normalizeToPOSIX(path),
);
})
.on("error", (error) => {
log.error("Error while watching files", error);
});
.on("add", send("addFile"))
.on("unlink", send("removeFile"))
.on("unlinkDir", send("removeDir"))
.on("error", (error) => log.error("Error while watching files", error));
return watcher;
};
const eventData = (path: string): [string, FolderWatch] => {
path = posixPath(path);
const watch = folderWatches().find((watch) =>
path.startsWith(watch.folderPath + "/"),
);
if (!watch) throw new Error(`No folder watch was found for path ${path}`);
return [path, watch];
};
/**
* Convert a file system {@link filePath} that uses the local system specific
* path separators into a path that uses POSIX file separators.
*/
const normalizeToPOSIX = (filePath: string) =>
const posixPath = (filePath: string) =>
filePath.split(path.sep).join(path.posix.sep);
export const findFiles = async (dirPath: string) => {
@ -156,10 +154,10 @@ export function updateWatchMappingIgnoredFiles(
setWatchMappings(watchMappings);
}
export function getWatchMappings() {
export const folderWatches = () => {
const mappings = watchStore.get("mappings") ?? [];
return mappings;
}
};
function setWatchMappings(watchMappings: WatchStoreType["mappings"]) {
watchStore.set("mappings", watchMappings);

View file

@ -96,7 +96,7 @@ class FolderWatcher {
this.setCollectionName = setCollectionName;
this.syncWithRemote = syncWithRemote;
this.setWatchFolderServiceIsRunning = setWatchFolderServiceIsRunning;
this.setupWatcherFunctions();
this.registerListeners();
await this.syncWithDisk();
}
@ -115,7 +115,7 @@ class FolderWatcher {
* collection do files belonging to nested directories go to.
*/
async addWatch(folderPath: string, mapping: CollectionMapping) {
await ensureElectron().watch.add(folderPath, mapping);
await ensureElectron().watcher.add(folderPath, mapping);
this.syncWithDisk();
}
@ -165,8 +165,14 @@ class FolderWatcher {
this.trashingDirQueue.push(path);
}
private setupWatcherFunctions() {
ensureElectron().registerWatcherFunctions(
private registerListeners() {
const watch = ensureElectron().watcher;
// [Note: File renames during folder watch]
//
// Renames come as two file system events - an `onAddFile` + an
// `onRemoveFile` - in an arbitrary order.
watch.onAddFile(
diskFileAddedCallback,
diskFileRemovedCallback,
diskFolderRemovedCallback,
@ -594,9 +600,9 @@ interface WatchEvent {
filePath: string;
}
async function diskFileAddedCallback(file: ElectronFile) {
const onAddFile = async (path: string) => {
const collectionNameAndFolderPath =
await watcher.getCollectionNameAndFolderPath(file.path);
await watcher.getCollectionNameAndFolderPath(path);
if (!collectionNameAndFolderPath) {
return;
@ -604,13 +610,12 @@ async function diskFileAddedCallback(file: ElectronFile) {
const { collectionName, folderPath } = collectionNameAndFolderPath;
const event: EventQueueItem = {
type: "upload",
watcher.pushEvent({
action: "upload",
collectionName,
folderPath,
path: file.path,
};
watcher.pushEvent(event);
});
}
async function diskFileRemovedCallback(filePath: string) {
@ -701,7 +706,7 @@ const deduceEvents = async (
for (const watch of activeWatches) {
const folderPath = watch.folderPath;
const paths = (await electron.watch.findFiles(folderPath))
const paths = (await electron.watcher.findFiles(folderPath))
// Filter out hidden files (files whose names begins with a dot)
.filter((path) => !isHiddenFile(path));
@ -741,7 +746,7 @@ const isSyncedOrIgnoredPath = (path: string, watch: FolderWatch) =>
const collectionNameForPath = (filePath: string, watch: FolderWatch) =>
watch.collectionMapping == "root"
? watch.rootFolderName
? dirname(watch.folderPath)
: parentDirectoryName(filePath);
const parentDirectoryName = (path: string) => basename(dirname(path));

View file

@ -275,7 +275,7 @@ export interface Electron {
// - Watch
/**
* Functions tailored for the folder watch functionality
* Interface with the file system watcher running in our Node.js layer.
*
* [Note: Folder vs Directory in the context of FolderWatch-es]
*
@ -288,7 +288,7 @@ export interface Electron {
* dragged/dropped or selected to set up the folder watch, will be referred
* to as a folder when naming things.
*/
watch: {
watcher: {
/**
* Return the paths of all the files under the given folder.
*
@ -333,6 +333,45 @@ export interface Electron {
* is no longer present, and returns this pruned list of watches.
*/
get: () => Promise<FolderWatch[]>;
/**
* Register the function to invoke when a file is added in one of the
* folders we are watching.
*
* The callback function is passed the path to the file that was added,
* and the folder watch it was associated with.
*
* The path is guaranteed to use POSIX separators ('/').
*/
onAddFile: (
f: (path: string, watch: FolderWatch) => void,
) => Promise<void>;
/**
* Register the function to invoke when a file is removed in one of the
* folders we are watching.
*
* The callback function is passed the path to the file that was
* removed, and the folder watch it was associated with.
*
* The path is guaranteed to use POSIX separators ('/').
*/
onRemoveFile: (
f: (path: string, watch: FolderWatch) => void,
) => Promise<void>;
/**
* Register the function to invoke when a directory is removed in one of
* the folders we are watching.
*
* The callback function is passed the path to the directory that was
* removed, and the folder watch it was associated with.
*
* The path is guaranteed to use POSIX separators ('/').
*/
onRemoveDir: (
f: (path: string, watch: FolderWatch) => void,
) => Promise<void>;
};
registerWatcherFunctions: (