Skip to content

Commit

Permalink
Add saving/loading from Ace editor
Browse files Browse the repository at this point in the history
Add MainApp class to hold main process code besides setup.
Add menu options to open and save Python files in Editor.
Add file info bar in Editor displaying file name and status.
Add generic confirmation modal.
  • Loading branch information
Hal-9k1 committed Jul 10, 2024
1 parent 59a2f39 commit 49ee940
Show file tree
Hide file tree
Showing 10 changed files with 424 additions and 30 deletions.
10 changes: 10 additions & 0 deletions src/common/AppConsoleMessage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export default class AppConsoleMessage {
#type: string;

#text: string;

constructor(type: string, text: string) {
this.#type = type;
this.#text = text;
}
}
164 changes: 164 additions & 0 deletions src/main/MainApp.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
import { dialog, ipcMain } from 'electron';
import type { BrowserWindow } from 'electron';
import fs from 'fs';
import { version as dawnVersion } from '../../package.json';
import AppConsoleMessage from '../common/AppConsoleMessage';

const WATCH_DEBOUNCE_MS = 3000;
const CODE_FILE_FILTERS = [
{ name: 'Python Files', extensions: ['py'] },
{ name: 'All Files', extensions: ['*'] },
];

export default class MainApp {
readonly #mainWindow: BrowserWindow;

#savePath: string | null;

#watcher: fs.FSWatcher | null;

#watchDebounce: boolean;

#preventQuit: boolean;

constructor(mainWindow: BrowserWindow) {
this.#mainWindow = mainWindow;
this.#savePath = null;
this.#watcher = null;
this.#watchDebounce = true;
this.#preventQuit = true;
mainWindow.on('close', (e) => {
if (this.#preventQuit) {
e.preventDefault();
this.#sendToRenderer('renderer-quit-request');
}
});
ipcMain.on('main-file-control', (_event, data) => {
if (data.type === 'save') {
this.#saveCodeFile(data.content as string, data.forceDialog as boolean);
} else if (data.type === 'load') {
this.#openCodeFile();
} else {
// eslint-disable-next-line no-console
console.error(`Unknown data.type for main-file-control ${data.type}`);
}
});
ipcMain.on('main-quit', () => {
this.#preventQuit = false;
this.#mainWindow.close();
});
}

#sendToRenderer(...args) {

Check failure on line 52 in src/main/MainApp.ts

View workflow job for this annotation

GitHub Actions / test (ubuntu-latest)

Rest parameter 'args' implicitly has an 'any[]' type.
this.#mainWindow.webContents.send(...args);

Check failure on line 53 in src/main/MainApp.ts

View workflow job for this annotation

GitHub Actions / test (ubuntu-latest)

A spread argument must either have a tuple type or be passed to a rest parameter.
}

onPresent() {
this.#watcher?.close();
this.#savePath = null;
this.#sendToRenderer('renderer-init', { dawnVersion });
}

promptSaveCodeFile(forceDialog: boolean) {
this.#sendToRenderer('renderer-file-control', {
type: 'promptSave',
forceDialog,
});
}

promptLoadCodeFile() {
this.#sendToRenderer('renderer-file-control', { type: 'promptLoad' });
}

#saveCodeFile(code: string, forceDialog: boolean) {
let success = true;
if (this.#savePath === null || forceDialog) {
success = this.#showCodePathDialog('save');
}
if (success) {
// Temporarily disable watcher
this.#watcher?.close();
this.#watcher = null;
fs.writeFile(
this.#savePath,

Check failure on line 83 in src/main/MainApp.ts

View workflow job for this annotation

GitHub Actions / test (ubuntu-latest)

Argument of type 'string | null' is not assignable to parameter of type 'PathOrFileDescriptor'.
code,
{ encoding: 'utf8', flag: 'w' },
(err) => {
if (err) {
this.#sendToRenderer(
'renderer-post-console',
new AppConsoleMessage(
'dawn-err',
`Failed to save code to ${this.#savePath}. ${err}`,
),
);
} else {
this.#sendToRenderer('renderer-file-control', { type: 'didSave' });
}
this.#watchCodeFile();
},
);
}
}

#openCodeFile() {
const success = this.#showCodePathDialog('load');
if (success) {
this.#sendToRenderer('renderer-file-control', {
type: 'didOpen',
content: fs.readFileSync(this.#savePath, {

Check failure on line 109 in src/main/MainApp.ts

View workflow job for this annotation

GitHub Actions / test (ubuntu-latest)

No overload matches this call.
encoding: 'utf8',
flag: 'r',
}),
});
}
}

#showCodePathDialog(mode: 'save' | 'load') {
let result: string | string[] | undefined;
if (mode === 'save') {
result = dialog.showSaveDialogSync(this.#mainWindow, {
filters: CODE_FILE_FILTERS,
...(this.#savePath === null ? {} : { defaultPath: this.#savePath }),
});
} else {
result = dialog.showOpenDialogSync(this.#mainWindow, {
filters: CODE_FILE_FILTERS,
properties: ['openFile'],
});
}
if (result && result.length) {
this.#savePath = typeof result === 'string' ? result : result[0];
this.#sendToRenderer('renderer-file-control', {
type: 'didChangePath',
path: this.#savePath,
});
if (mode === 'load') {
this.#watchCodeFile();
}
return true;
}
return false;
}

#watchCodeFile() {
this.#watcher?.close();
this.#watchDebounce = true;
this.#watcher = fs.watch(
this.#savePath,

Check failure on line 148 in src/main/MainApp.ts

View workflow job for this annotation

GitHub Actions / test (ubuntu-latest)

No overload matches this call.
{ persistent: false, encoding: 'utf8' },
() => {
// Don't care what the event type is
if (this.#watchDebounce) {
this.#watchDebounce = false;
setTimeout(() => {
this.#watchDebounce = true;
}, WATCH_DEBOUNCE_MS);
this.#sendToRenderer('renderer-file-control', {
type: 'didExternalChange',
});
}
},
);
}
}
8 changes: 4 additions & 4 deletions src/main/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { autoUpdater } from 'electron-updater';
import log from 'electron-log';
import MenuBuilder from './menu';
import { resolveHtmlPath } from './util';
import { version as dawnVersion } from '../../package.json';
import MainApp from './MainApp';

class AppUpdater {
constructor() {
Expand Down Expand Up @@ -75,14 +75,14 @@ const createWindow = async () => {
: path.join(__dirname, '../../.erb/dll/preload.js'),
},
});
const mainApp = new MainApp(mainWindow);

mainWindow.loadURL(resolveHtmlPath('index.html'));

mainWindow.on('ready-to-show', () => {
if (!mainWindow) {
throw new Error('"mainWindow" is not defined');
}
mainWindow.webContents.send('renderer-init', { dawnVersion });
mainApp.onPresent();
if (process.env.START_MINIMIZED) {
mainWindow.minimize();
} else {
Expand All @@ -94,7 +94,7 @@ const createWindow = async () => {
mainWindow = null;
});

const menuBuilder = new MenuBuilder(mainWindow);
const menuBuilder = new MenuBuilder(mainApp, mainWindow);
menuBuilder.buildMenu();

// Open urls in the user's browser
Expand Down
28 changes: 21 additions & 7 deletions src/main/menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,20 @@ import {
BrowserWindow,
MenuItemConstructorOptions,
} from 'electron';
import type MainApp from './MainApp';

interface DarwinMenuItemConstructorOptions extends MenuItemConstructorOptions {
selector?: string;
submenu?: DarwinMenuItemConstructorOptions[] | Menu;
}

export default class MenuBuilder {
mainApp: MainApp;

mainWindow: BrowserWindow;

constructor(mainWindow: BrowserWindow) {
constructor(mainApp: MainApp, mainWindow: BrowserWindow) {
this.mainApp = mainApp;
this.mainWindow = mainWindow;
}

Expand Down Expand Up @@ -200,12 +204,22 @@ export default class MenuBuilder {
{
label: '&Open',
accelerator: 'Ctrl+O',
click: () => {
this.mainApp.promptLoadCodeFile();
},
},
{
label: '&Close',
accelerator: 'Ctrl+W',
label: '&Save',
accelerator: 'Ctrl+S',
click: () => {
this.mainWindow.close();
this.mainApp.promptSaveCodeFile(false);
},
},
{
label: 'Save &As',
accelerator: 'Ctrl+Shift+S',
click: () => {
this.mainApp.promptSaveCodeFile(true);
},
},
],
Expand Down Expand Up @@ -234,7 +248,7 @@ export default class MenuBuilder {
},
{
label: 'Toggle &Developer Tools',
accelerator: 'Alt+Ctrl+I',
accelerator: 'Ctrl+Shift+I',
click: () => {
this.mainWindow.webContents.toggleDevTools();
},
Expand All @@ -252,7 +266,7 @@ export default class MenuBuilder {
},
],
},
{
/* {
label: 'Help',
submenu: [
{
Expand Down Expand Up @@ -282,7 +296,7 @@ export default class MenuBuilder {
},
},
],
},
}, */
];

return templateDefault;
Expand Down
9 changes: 8 additions & 1 deletion src/main/preload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,14 @@
/* eslint no-unused-vars: off */
import { contextBridge, ipcRenderer, IpcRendererEvent } from 'electron';

export type Channels = 'renderer-init' | 'robot-connection-update';
export type Channels =
| 'renderer-init'
| 'renderer-robot-update'
| 'renderer-post-console'
| 'renderer-file-control'
| 'renderer-quit-request'
| 'main-file-control'
| 'main-quit';

const electronHandler = {
ipcRenderer: {
Expand Down
Loading

0 comments on commit 49ee940

Please sign in to comment.