perf: 优化客户端自动更新
This commit is contained in:
parent
c6ebe994cc
commit
2a8e030fb4
115
electron/main.js
vendored
115
electron/main.js
vendored
@ -14,7 +14,7 @@ let mainWindow = null,
|
|||||||
devloadUrl = "",
|
devloadUrl = "",
|
||||||
devloadCachePath = path.resolve(__dirname, ".devload"),
|
devloadCachePath = path.resolve(__dirname, ".devload"),
|
||||||
downloadList = [],
|
downloadList = [],
|
||||||
downloadCacheFile = path.join(app.getPath('cache'), config.name + '.downloadCache');
|
downloadCacheFile = path.join(app.getPath('cache'), config.name, '.downloadCache');
|
||||||
|
|
||||||
if (fs.existsSync(devloadCachePath)) {
|
if (fs.existsSync(devloadCachePath)) {
|
||||||
devloadUrl = fs.readFileSync(devloadCachePath, 'utf8')
|
devloadUrl = fs.readFileSync(devloadCachePath, 'utf8')
|
||||||
@ -23,6 +23,39 @@ if (fs.existsSync(downloadCacheFile)) {
|
|||||||
downloadList = utils.jsonParse(fs.readFileSync(downloadCacheFile, 'utf8'), [])
|
downloadList = utils.jsonParse(fs.readFileSync(downloadCacheFile, 'utf8'), [])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function downloadUpdate(item) {
|
||||||
|
const chain = item.getURLChain()
|
||||||
|
if (chain.length == 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let currentState = item.getState()
|
||||||
|
if (currentState == "progressing" && item.isPaused()) {
|
||||||
|
currentState = "paused"
|
||||||
|
}
|
||||||
|
//
|
||||||
|
const downloadItem = downloadList.find(item => item.url == chain[0])
|
||||||
|
if (downloadItem && downloadItem.state != currentState) {
|
||||||
|
downloadItem.state = currentState;
|
||||||
|
downloadItem.result = {
|
||||||
|
url: item.getURL(),
|
||||||
|
name: item.getFilename(),
|
||||||
|
savePath: item.getSavePath(),
|
||||||
|
mimeType: item.getMimeType(),
|
||||||
|
totalBytes: item.getTotalBytes(),
|
||||||
|
chain,
|
||||||
|
};
|
||||||
|
fs.writeFileSync(downloadCacheFile, utils.jsonStringify(downloadList), 'utf8');
|
||||||
|
//
|
||||||
|
if (currentState == 'completed') {
|
||||||
|
mainWindow.webContents.send("downloadDone", downloadItem)
|
||||||
|
log.info("下载完成", downloadItem)
|
||||||
|
} else {
|
||||||
|
mainWindow.webContents.send("downloadUpdate", downloadItem)
|
||||||
|
log.info("下载更新", downloadItem)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function createMainWindow() {
|
function createMainWindow() {
|
||||||
mainWindow = new BrowserWindow({
|
mainWindow = new BrowserWindow({
|
||||||
width: 1280,
|
width: 1280,
|
||||||
@ -69,37 +102,12 @@ function createMainWindow() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
mainWindow.webContents.session.on('will-download', (event, item) => {
|
mainWindow.webContents.session.on('will-download', (event, item) => {
|
||||||
item.setSavePath(path.join(app.getPath('cache'), item.getFilename()));
|
item.setSavePath(path.join(app.getPath('cache'), config.name, item.getFilename()));
|
||||||
item.on('done', (event, state) => {
|
item.on('updated', () => {
|
||||||
try {
|
downloadUpdate(item)
|
||||||
const info = {
|
|
||||||
state,
|
|
||||||
name: item.getFilename(),
|
|
||||||
url: item.getURL(),
|
|
||||||
chain: item.getURLChain(),
|
|
||||||
savePath: item.getSavePath(),
|
|
||||||
mimeType: item.getMimeType(),
|
|
||||||
totalBytes: item.getTotalBytes(),
|
|
||||||
};
|
|
||||||
mainWindow.webContents.send("downloadDone", info)
|
|
||||||
//
|
|
||||||
if (info.state == "completed") {
|
|
||||||
// 下载完成
|
|
||||||
info.chain.some(url => {
|
|
||||||
let download = downloadList.find(item => item.url == url)
|
|
||||||
if (download) {
|
|
||||||
download.status = "completed"
|
|
||||||
download.info = info
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
fs.writeFileSync(downloadCacheFile, utils.jsonStringify(downloadList), 'utf8');
|
item.on('done', () => {
|
||||||
} else {
|
downloadUpdate(item)
|
||||||
// 下载失败
|
|
||||||
info.chain.some(url => {
|
|
||||||
downloadList = downloadList.filter(item => item.url != url)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
} catch (e) { }
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -201,26 +209,33 @@ ipcMain.on('inheritClose', (event) => {
|
|||||||
* @param args {url}
|
* @param args {url}
|
||||||
*/
|
*/
|
||||||
ipcMain.on('downloadFile', (event, args) => {
|
ipcMain.on('downloadFile', (event, args) => {
|
||||||
const download = downloadList.find(({url}) => url == args.url);
|
|
||||||
if (download) {
|
|
||||||
if (download.status == "completed") {
|
|
||||||
if (fs.existsSync(download.info.savePath)) {
|
|
||||||
log.warn("已下载完成", args)
|
|
||||||
mainWindow.webContents.send("downloadDone", download.info)
|
|
||||||
} else {
|
|
||||||
log.info("开始重新下载", args)
|
|
||||||
download.status = "progressing"
|
|
||||||
mainWindow.webContents.downloadURL(args.url);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log.warn("已在下载列表中", args)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log.info("开始下载", args)
|
|
||||||
downloadList.push(Object.assign(args, { status: "progressing" }))
|
|
||||||
mainWindow.webContents.downloadURL(args.url);
|
|
||||||
}
|
|
||||||
event.returnValue = "ok"
|
event.returnValue = "ok"
|
||||||
|
//
|
||||||
|
let appendJson = {state: "progressing", startTime: utils.Time()}
|
||||||
|
let downloadItem = downloadList.find(({url}) => url == args.url)
|
||||||
|
if (downloadItem) {
|
||||||
|
switch (downloadItem.state) {
|
||||||
|
case "completed":
|
||||||
|
if (fs.existsSync(downloadItem.result.savePath)) { // 下载完成,文件存在
|
||||||
|
log.info("下载已完成", downloadItem)
|
||||||
|
mainWindow.webContents.send("downloadDone", downloadItem)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "progressing":
|
||||||
|
if (downloadItem.startTime + 480 > utils.Time()) { // 下载中,未超时(超时时间8分钟)
|
||||||
|
log.info("下载已存在", downloadItem)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
downloadItem = Object.assign(downloadItem, appendJson)
|
||||||
|
} else {
|
||||||
|
downloadList.push(downloadItem = Object.assign(args, appendJson))
|
||||||
|
}
|
||||||
|
fs.writeFileSync(downloadCacheFile, utils.jsonStringify(downloadList), 'utf8');
|
||||||
|
mainWindow.webContents.downloadURL(downloadItem.url);
|
||||||
|
log.info("下载开始", downloadItem)
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
17
electron/utils.js
vendored
17
electron/utils.js
vendored
@ -252,4 +252,21 @@ module.exports = {
|
|||||||
let domain = (weburl + "").match(urlReg);
|
let domain = (weburl + "").match(urlReg);
|
||||||
return ((domain != null && domain.length > 0) ? domain[2] : "");
|
return ((domain != null && domain.length > 0) ? domain[2] : "");
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回10位数时间戳
|
||||||
|
* @param v
|
||||||
|
* @returns {number}
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
Time(v = undefined) {
|
||||||
|
let time
|
||||||
|
if (typeof v === "string" && this.strExists(v, "-")) {
|
||||||
|
v = v.replace(/-/g, '/');
|
||||||
|
time = new Date(v).getTime();
|
||||||
|
} else {
|
||||||
|
time = new Date().getTime();
|
||||||
|
}
|
||||||
|
return Math.round(time / 1000)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
<div v-if="$Electron" class="common-app-down-link" @click="releasesNotification">
|
<div v-if="$Electron" class="common-app-down-link" @click="releasesNotification">
|
||||||
<Icon type="md-download"/> {{$L(repoTitle)}}
|
<Icon type="md-download"/> {{$L(repoTitle)}}
|
||||||
</div>
|
</div>
|
||||||
<a v-else class="common-app-down-link" :href="releases.html_url" target="_blank">
|
<a v-else class="common-app-down-link" :href="repoReleases.html_url" target="_blank">
|
||||||
<Icon type="md-download"/> {{$L(repoTitle)}}
|
<Icon type="md-download"/> {{$L(repoTitle)}}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
@ -15,7 +15,6 @@ import MarkdownPreview from "./MDEditor/components/preview";
|
|||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
Vue.component('MarkdownPreview', MarkdownPreview)
|
Vue.component('MarkdownPreview', MarkdownPreview)
|
||||||
|
|
||||||
import {Store} from "le5le-store";
|
|
||||||
import {mapState} from "vuex";
|
import {mapState} from "vuex";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@ -26,19 +25,19 @@ export default {
|
|||||||
|
|
||||||
repoName: 'kuaifan/dootask',
|
repoName: 'kuaifan/dootask',
|
||||||
repoData: {},
|
repoData: {},
|
||||||
|
repoStatus: 0, // 0 没有,1有客户端,2客户端有新版本
|
||||||
|
repoReleases: {},
|
||||||
|
|
||||||
status: 0, // 0 没有,1有客户端,2客户端有新版本
|
downloadResult: {},
|
||||||
releases: {},
|
|
||||||
downInfo: {},
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.getReleases();
|
this.getReleases();
|
||||||
//
|
//
|
||||||
if (this.$Electron) {
|
if (this.$Electron) {
|
||||||
this.$Electron.ipcRenderer.on('downloadDone', (event, args) => {
|
this.$Electron.ipcRenderer.on('downloadDone', (event, {result}) => {
|
||||||
if (args.name == this.repoData.name) {
|
if (result.name == this.repoData.name) {
|
||||||
this.downInfo = args;
|
this.downloadResult = result;
|
||||||
this.releasesNotification()
|
this.releasesNotification()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -49,10 +48,10 @@ export default {
|
|||||||
'wsOpenNum',
|
'wsOpenNum',
|
||||||
]),
|
]),
|
||||||
repoTitle() {
|
repoTitle() {
|
||||||
return this.status == 2 ? '更新客户端' : '客户端下载';
|
return this.repoStatus == 2 ? '更新客户端' : '客户端下载';
|
||||||
},
|
},
|
||||||
showButton() {
|
showButton() {
|
||||||
return this.status && !this.$store.state.windowMax768 && ['login', 'manage-dashboard'].includes(this.$route.name)
|
return this.repoStatus && !this.$store.state.windowMax768 && ['login', 'manage-dashboard'].includes(this.$route.name)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
@ -108,7 +107,7 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
getReleases() {
|
getReleases() {
|
||||||
if (this.status > 0) {
|
if (this.repoStatus > 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.loadIng > 0) {
|
if (this.loadIng > 0) {
|
||||||
@ -116,10 +115,11 @@ export default {
|
|||||||
}
|
}
|
||||||
//
|
//
|
||||||
let cache = $A.getStorageJson("cacheAppdown");
|
let cache = $A.getStorageJson("cacheAppdown");
|
||||||
let timeout = 1800;
|
let timeout = 600;
|
||||||
if (cache.time && cache.time + timeout > Math.round(new Date().getTime() / 1000)) {
|
if (cache.time && cache.time + timeout > Math.round(new Date().getTime() / 1000)) {
|
||||||
this.releases = cache.data;
|
this.repoReleases = cache.data;
|
||||||
this.chackReleases()
|
this.chackReleases()
|
||||||
|
setTimeout(this.getReleases, timeout * 1000)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
@ -127,22 +127,24 @@ export default {
|
|||||||
axios.get("https://api.github.com/repos/" + this.repoName + "/releases/latest").then(({status, data}) => {
|
axios.get("https://api.github.com/repos/" + this.repoName + "/releases/latest").then(({status, data}) => {
|
||||||
this.loadIng--;
|
this.loadIng--;
|
||||||
if (status === 200) {
|
if (status === 200) {
|
||||||
$A.setStorage("cacheAppdown", {
|
cache = {
|
||||||
time: Math.round(new Date().getTime() / 1000),
|
time: Math.round(new Date().getTime() / 1000),
|
||||||
data: data
|
data: data
|
||||||
});
|
|
||||||
this.releases = data;
|
|
||||||
this.chackReleases();
|
|
||||||
setTimeout(this.getReleases, timeout)
|
|
||||||
}
|
}
|
||||||
|
$A.setStorage("cacheAppdown", cache);
|
||||||
|
this.repoReleases = cache.data;
|
||||||
|
this.chackReleases()
|
||||||
|
}
|
||||||
|
setTimeout(this.getReleases, timeout * 1000)
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
this.loadIng--;
|
this.loadIng--;
|
||||||
|
setTimeout(this.getReleases, timeout * 1000)
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
chackReleases() {
|
chackReleases() {
|
||||||
let hostName = $A.getDomain(window.systemInfo.apiUrl);
|
let hostName = $A.getDomain(window.systemInfo.apiUrl);
|
||||||
if (hostName == "" || hostName == '127.0.0.1') {
|
if (hostName == "" || $A.leftExists(hostName, '127.0.0.1')) {
|
||||||
hostName = "public"
|
hostName = "public"
|
||||||
}
|
}
|
||||||
if (this.$Electron) {
|
if (this.$Electron) {
|
||||||
@ -153,18 +155,18 @@ export default {
|
|||||||
}
|
}
|
||||||
let artifactName = null;
|
let artifactName = null;
|
||||||
if (match[2] === 'darwin') {
|
if (match[2] === 'darwin') {
|
||||||
artifactName = `${hostName}-${this.releases.tag_name}-mac-${match[3]}.pkg`;
|
artifactName = `${hostName}-${this.repoReleases.tag_name}-mac-${match[3]}.pkg`;
|
||||||
} else if (match[2] === 'win32') {
|
} else if (match[2] === 'win32') {
|
||||||
artifactName = `${hostName}-${this.releases.tag_name}-win-${match[3]}.exe`;
|
artifactName = `${hostName}-${this.repoReleases.tag_name}-win-${match[3]}.exe`;
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.repoData = (this.releases.assets || []).find(({name}) => name == artifactName);
|
this.repoData = (this.repoReleases.assets || []).find(({name}) => name == artifactName);
|
||||||
if (!this.repoData) {
|
if (!this.repoData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let currentVersion = window.systemInfo.version;
|
let currentVersion = window.systemInfo.version;
|
||||||
let latestVersion = $A.leftDelete(this.releases.tag_name.toLowerCase(), "v")
|
let latestVersion = $A.leftDelete(this.repoReleases.tag_name.toLowerCase(), "v")
|
||||||
if (this.compareVersion(latestVersion, currentVersion) === 1) {
|
if (this.compareVersion(latestVersion, currentVersion) === 1) {
|
||||||
// 有新版本
|
// 有新版本
|
||||||
console.log("New version: " + latestVersion);
|
console.log("New version: " + latestVersion);
|
||||||
@ -174,26 +176,23 @@ export default {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 网页版(提示有客户端下载)
|
// 网页版(提示有客户端下载)
|
||||||
this.repoData = (this.releases.assets || []).find(({name}) => $A.strExists(name, hostName));
|
this.repoData = (this.repoReleases.assets || []).find(({name}) => $A.strExists(name, hostName));
|
||||||
if (this.repoData) {
|
if (this.repoData) {
|
||||||
let latestVersion = $A.leftDelete(this.releases.tag_name.toLowerCase(), "v")
|
let latestVersion = $A.leftDelete(this.repoReleases.tag_name.toLowerCase(), "v")
|
||||||
console.log("Exist client: " + latestVersion);
|
console.log("Exist client: " + latestVersion);
|
||||||
this.status = 1;
|
this.repoStatus = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
releasesNotification() {
|
releasesNotification() {
|
||||||
if (this.downInfo.state != "completed") {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$A.modalConfirm({
|
$A.modalConfirm({
|
||||||
okText: this.$L('立即更新'),
|
okText: this.$L('立即更新'),
|
||||||
onOk: () => {
|
onOk: () => {
|
||||||
this.installApplication();
|
this.installApplication();
|
||||||
},
|
},
|
||||||
onCancel: () => {
|
onCancel: () => {
|
||||||
this.status = 2;
|
this.repoStatus = 2;
|
||||||
},
|
},
|
||||||
render: (h) => {
|
render: (h) => {
|
||||||
return h('div', {
|
return h('div', {
|
||||||
@ -209,12 +208,12 @@ export default {
|
|||||||
props: {
|
props: {
|
||||||
color: 'volcano'
|
color: 'volcano'
|
||||||
}
|
}
|
||||||
}, this.releases.tag_name)
|
}, this.repoReleases.tag_name)
|
||||||
]),
|
]),
|
||||||
h('MarkdownPreview', {
|
h('MarkdownPreview', {
|
||||||
class: 'notification-body',
|
class: 'notification-body',
|
||||||
props: {
|
props: {
|
||||||
initialValue: this.releases.body
|
initialValue: this.repoReleases.body
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
])
|
])
|
||||||
@ -227,7 +226,7 @@ export default {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.$Electron.ipcRenderer.send('openFile', {
|
this.$Electron.ipcRenderer.send('openFile', {
|
||||||
path: this.downInfo.savePath
|
path: this.downloadResult.savePath
|
||||||
});
|
});
|
||||||
this.$Electron.ipcRenderer.send('windowQuit');
|
this.$Electron.ipcRenderer.send('windowQuit');
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,8 @@
|
|||||||
}
|
}
|
||||||
.notification-body {
|
.notification-body {
|
||||||
max-height: 210px;
|
max-height: 210px;
|
||||||
overflow: auto;
|
overflow-x: hidden;
|
||||||
|
overflow-y: auto;
|
||||||
margin: 18px 0;
|
margin: 18px 0;
|
||||||
.markdown-preview {
|
.markdown-preview {
|
||||||
margin: -20px -12px;
|
margin: -20px -12px;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user