-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.ts
278 lines (241 loc) · 7.99 KB
/
main.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
import { app, BrowserWindow, ipcMain, shell } from 'electron';
import contextMenu from 'electron-context-menu';
import isDev from 'electron-is-dev';
import log from 'electron-log';
import fs from 'fs';
import mime from 'mime';
import path from 'path';
import { promisify } from 'util';
import { appUpdater } from './appUpdater';
import { FileData } from './global';
import { setMenu } from './menuTemplate';
import platform from './platform';
import { filterFileArgs } from './utils/filterFileArgs';
import { handleDownload } from './utils/handleDownload';
import { getWindowState, saveWindowState } from './windowState';
const readdir = promisify(fs.readdir);
const stat = promisify(fs.stat);
const unlink = promisify(fs.unlink);
contextMenu({
prepend: (_defaultActions, params, _browserWindow) => [
{
label: 'Search Google for “{selection}”',
// Only show it when right-clicking text
visible: params.selectionText.trim().length > 0,
click: () => {
shell.openExternal(`https://google.com.au/search?q=${encodeURIComponent(params.selectionText)}`);
},
},
],
showSaveImage: true,
showSaveImageAs: true,
});
// Set up all log related functionality here. Don't 100% understand the logging levels/functionality.
// Has been sporadic, esp when not in appData.Don't know if related. Second line causes an error if not commented out
log.transports.file.level = 'info';
// log.transports.file.file = __dirname + '/log.txt';
let mainWindow: null | Electron.BrowserWindow = null;
// Declare a global empty object variable to hold file path if a file is opened while the app is closed
// @ts-ignore
global.fileToOpen = null;
// @ts-ignore
global.pathToHandle = null;
// Clear the global fileToOpen variable once Mediref app renderer process has handled the file
ipcMain.on('file-handled', () => {
// @ts-ignore
global.fileToOpen = null;
});
// Function to log a message on front end
function logMessageOnClient(message: string) {
if (mainWindow) {
console.log(mainWindow.webContents.send);
mainWindow.webContents.send('Updater', message);
}
}
// Takes in a file path, reads the file, assigns it to the global fileToOpen and then emits an event if window open
function handleFilePath(filePath: string, ptName = '', ptEmail = '', recipientEmail = '') {
// @ts-ignore
global.pathToHandle = filePath;
const name = path.basename(filePath);
const type = mime.getType(filePath);
const data = fs.readFileSync(filePath, 'base64');
const fileData: FileData = {
name,
data,
type,
path: filePath,
ptName,
ptEmail,
recipientEmail,
};
// @ts-ignore
global.fileToOpen = fileData;
if (mainWindow) {
mainWindow.webContents.send('open-file', fileData);
}
return fileData;
}
function handleWindowsArgs(args: string[]) {
const [filePath, ptName = '', ptEmail = '', recipientEmail = ''] = filterFileArgs(args);
if (filePath) {
handleFilePath(filePath, ptName, ptEmail, recipientEmail);
}
}
// Temp folder for PS files (when using Ghostscript) should be cleared
async function clearTempFolder() {
try {
const tempDir = 'C:\\MedirefPrinter\\Temp';
// Retrieve all files in the temp folder
const files = await readdir(tempDir);
const oneDay = 1 * 24 * 60 * 60 * 1000;
const deleteDate = new Date().getTime() - oneDay;
files.forEach(async function (file) {
const filepath = path.join(tempDir, file);
if (!mainWindow) return;
logMessageOnClient(`File: ${filepath}`);
// Find each file's createdAt timestamp. Use the earlier between mtime and birthtime to account for
// situations where birthtime reverts to ctime. See https://nodejs.org/api/fs.html#statsbirthtime
const { mtime, birthtime } = await stat(filepath);
const createdDate = Math.min(mtime.getTime(), birthtime.getTime());
// If older than one day, delete it
if (deleteDate > createdDate) {
await unlink(filepath);
logMessageOnClient(`Deleted file: ${filepath}`);
} else {
logMessageOnClient(`Did not delete file: ${filepath}`);
}
});
} catch (err: any) {
logMessageOnClient(`Error clearing temp folder: ${JSON.stringify(err)}`);
if (err.code === 'ENOENT') {
return;
}
}
}
function createMainWindow() {
const { maximise, ...windowState } = getWindowState();
mainWindow = new BrowserWindow({
webPreferences: {
nodeIntegration: false,
preload: __dirname + '/preload.js',
spellcheck: true,
},
// Specify window state if not maximised and hide window if maximised (we will reveal the window after the maximise method is called)
...(maximise ? { show: false } : windowState),
});
if (maximise) {
mainWindow.maximize();
mainWindow.show();
}
if (platform.isWindows) {
handleWindowsArgs(process.argv);
}
if (isDev) {
mainWindow.loadURL('http://localhost:3000/new');
mainWindow.webContents.openDevTools();
} else {
mainWindow.loadURL('https://www.mediref.com.au/compose');
}
setMenu(app);
mainWindow.on('resize', () => saveWindowState(mainWindow));
mainWindow.on('move', () => saveWindowState(mainWindow));
}
/**
* Each 'print' launches a new instance. Hence, this check ensures only one instance is ever running...
* See: https://www.electronjs.org/docs/all#apprequestsingleinstancelock
* The return value of this method indicates whether or not this instance of your application successfully obtained
* the lock. If it failed to obtain the lock, you can assume that another instance of your application is already
* running with the lock and exit immediately.
*/
const gotTheLock = app.requestSingleInstanceLock();
if (!gotTheLock) {
app.quit();
} else {
app.on('second-instance', (_event, commandLine) => {
if (mainWindow) {
if (mainWindow.isMinimized()) {
mainWindow.restore();
}
mainWindow.focus();
handleWindowsArgs(commandLine);
}
});
app.on('ready', createMainWindow);
}
app.on('will-finish-launching', () => {
app.on('open-file', (event, filePath) => {
event.preventDefault();
handleFilePath(filePath);
logMessageOnClient(`Calling open-file event...`);
});
});
// For Mac's where app has not quit even if all windows are 'closed'
app.on('activate', () => {
if (mainWindow === null) {
createMainWindow();
}
});
// TODO Set up crash reporter
process.on('uncaughtException', (err) => {
log.info(err);
console.log(`Application exited with error: ${err}`);
});
// Quit app if all windows are closed
app.on('window-all-closed', () => {
app.quit();
});
ipcMain.on('view-pdf', (_event, url: string, filename: string) => {
const pdfWindow = new BrowserWindow({
width: 1024,
height: 800,
webPreferences: {
plugins: true,
},
title: filename,
});
pdfWindow.loadURL(url);
});
ipcMain.on('app-mounted', () => {
if (!mainWindow) return;
// If there is a global file, send it across
// @ts-ignore
if (global.fileToOpen) {
// @ts-ignore
mainWindow.webContents.send('open-file', global.fileToOpen);
}
// Send electron metadata
const { name: os, is64Bit } = platform;
const electronVersion = app.getVersion();
const basepath = app.getAppPath();
mainWindow.webContents.send('handle-electron-version', { version: electronVersion, os, is64Bit, path: basepath });
appUpdater(mainWindow);
if (platform.isWindows) {
clearTempFolder();
}
});
ipcMain.on('download-file', handleDownload);
// Remotely load a provided url on to the main window (allows for easier use of ngrok)
ipcMain.on('load-url', (_event, url) => {
if (!mainWindow) return;
mainWindow.loadURL(url);
});
// Remotely load a provided url on to the main window (allows for easier use of ngrok)
ipcMain.on('load-dev', () => {
if (!mainWindow) return;
mainWindow.loadURL('http://localhost:3000/');
});
// Remotely load staging url on to the main window (allows for easier debugging of staging environment)
ipcMain.on('load-staging', () => {
if (!mainWindow) return;
mainWindow.loadURL('https://staging.mediref.com.au/');
});
ipcMain.on('clear-temp', async () => {
await clearTempFolder();
logMessageOnClient(`Temp folder cleared...`);
});
ipcMain.on('ping', async () => {
console.log('Received ping...');
// @ts-ignore
logMessageOnClient(JSON.stringify(global.fileToOpen));
logMessageOnClient(`Ping pong!`);
});