123-lang 2.1.3 → 2.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/source/electron.js +312 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "123-lang",
3
- "version": "2.1.3",
3
+ "version": "2.1.4",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -0,0 +1,312 @@
1
+ const path = require('path');
2
+
3
+ const {
4
+ app,
5
+ BrowserWindow,
6
+ shell,
7
+ dialog,
8
+ session,
9
+ globalShortcut,
10
+ } = require('electron');
11
+ const isDev = require('electron-is-dev');
12
+ // Auto updater
13
+ const fs = require('fs');
14
+ const { localStorage } = require('electron-browser-storage');
15
+ const { t } = require('./electron-configuration/messages');
16
+ const {
17
+ config,
18
+ platforms,
19
+ platformsNames,
20
+ } = require('./electron-configuration/configuration');
21
+ const { autoUpdater } = require('electron-updater');
22
+ const log = require('electron-log');
23
+ const forge = require('node-forge');
24
+ const os = require('os');
25
+
26
+ const getLang = async () => localStorage.getItem(config.storageNames.lang);
27
+
28
+ const { isEnableDevTools, isAvailableDomainInput, certificate } = config;
29
+
30
+ const rootCertificatePath = path.join(
31
+ __dirname,
32
+ certificate.dir,
33
+ certificate.fileName
34
+ );
35
+ const rootCertificatePathSecondary = path.join(
36
+ __dirname,
37
+ certificate.dir,
38
+ certificate.fileNameSecondary
39
+ );
40
+
41
+ const currentPlatform = platformsNames[os.platform()];
42
+ let updatesPath;
43
+
44
+ log.info(`Current Platform: ${currentPlatform}`);
45
+
46
+ // Disable downloading and installation updates for the MAC
47
+ autoUpdater.autoDownload = currentPlatform !== platforms.MAC;
48
+ autoUpdater.autoInstallOnAppQuit = currentPlatform !== platforms.MAC;
49
+
50
+ // Enable usage of Portal's globalShortcuts. This is essential for cases when
51
+ // the app runs in a Wayland session.
52
+ app.commandLine.appendSwitch('enable-features', 'GlobalShortcutsPortal');
53
+
54
+ function createWindow() {
55
+ // Create the browser window.
56
+ const win = new BrowserWindow({
57
+ ...config.mainWindow,
58
+ webPreferences: {
59
+ devTools: true,
60
+ nodeIntegration: true,
61
+ },
62
+ });
63
+
64
+ win.webContents.on('new-window', function (e, url) {
65
+ e.preventDefault();
66
+ shell.openExternal(url);
67
+ });
68
+ // Set Links Settings
69
+
70
+ win.webContents.setWindowOpenHandler(details => {
71
+ shell.openExternal(details.url); // Open URL in user's Browser
72
+ return { action: 'deny' };
73
+ });
74
+
75
+ if (!isEnableDevTools) {
76
+ win.removeMenu();
77
+ }
78
+
79
+ // Register a config?.shortCuts?.devTools shortcut listener.
80
+ const ret = globalShortcut.register(config?.shortCuts?.devTools, () => {
81
+ const focusedWindow = BrowserWindow.getFocusedWindow();
82
+ log.info(`${config?.shortCuts?.devTools} is pressed`);
83
+ if (focusedWindow) {
84
+ const isOpen = focusedWindow.webContents.isDevToolsOpened();
85
+ if (isOpen) {
86
+ focusedWindow.webContents.closeDevTools();
87
+ } else {
88
+ focusedWindow.webContents.openDevTools({ mode: 'detach' });
89
+ }
90
+ } else {
91
+ log.warn('No focused window to toggle DevTools.');
92
+ }
93
+ });
94
+
95
+ // and load the index.html of the app.
96
+ // win.loadFile("index.html");
97
+ win.loadURL(
98
+ isDev
99
+ ? 'http://localhost:3000'
100
+ : `file://${path.join(__dirname, '../build/index.html')}`
101
+ );
102
+
103
+ // Open the DevTools.
104
+ if (isEnableDevTools) {
105
+ win.webContents.openDevTools({ mode: 'detach' });
106
+ }
107
+
108
+ // Check up for updates
109
+ // Verify certificate for the autoUpdater
110
+ autoUpdater.netSession.setCertificateVerifyProc((request, callback) => {
111
+ const certStatuses = {
112
+ trusted: 0,
113
+ failed: -2,
114
+ browserChecked: -3,
115
+ };
116
+ const { hostname: hostName, verificationResult: e, certificate } = request;
117
+ let subjectName = certificate?.subjectName?.split('\n')[0];
118
+ subjectName = subjectName?.replace('*.', '');
119
+ const status = hostName?.includes(subjectName)
120
+ ? certStatuses.trusted
121
+ : certStatuses.failed;
122
+ if (status === certStatuses.failed) {
123
+ log.error('Certificate validation error:');
124
+ log.error(e);
125
+ }
126
+ callback(status);
127
+ });
128
+
129
+ const generateUpdateConfig = async () => {
130
+ let status = true;
131
+ const domainURL = await localStorage.getItem(config.storageNames.domain);
132
+ // Test local server
133
+ // const domainURL = `http://localhost:3100/`;
134
+ if (!domainURL) {
135
+ status = false;
136
+ return status;
137
+ }
138
+ const platformPath =
139
+ config?.updatesPathForPlatform[currentPlatform] ??
140
+ config?.updatesPathForPlatform[platforms.WINDOWS];
141
+
142
+ updatesPath = `${domainURL}${platformPath}`;
143
+
144
+ try {
145
+ log.info('domain: ', domainURL);
146
+ log.info('updates path: ', updatesPath);
147
+ autoUpdater.setFeedURL({
148
+ url: updatesPath,
149
+ provider: config.provider,
150
+ });
151
+ } catch (err) {
152
+ log.error(err);
153
+ status = false;
154
+ }
155
+ return status;
156
+ };
157
+
158
+ if (app.isPackaged) {
159
+ if (isAvailableDomainInput) {
160
+ generateUpdateConfig()
161
+ .then(status => {
162
+ if (status) {
163
+ autoUpdater.logger = log;
164
+ autoUpdater.checkForUpdates();
165
+ }
166
+ })
167
+ .catch(e => log.error(e));
168
+ return;
169
+ }
170
+ autoUpdater.logger = log;
171
+ autoUpdater.checkForUpdates();
172
+ }
173
+ }
174
+
175
+ // This method will be called when Electron has finished
176
+ // initialization and is ready to create browser windows.
177
+ // Some APIs can only be used after this event occurs.
178
+ app.whenReady().then(() => {
179
+ createWindow();
180
+
181
+ // MAC OS FIX: Re-create a window in the app when the dock icon is clicked
182
+ app.on('activate', () => {
183
+ if (BrowserWindow.getAllWindows().length === 0) createWindow();
184
+ });
185
+ });
186
+
187
+ // Quit when all windows are closed, except on macOS. There, it's common
188
+ // for applications and their menu bar to stay active until the user quits
189
+ // explicitly with Cmd + Q.
190
+ app.on('window-all-closed', () => {
191
+ if (process.platform !== 'darwin') {
192
+ app.quit();
193
+ }
194
+ });
195
+
196
+ // Auto updater events
197
+ // Check is auto update available
198
+ autoUpdater.on('update-available', info => {
199
+ log.info('Update available:', info);
200
+ log.info('Updates path:', updatesPath);
201
+
202
+ const showInfoDialog = (lang = 'en') => {
203
+ log.info('showInfoDialog lang', lang);
204
+ const options = {
205
+ type: 'info',
206
+ buttons: [
207
+ t('Download installer', lang),
208
+ t('Download manual', lang),
209
+ t('Cancel', lang),
210
+ ],
211
+ defaultId: 2,
212
+ title: t('Update is available', lang),
213
+ message: t('Update is available', lang),
214
+ detail: '',
215
+ };
216
+ dialog.showMessageBox(options).then(response => {
217
+ if (response.response === 0) {
218
+ shell.openExternal(
219
+ `${updatesPath}${config?.macUpdateConfig?.installerName}`
220
+ );
221
+ showInfoDialog(lang);
222
+ } else if (response.response === 1) {
223
+ shell.openExternal(
224
+ `${updatesPath}${config?.macUpdateConfig?.manualMap[lang]}`
225
+ );
226
+ showInfoDialog(lang);
227
+ }
228
+ });
229
+ };
230
+ if (currentPlatform === platforms.MAC) {
231
+ getLang()
232
+ .then(lang => {
233
+ showInfoDialog(lang);
234
+ })
235
+ .catch(() => {
236
+ log.error('Unable get language');
237
+ showInfoDialog();
238
+ });
239
+ }
240
+ });
241
+ autoUpdater.on('update-downloaded', (_event, releaseNotes, releaseName) => {
242
+ const showTranslatedDialog = lang => {
243
+ const dialogOpts = {
244
+ type: 'info',
245
+ buttons: [t('Ok', lang), t('Later', lang)],
246
+ title: t('Update is available', lang),
247
+ message: process.platform === 'win32' ? releaseNotes : releaseName,
248
+ detail: t('Now application will start updating and restart.', lang),
249
+ };
250
+ dialog.showMessageBox(dialogOpts).then(returnValue => {
251
+ if (returnValue.response === 0) autoUpdater.quitAndInstall();
252
+ });
253
+ };
254
+ getLang()
255
+ .then(lang => {
256
+ showTranslatedDialog(lang);
257
+ })
258
+ .catch(() => {
259
+ log.error('Unable get language');
260
+ showTranslatedDialog();
261
+ });
262
+ });
263
+
264
+ autoUpdater.on('error', message => {
265
+ log.error(t('There was a problem updating the application'));
266
+ log.error(message);
267
+ });
268
+
269
+ app.on(
270
+ 'certificate-error',
271
+ (event, webContents, url, error, certificate, callback) => {
272
+ try {
273
+ const rootCertificateContent = fs.readFileSync(
274
+ rootCertificatePath,
275
+ 'utf8'
276
+ );
277
+ const rootCertificateContentSecondary = fs.readFileSync(
278
+ rootCertificatePathSecondary,
279
+ 'utf8'
280
+ );
281
+ const rootCert = forge.pki.certificateFromPem(rootCertificateContent);
282
+ const rootCertSecondary = forge.pki.certificateFromPem(
283
+ rootCertificateContentSecondary
284
+ );
285
+ const clientCert = forge.pki.certificateFromPem(
286
+ certificate.data.toString()
287
+ );
288
+ callback(
289
+ clientCert.isIssuer(rootCert) || clientCert.isIssuer(rootCertSecondary)
290
+ );
291
+ } catch (e) {
292
+ log.error('Certificate validation error:');
293
+ log.error(e);
294
+ callback(false);
295
+ }
296
+ }
297
+ );
298
+
299
+ // Clear Cache
300
+ app.on('ready', () => {
301
+ session.defaultSession.clearCache().then(() => {
302
+ log.info('Cache cleared!');
303
+ });
304
+ });
305
+
306
+ app.on('will-quit', () => {
307
+ // Unregister a shortcut.
308
+ globalShortcut.unregister(config?.shortCuts?.devTools);
309
+
310
+ // Unregister all shortcuts.
311
+ globalShortcut.unregisterAll();
312
+ });