diff --git a/README.md b/README.md
index 5476fbf..50eaf96 100644
--- a/README.md
+++ b/README.md
@@ -247,6 +247,11 @@ https://github.com/MrMYHuang/cbetar2/releases/latest
11. 合成語音選項在Android Chrome無效。( https://stackoverflow.com/a/61366224/631869 )
## 版本歷史
+* 2021.02.09:
+ * PWA 4.23.0:
+ * [新增] 支援檢查後端app下載進度顯示。
+ * Backend 13.0.0:
+ * [新增] 支援檢查後端app更新、下載。
* PWA 4.22.0:
* [新增] 經文頁開啟CBETA Online經文功能。
* PWA 4.21.5:
diff --git a/electronBuilderConfigs/IsDeb.txt b/electronBuilderConfigs/IsDeb.txt
new file mode 100644
index 0000000..e69de29
diff --git a/electronBuilderConfigs/IsMac.txt b/electronBuilderConfigs/IsMac.txt
new file mode 100644
index 0000000..e69de29
diff --git a/electronBuilderConfigs/IsRpm.txt b/electronBuilderConfigs/IsRpm.txt
new file mode 100644
index 0000000..e69de29
diff --git a/electronBuilderConfigs/IsWin.txt b/electronBuilderConfigs/IsWin.txt
new file mode 100644
index 0000000..e69de29
diff --git a/electronBuilderConfigs/deb.json b/electronBuilderConfigs/deb.json
index e630337..eb97b06 100644
--- a/electronBuilderConfigs/deb.json
+++ b/electronBuilderConfigs/deb.json
@@ -5,6 +5,13 @@
"buildElectron/**/*",
"package.json"
],
+ "extraFiles": [
+ {
+ "from": "electronBuilderConfigs",
+ "to": ".",
+ "filter": ["IsDeb.txt"]
+ }
+ ],
"extraResources": [
"buildElectron/*.xsl"
],
diff --git a/electronBuilderConfigs/mac.json b/electronBuilderConfigs/mac.json
index 6e0c214..0c27a4f 100644
--- a/electronBuilderConfigs/mac.json
+++ b/electronBuilderConfigs/mac.json
@@ -6,6 +6,11 @@
"package.json"
],
"extraResources": [
+ {
+ "from": "electronBuilderConfigs",
+ "to": ".",
+ "filter": ["IsMac.txt"]
+ },
"buildElectron/*.xsl"
],
"asarUnpack": [
diff --git a/electronBuilderConfigs/rpm.json b/electronBuilderConfigs/rpm.json
index 6ccec75..63a24f9 100644
--- a/electronBuilderConfigs/rpm.json
+++ b/electronBuilderConfigs/rpm.json
@@ -5,6 +5,13 @@
"buildElectron/**/*",
"package.json"
],
+ "extraFiles": [
+ {
+ "from": "electronBuilderConfigs",
+ "to": ".",
+ "filter": ["IsRpm.txt"]
+ }
+ ],
"extraResources": [
"buildElectron/*.xsl"
],
diff --git a/electronBuilderConfigs/snap.json b/electronBuilderConfigs/snap.json
index 56b27fd..cb79f86 100644
--- a/electronBuilderConfigs/snap.json
+++ b/electronBuilderConfigs/snap.json
@@ -6,7 +6,11 @@
"package.json"
],
"extraFiles": [
- "electronBuilderConfigs/IsSnap.txt",
+ {
+ "from": "electronBuilderConfigs",
+ "to": ".",
+ "filter": ["IsSnap.txt"]
+ }
],
"extraResources": [
"buildElectron/*.xsl"
diff --git a/package-lock.json b/package-lock.json
index d8c3acf..c991d5d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -49,6 +49,12 @@
"source-map": "^0.5.0"
},
"dependencies": {
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true
+ },
"source-map": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
@@ -105,6 +111,14 @@
"@babel/helper-validator-option": "^7.12.1",
"browserslist": "^4.14.5",
"semver": "^5.5.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true
+ }
}
},
"@babel/helper-create-class-features-plugin": {
@@ -973,6 +987,14 @@
"@babel/helper-plugin-utils": "^7.10.4",
"resolve": "^1.8.1",
"semver": "^5.5.1"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true
+ }
}
},
"@babel/plugin-transform-shorthand-properties": {
@@ -1123,6 +1145,14 @@
"@babel/types": "^7.12.11",
"core-js-compat": "^3.8.0",
"semver": "^5.5.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true
+ }
}
},
"@babel/preset-modules": {
@@ -3326,6 +3356,11 @@
"@types/node": "*"
}
},
+ "@types/semver": {
+ "version": "7.3.4",
+ "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.4.tgz",
+ "integrity": "sha512-+nVsLKlcUCeMzD2ufHEYuJ9a2ovstb6Dp52A5VsoKxDXgvE051XgHI/33I1EymwkRGQkwnA0LkhnUzituGs4EQ=="
+ },
"@types/source-list-map": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz",
@@ -4312,7 +4347,6 @@
"version": "0.21.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
"integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
- "dev": true,
"requires": {
"follow-redirects": "^1.10.0"
},
@@ -4320,8 +4354,7 @@
"follow-redirects": {
"version": "1.13.1",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.1.tgz",
- "integrity": "sha512-SSG5xmZh1mkPGyKzjZP8zLjltIfpW32Y5QpdNJyjcfGxK3qo3NDDkZOZSFiGn1A6SclQxY9GzEwAHQ3dmYRWpg==",
- "dev": true
+ "integrity": "sha512-SSG5xmZh1mkPGyKzjZP8zLjltIfpW32Y5QpdNJyjcfGxK3qo3NDDkZOZSFiGn1A6SclQxY9GzEwAHQ3dmYRWpg=="
}
}
},
@@ -4735,6 +4768,14 @@
"@babel/types": "^7.12.1",
"core-js-compat": "^3.6.2",
"semver": "^5.5.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true
+ }
}
},
"@babel/preset-react": {
@@ -6278,6 +6319,14 @@
"semver": "^5.5.0",
"shebang-command": "^1.2.0",
"which": "^1.2.9"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true
+ }
}
},
"crypto-browserify": {
@@ -9456,6 +9505,12 @@
"to-regex": "^3.0.2"
}
},
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true
+ },
"to-regex-range": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
@@ -14958,7 +15013,6 @@
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
- "dev": true,
"requires": {
"yallist": "^4.0.0"
}
@@ -14993,6 +15047,12 @@
"resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
"integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
"dev": true
+ },
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true
}
}
},
@@ -15520,6 +15580,11 @@
"tslib": "^2.0.3"
}
},
+ "node-downloader-helper": {
+ "version": "1.0.17",
+ "resolved": "https://registry.npmjs.org/node-downloader-helper/-/node-downloader-helper-1.0.17.tgz",
+ "integrity": "sha512-EnaY0uBSdVo4kYfSmkDlTJG8GqmS8fbfoOau/OsTnikCwt9vsU0w8REVxwWbVz7DzNtHSEBKpU6jV1hmtlx0Dg=="
+ },
"node-forge": {
"version": "0.10.0",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz",
@@ -15680,6 +15745,11 @@
"glob": "^7.1.3"
}
},
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
+ },
"tar": {
"version": "4.4.13",
"resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz",
@@ -15748,6 +15818,14 @@
"resolve": "^1.10.0",
"semver": "2 || 3 || 4 || 5",
"validate-npm-package-license": "^3.0.1"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true
+ }
}
},
"normalize-path": {
@@ -18003,6 +18081,14 @@
"dev": true,
"requires": {
"semver": "^5.6.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true
+ }
}
},
"react-dev-utils": {
@@ -19400,9 +19486,12 @@
}
},
"semver": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
- "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
+ "version": "7.3.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz",
+ "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==",
+ "requires": {
+ "lru-cache": "^6.0.0"
+ }
},
"semver-compare": {
"version": "1.0.0",
@@ -23030,8 +23119,7 @@
"yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
- "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
- "dev": true
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
},
"yaml": {
"version": "1.10.0",
diff --git a/package.json b/package.json
index 554c7a8..b4bb67d 100644
--- a/package.json
+++ b/package.json
@@ -1,8 +1,8 @@
{
"name": "cbetar2",
"productName": "電子佛典",
- "pwaVersion": "4.22.0",
- "version": "12.0.1",
+ "pwaVersion": "4.23.0",
+ "version": "13.0.0",
"license": "MIT",
"keywords": [
"CBETA",
@@ -49,8 +49,12 @@
"extends": "react-app"
},
"dependencies": {
+ "@types/semver": "^7.3.4",
+ "axios": "^0.21.1",
"electron-window-state": "^5.0.3",
- "libxslt-myh": "^0.9.7"
+ "libxslt-myh": "^0.9.7",
+ "node-downloader-helper": "^1.0.17",
+ "semver": "^7.3.4"
},
"devDependencies": {
"@ionic/react": "^5.5.3",
@@ -68,7 +72,6 @@
"@types/react-router": "^5.1.8",
"@types/react-router-dom": "^5.1.6",
"@types/uuid": "^8.3.0",
- "axios": "^0.21.1",
"customize-cra": "^1.0.0",
"electron": "^11.2.1",
"electron-builder": "^22.9.1",
diff --git a/src/App.tsx b/src/App.tsx
index db82881..fa754af 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -47,6 +47,7 @@ import DictionaryPage from './pages/DictionaryPage';
import FullTextSearchPage from './pages/FullTextSearchPage';
import ShareTextModal from './components/ShareTextModal';
import WordDictionaryPage from './pages/WordDictionaryPage';
+import DownloadModal from './components/DownloadModal';
const electronBackendApi: any = (window as any).electronBackendApi;
@@ -97,6 +98,7 @@ interface State {
toastMessage: string;
showUpdateAlert: boolean;
showRestoreAppSettingsToast: boolean;
+ downloadModal: any;
}
class _App extends React.Component {
@@ -135,6 +137,12 @@ class _AppOrig extends React.Component {
val: data.isOn,
});
break;
+ case 'DownloadingBackend':
+ this.setState({ downloadModal: { show: true, progress: data.progress / 100 } });
+ break;
+ case 'DownloadingBackendDone':
+ this.setState({ downloadModal: { show: false, progress: this.state.downloadModal.progress } });
+ break;
}
});
electronBackendApi?.send("toMain", { event: 'ready' });
@@ -183,6 +191,7 @@ class _AppOrig extends React.Component {
showRestoreAppSettingsToast: (queryParams.settings != null && this.originalAppSettingsStr != null) || false,
showToast: false,
toastMessage: '',
+ downloadModal: { progress: 0, show: false }
};
serviceWorkCallbacks.onUpdate = (registration: ServiceWorkerRegistration) => {
@@ -385,6 +394,14 @@ class _AppOrig extends React.Component {
}}
/>
+
+
{ }
+
+interface State {
+ isAppSettingsExport: Array;
+}
+
+class _DownloadModal extends React.Component {
+
+ constructor(props: any) {
+ super(props);
+ this.state = {
+ isAppSettingsExport: Array(Object.keys(Globals.appSettings).length)
+ }
+ }
+
+ render() {
+ return (
+
+
+
+
+ 後端app下載進度
+
+
+
{Math.floor(this.props.progress * 100)}%
+
+
+
+ );
+ }
+};
+
+const mapStateToProps = (state: any /*, ownProps*/) => {
+ return {
+ }
+};
+
+//const mapDispatchToProps = {};
+
+export default connect(
+ mapStateToProps,
+)(_DownloadModal);
diff --git a/srcElectron/Globals.ts b/srcElectron/Globals.ts
index 24a84d6..146f23a 100644
--- a/srcElectron/Globals.ts
+++ b/srcElectron/Globals.ts
@@ -1 +1,11 @@
-export const localFileProtocolName = 'safe-file-protocol';
\ No newline at end of file
+export const localFileProtocolName = 'safe-file-protocol';
+export const latestDownloadUrl = 'https://github.com/MrMYHuang/cbetar2/releases/latest/download';
+import * as fs from 'fs';
+export function backendAppPackageType() {
+ if (fs.existsSync(`${process.resourcesPath}/IsWin.txt`)) return 'win';
+ if (fs.existsSync(`${process.resourcesPath}/IsMac.txt`)) return 'mac';
+ if (fs.existsSync(`${process.resourcesPath}/IsRpm.txt`)) return 'rpm';
+ if (fs.existsSync(`${process.resourcesPath}/IsDeb.txt`)) return 'deb';
+ if (fs.existsSync(`${process.resourcesPath}/IsSnap.txt`)) return 'snap';
+ return 'unknown';
+}
\ No newline at end of file
diff --git a/srcElectron/Update.ts b/srcElectron/Update.ts
new file mode 100644
index 0000000..09db5ac
--- /dev/null
+++ b/srcElectron/Update.ts
@@ -0,0 +1,76 @@
+import * as semver from 'semver';
+import { dialog, BrowserWindow } from 'electron';
+import axios from 'axios';
+import { DownloaderHelper, Stats } from 'node-downloader-helper';
+import * as Globals from './Globals';
+const PackageInfos = require('../package.json');
+
+const axiosInstance = axios.create({
+ timeout: 5000,
+});
+
+export async function lookupLatestVersion() {
+ const result = await axiosInstance.get(`${Globals.latestDownloadUrl}/latest.yml`, { responseType: 'text' });
+ return /version: (.*)\n/.exec(result.data)![1];
+}
+
+export async function check(browserWindow: BrowserWindow) {
+ const lastestVersion = await lookupLatestVersion();
+ if (semver.gte(PackageInfos.version, lastestVersion)) {
+ dialog.showMessageBox({
+ type: 'info',
+ message: '後端app已是最新版!'
+ });
+ return
+ }
+
+ const clickedButtonId = dialog.showMessageBoxSync(browserWindow, {
+ type: 'question',
+ message: `發現新版cbetar2 ${lastestVersion}後端app,是否下載安裝檔?`,
+ buttons: ['取消', '下載'],
+ });
+
+ let packageSuffix = 'win64.exe';
+ switch (Globals.backendAppPackageType()) {
+ case 'win': packageSuffix = 'win64.exe'; break;
+ case 'mac': packageSuffix = 'macos64.pkg'; break;
+ case 'rpm': packageSuffix = 'linux64.rpm'; break;
+ case 'deb': packageSuffix = 'linux64.deb'; break;
+ case 'snap': packageSuffix = 'linux64.snap'; break;
+ }
+
+ if (clickedButtonId) {
+ const path = dialog.showOpenDialogSync(browserWindow, {
+ message: '選擇下載位置',
+ properties: ['openDirectory']
+ });
+ const file = `${PackageInfos.name}_${lastestVersion}_${packageSuffix}`;
+ const downloadUrl = `${Globals.latestDownloadUrl}/${file}`;
+
+ if (path) {
+ const dl = new DownloaderHelper(downloadUrl, path[0]);
+ browserWindow.webContents.send('fromMain', { event: 'DownloadingBackend', progress: 0 });
+ let progressUpdateEnable = true;
+ dl.on('progress', (stats: Stats) => {
+ if (progressUpdateEnable) {
+ // Reduce number of this calls.
+ // Too many of this calls could result in 'end' event callback is executed before 'progress' event callbacks!
+ browserWindow.webContents.send('fromMain', { event: 'DownloadingBackend', progress: stats.progress });
+ progressUpdateEnable = false;
+ setTimeout(() => {
+ progressUpdateEnable = true;
+ }, 100);
+ }
+ });
+ dl.on('end', (downloadInfo: any) => {
+ dl.removeAllListeners();
+ browserWindow.webContents.send('fromMain', { event: 'DownloadingBackendDone' });
+ dialog.showMessageBox({
+ type: 'info',
+ message: '新版後端app安裝程式下載完成!請關閉app,手動執行安裝程式。'
+ });
+ });
+ dl.start();
+ }
+ }
+}
\ No newline at end of file
diff --git a/srcElectron/main.ts b/srcElectron/main.ts
index a2ee991..ffaeb14 100644
--- a/srcElectron/main.ts
+++ b/srcElectron/main.ts
@@ -5,6 +5,7 @@ const path = require('path');
import * as fs from 'fs';
import * as os from 'os';
const PackageInfos = require('../package.json');
+import * as update from './Update';
import * as cbetaOfflineDb from './CbetaOfflineDb';
import * as Globals from './Globals';
@@ -55,6 +56,7 @@ async function setCbetaBookcase() {
}
} else {
dialog.showMessageBox({
+ type: 'info',
message: '設定取消'
});
}
@@ -79,6 +81,13 @@ function loadSettings() {
}
}
+async function checkUpdate() {
+ const latestVersion = await update.lookupLatestVersion();
+ update.check(mainWindow!);
+ settings.lastCheckedVersion = latestVersion;
+ fs.writeFileSync(backendAppSettingsFile, JSON.stringify(settings));
+}
+
const template = [
new MenuItem({
label: '檔案',
@@ -142,13 +151,17 @@ const template = [
role: 'forceReload',
label: '強制重新載入',
},
+ {
+ label: '檢查後端app更新',
+ click: checkUpdate,
+ },
]
}),
];
const menu = Menu.buildFromTemplate(template)
Menu.setApplicationMenu(menu)
-function createWindow() {
+async function createWindow() {
frontendIsReady = false;
let mainWindowState = windowStateKeeper({
@@ -173,11 +186,16 @@ function createWindow() {
// Open the DevTools.
//mainWindow.webContents.openDevTools()
- ipcMain.on('toMain', (ev, args) => {
+ ipcMain.on('toMain', async (ev, args) => {
switch (args.event) {
case 'ready':
frontendIsReady = true;
loadSettings();
+ const latestVersion = await update.lookupLatestVersion();
+ // Ask for updating for each new version once.
+ if (settings.lastCheckedVersion !== latestVersion) {
+ checkUpdate();
+ }
mainWindow?.webContents.send('fromMain', { event: 'version', version: PackageInfos.version });
break;
case 'fetchCatalog':