Skip to content

Commit

Permalink
Move all fs calls to main process, invoke via IPC (#2716)
Browse files Browse the repository at this point in the history
* Move startup template loading to main process

* remove unused variable

* replace initial batch of frontend FS

* move input override code that the renderer needs

* more correct typing for read and write file, pass through options

---------

Co-authored-by: Michael Schmidt <[email protected]>
  • Loading branch information
joeyballentine and RunDevelopment authored Mar 29, 2024
1 parent c4a050c commit ff8f362
Show file tree
Hide file tree
Showing 8 changed files with 89 additions and 18 deletions.
9 changes: 9 additions & 0 deletions src/common/input-override-common.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { InputId } from './common-types';

export type InputOverrideId = string & { readonly __input_override_id?: never };

export const createInputOverrideId = (nodeId: string, inputId: InputId): InputOverrideId => {
if (nodeId.length !== 36)
throw new Error('Expected node id to be a 36 character hexadecimal UUID.');
return `#${nodeId}:${inputId}`;
};
9 changes: 1 addition & 8 deletions src/common/input-override.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,12 @@
import { readFile } from 'fs/promises';
import { extname } from 'path';
import { EdgeData, InputData, InputId, InputValue, Mutable, NodeData } from './common-types';
import { InputOverrideId } from './input-override-common';
import { log } from './log';
import { SchemaMap } from './SchemaMap';
import { joinEnglish } from './util';
import type { Edge, Node } from 'reactflow';

export type InputOverrideId = string & { readonly __input_override_id?: never };

export const createInputOverrideId = (nodeId: string, inputId: InputId): InputOverrideId => {
if (nodeId.length !== 36)
throw new Error('Expected node id to be a 36 character hexadecimal UUID.');
return `#${nodeId}:${inputId}`;
};

const isValidInputOverrideId = (id: InputOverrideId) => /^#[a-f0-9-]{36}:\d+$/.test(id);
export const parseInputOverrideId = (id: InputOverrideId): { nodeId: string; inputId: InputId } => {
if (!isValidInputOverrideId(id)) throw new Error(`"${id}" is not a valid input override id.`);
Expand Down
41 changes: 41 additions & 0 deletions src/common/safeIpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import {
ipcMain as unsafeIpcMain,
ipcRenderer as unsafeIpcRenderer,
} from 'electron';
import { MakeDirectoryOptions } from 'fs';
import { Mode, ObjectEncodingOptions, OpenMode, PathLike } from 'original-fs';
import { FileOpenResult, FileSaveResult, PythonInfo, Version } from './common-types';
import { ParsedSaveData, SaveData } from './SaveFile';
import { ChainnerSettings } from './settings/settings';
Expand Down Expand Up @@ -50,6 +52,45 @@ export interface InvokeChannels {
// settings
'get-settings': ChannelInfo<ChainnerSettings>;
'set-settings': ChannelInfo<void, [settings: ChainnerSettings]>;

// fs
'fs-read-file': ChannelInfo<
string,
// Mostly copied this from the original fs.readFile, but had to remove some bits due to being unable to import the types
[
path: PathLike,
options:
| {
encoding: BufferEncoding;
flag?: OpenMode | undefined;
}
| BufferEncoding
]
>;
'fs-write-file': ChannelInfo<
void,
// Mostly copied this from the original fs.writeFile, but had to remove some bits due to being unable to import the types
[
file: PathLike,
data:
| string
| NodeJS.ArrayBufferView
| Iterable<string | NodeJS.ArrayBufferView>
| AsyncIterable<string | NodeJS.ArrayBufferView>,
options?:
| (ObjectEncodingOptions & {
mode?: Mode | undefined;
flag?: OpenMode | undefined;
})
| BufferEncoding
| null
]
>;
'fs-exists': ChannelInfo<boolean, [path: string]>;
'fs-mkdir': ChannelInfo<string | undefined, [path: string, options: MakeDirectoryOptions]>;
'fs-readdir': ChannelInfo<string[], [path: string]>;
'fs-unlink': ChannelInfo<void, [path: string]>;
'fs-access': ChannelInfo<void, [path: string]>;
}

export interface SendChannels {
Expand Down
19 changes: 19 additions & 0 deletions src/main/gui/main-window.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { BrowserWindow, app, dialog, nativeTheme, powerSaveBlocker, shell } from 'electron';
import EventSource from 'eventsource';
import fs, { constants } from 'fs/promises';
import { t } from 'i18next';
import { BackendEventMap } from '../../common/Backend';
import { Version } from '../../common/common-types';
Expand Down Expand Up @@ -195,6 +196,24 @@ const registerEventHandlerPreSetup = (
})().catch(log.error);
});
}

// Handle filesystem
ipcMain.handle('fs-read-file', async (event, path, options) => fs.readFile(path, options));
ipcMain.handle('fs-write-file', async (event, path, content, options) =>
fs.writeFile(path, content, options)
);
ipcMain.handle('fs-exists', async (event, path) => {
try {
await fs.access(path, constants.F_OK);
return true;
} catch {
return false;
}
});
ipcMain.handle('fs-mkdir', async (event, path, options) => fs.mkdir(path, options));
ipcMain.handle('fs-readdir', async (event, path) => fs.readdir(path));
ipcMain.handle('fs-unlink', async (event, path) => fs.unlink(path));
ipcMain.handle('fs-access', async (event, path) => fs.access(path));
};

const registerEventHandlerPostSetup = (
Expand Down
6 changes: 4 additions & 2 deletions src/renderer/components/groups/NcnnFileInputsGroup.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { memo, useEffect } from 'react';
import { log } from '../../../common/log';
import { checkFileExists, getInputValue } from '../../../common/util';
import { ipcRenderer } from '../../../common/safeIpc';
import { getInputValue } from '../../../common/util';
import { SchemaInput } from '../inputs/SchemaInput';
import { GroupProps } from './props';

const ifExists = (file: string, then: () => void) => {
checkFileExists(file)
ipcRenderer
.invoke('fs-exists', file)
.then((exists) => {
if (exists) {
then();
Expand Down
16 changes: 11 additions & 5 deletions src/renderer/components/settings/components.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {
Select,
Switch,
} from '@chakra-ui/react';
import { access, mkdir, readdir, unlink } from 'fs/promises';
import path from 'path';
import { memo, useEffect, useMemo } from 'react';
import { Setting } from '../../../common/common-types';
Expand Down Expand Up @@ -130,9 +129,14 @@ const CacheSetting = memo(({ setting, value, setValue }: SettingsProps<'cache'>)
onClick={() => {
locationPromise
.then(async (cacheLocation) => {
const files = await readdir(cacheLocation);
const files = await ipcRenderer.invoke('fs-readdir', cacheLocation);
await Promise.all(
files.map((file) => unlink(path.join(cacheLocation, file)))
files.map((file) =>
ipcRenderer.invoke(
'fs-unlink',
path.join(cacheLocation, file)
)
)
);
})
.catch(log.error);
Expand All @@ -151,9 +155,11 @@ const CacheSetting = memo(({ setting, value, setValue }: SettingsProps<'cache'>)
locationPromise
.then(async (cacheLocation) => {
try {
await access(cacheLocation);
await ipcRenderer.invoke('fs-access', cacheLocation);
} catch (error) {
await mkdir(cacheLocation, { recursive: true });
await ipcRenderer.invoke('fs-mkdir', cacheLocation, {
recursive: true,
});
}
setValue(cacheLocation);
})
Expand Down
5 changes: 3 additions & 2 deletions src/renderer/helpers/copyAndPaste.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { clipboard } from 'electron';
import { writeFile } from 'fs/promises';
import os from 'os';
import path from 'path';
import { Edge, Node, Project } from 'reactflow';
import { v4 as uuid4 } from 'uuid';
import { EdgeData, InputId, NodeData, SchemaId } from '../../common/common-types';
import { log } from '../../common/log';
import { ipcRenderer } from '../../common/safeIpc';
import { createUniqueId, deriveUniqueId } from '../../common/util';
import { NodeProto, copyEdges, copyNodes, setSelected } from './reactFlowUtil';
import { SetState } from './types';
Expand Down Expand Up @@ -108,7 +108,8 @@ export const pasteFromClipboard = (
case 'image/png': {
const imgData = clipboard.readImage().toPNG();
const imgPath = path.join(os.tmpdir(), `chaiNNer-clipboard-${uuid4()}.png`);
writeFile(imgPath, imgData)
ipcRenderer
.invoke('fs-write-file', imgPath, imgData)
.then(() => {
log.debug('Clipboard image', imgPath);
let positionX = 0;
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/hooks/useInputRefactor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
PartialBy,
SchemaId,
} from '../../common/common-types';
import { createInputOverrideId } from '../../common/input-override';
import { createInputOverrideId } from '../../common/input-override-common';
import { createUniqueId } from '../../common/util';
import { BackendContext } from '../contexts/BackendContext';
import { FakeNodeContext } from '../contexts/FakeExampleContext';
Expand Down

0 comments on commit ff8f362

Please sign in to comment.