mirror of
https://github.com/earthjasonlin/zzz-signal-search-export.git
synced 2024-11-22 13:20:23 +08:00
feat(update): re-implement auto update
This commit is contained in:
parent
bebb14b63d
commit
8b725053ce
51
.electron-vite/update.js
Normal file
51
.electron-vite/update.js
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
const fs = require('fs-extra')
|
||||||
|
const path = require('path')
|
||||||
|
const crypto = require('crypto')
|
||||||
|
const AdmZip = require('adm-zip')
|
||||||
|
const { version } = require('../package.json')
|
||||||
|
|
||||||
|
const hash = (data, type = 'sha256') => {
|
||||||
|
const hmac = crypto.createHmac(type, 'nap')
|
||||||
|
hmac.update(data)
|
||||||
|
return hmac.digest('hex')
|
||||||
|
}
|
||||||
|
|
||||||
|
const createZip = (filePath, dest) => {
|
||||||
|
const zip = new AdmZip()
|
||||||
|
zip.addLocalFolder(filePath)
|
||||||
|
zip.toBuffer()
|
||||||
|
zip.writeZip(dest)
|
||||||
|
}
|
||||||
|
|
||||||
|
const start = async () => {
|
||||||
|
copyAppZip()
|
||||||
|
const appPath = './build/win-ia32-unpacked/resources/app'
|
||||||
|
const name = 'app.zip'
|
||||||
|
const outputPath = path.resolve('./build/update/update/')
|
||||||
|
const zipPath = path.resolve(outputPath, name)
|
||||||
|
await fs.ensureDir(outputPath)
|
||||||
|
await fs.emptyDir(outputPath)
|
||||||
|
createZip(appPath, zipPath)
|
||||||
|
const buffer = await fs.readFile(zipPath)
|
||||||
|
const sha256 = hash(buffer)
|
||||||
|
const hashName = sha256.slice(7, 12)
|
||||||
|
await fs.copy(zipPath, path.resolve(outputPath, `${hashName}.zip`))
|
||||||
|
await fs.remove(zipPath)
|
||||||
|
await fs.outputJSON(path.join(outputPath, 'manifest.json'), {
|
||||||
|
active: true,
|
||||||
|
version,
|
||||||
|
from: '0.0.1',
|
||||||
|
name: `${hashName}.zip`,
|
||||||
|
hash: sha256
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const copyAppZip = () => {
|
||||||
|
try {
|
||||||
|
const dir = path.resolve('./build')
|
||||||
|
const filePath = path.resolve(dir, `ZzzSignalSearchExport-${version}-ia32-win.zip`)
|
||||||
|
fs.copySync(filePath, path.join(dir, 'app.zip'))
|
||||||
|
} catch (e) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
start()
|
55
.github/workflows/release.yml
vendored
Normal file
55
.github/workflows/release.yml
vendored
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
push:
|
||||||
|
# Sequence of patterns matched against refs/tag
|
||||||
|
tags:
|
||||||
|
- 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10
|
||||||
|
|
||||||
|
name: Release
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Release
|
||||||
|
runs-on: windows-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: Use Node.js
|
||||||
|
uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: '16.x'
|
||||||
|
- name: Build App
|
||||||
|
run: |
|
||||||
|
yarn --frozen-lockfile
|
||||||
|
yarn build:win32
|
||||||
|
yarn build-update
|
||||||
|
- name: Create Release
|
||||||
|
if: success()
|
||||||
|
id: create_release
|
||||||
|
uses: actions/create-release@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.TOKEN }}
|
||||||
|
with:
|
||||||
|
tag_name: ${{ github.ref }}
|
||||||
|
release_name: ZzzSignalSearchExport ${{ github.ref }}
|
||||||
|
draft: false
|
||||||
|
prerelease: false
|
||||||
|
- name: Upload Release Asset
|
||||||
|
if: success()
|
||||||
|
id: upload-release-asset
|
||||||
|
uses: actions/upload-release-asset@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.TOKEN }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
|
||||||
|
asset_path: ./build/app.zip
|
||||||
|
asset_name: ZzzSignalSearchExport.zip
|
||||||
|
asset_content_type: application/zip
|
||||||
|
- name: Deploy update
|
||||||
|
if: success()
|
||||||
|
uses: crazy-max/ghaction-github-pages@v2
|
||||||
|
with:
|
||||||
|
commit_message: Update app
|
||||||
|
build_dir: ./build/update
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.TOKEN }}
|
@ -16,6 +16,7 @@
|
|||||||
"build:dir": "cross-env BUILD_TARGET=clean node .electron-vite/build.js && electron-builder --dir",
|
"build:dir": "cross-env BUILD_TARGET=clean node .electron-vite/build.js && electron-builder --dir",
|
||||||
"build:clean": "cross-env BUILD_TARGET=onlyClean node .electron-vite/build.js",
|
"build:clean": "cross-env BUILD_TARGET=onlyClean node .electron-vite/build.js",
|
||||||
"build:web": "cross-env BUILD_TARGET=web node .electron-vite/build.js",
|
"build:web": "cross-env BUILD_TARGET=web node .electron-vite/build.js",
|
||||||
|
"build-update": "node .electron-vite/update.js",
|
||||||
"dev:web": "cross-env TARGET=web node .electron-vite/dev-runner.js",
|
"dev:web": "cross-env TARGET=web node .electron-vite/dev-runner.js",
|
||||||
"start": "electron ./src/main/main.js",
|
"start": "electron ./src/main/main.js",
|
||||||
"dep:upgrade": "yarn upgrade-interactive --latest",
|
"dep:upgrade": "yarn upgrade-interactive --latest",
|
||||||
|
@ -87,6 +87,7 @@
|
|||||||
"log.proxy.hint": "Using proxy mode [${ip}:${port}] to get URL,please reopen warp history inside the game client.",
|
"log.proxy.hint": "Using proxy mode [${ip}:${port}] to get URL,please reopen warp history inside the game client.",
|
||||||
"log.url.notFound2": "Unable to find URL, please make sure you already opened warp history inside the game client",
|
"log.url.notFound2": "Unable to find URL, please make sure you already opened warp history inside the game client",
|
||||||
"log.url.incorrect": "Unable to get URL parameters",
|
"log.url.incorrect": "Unable to get URL parameters",
|
||||||
|
"log.autoUpdate.success": "Auto update successful,please restart the program",
|
||||||
"excel.header.time": "time",
|
"excel.header.time": "time",
|
||||||
"excel.header.name": "name",
|
"excel.header.name": "name",
|
||||||
"excel.header.type": "type",
|
"excel.header.type": "type",
|
||||||
|
@ -86,6 +86,7 @@
|
|||||||
"log.proxy.hint": "正在使用代理模式[${ip}:${port}]获取URL,请重新打开游戏抽卡记录。",
|
"log.proxy.hint": "正在使用代理模式[${ip}:${port}]获取URL,请重新打开游戏抽卡记录。",
|
||||||
"log.url.notFound2": "未找到URL,请确认是否已打开游戏抽卡记录",
|
"log.url.notFound2": "未找到URL,请确认是否已打开游戏抽卡记录",
|
||||||
"log.url.incorrect": "获取URL参数失败",
|
"log.url.incorrect": "获取URL参数失败",
|
||||||
|
"log.autoUpdate.success": "自动更新已完成,重启工具后生效",
|
||||||
"excel.header.time": "时间",
|
"excel.header.time": "时间",
|
||||||
"excel.header.name": "名称",
|
"excel.header.name": "名称",
|
||||||
"excel.header.type": "类别",
|
"excel.header.type": "类别",
|
||||||
|
@ -5,6 +5,7 @@ require('./getData')
|
|||||||
require('./bridge')
|
require('./bridge')
|
||||||
require('./excel')
|
require('./excel')
|
||||||
require('./SRGFJson')
|
require('./SRGFJson')
|
||||||
|
const { getUpdateInfo } = require('./update/index')
|
||||||
|
|
||||||
const isDev = !app.isPackaged
|
const isDev = !app.isPackaged
|
||||||
let win = null
|
let win = null
|
||||||
@ -53,6 +54,12 @@ if (!isFirstInstance) {
|
|||||||
if (proxyStatus.started) {
|
if (proxyStatus.started) {
|
||||||
disableProxy()
|
disableProxy()
|
||||||
}
|
}
|
||||||
|
if (getUpdateInfo().status === 'moving') {
|
||||||
|
e.preventDefault()
|
||||||
|
setTimeout(() => {
|
||||||
|
app.quit()
|
||||||
|
}, 3000)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
app.on('quit', () => {
|
app.on('quit', () => {
|
||||||
|
185
src/main/module/extract-zip.js
Normal file
185
src/main/module/extract-zip.js
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
// Copyright (c) 2014 Max Ogden and other contributors
|
||||||
|
// All rights reserved.
|
||||||
|
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
// * Redistributions of source code must retain the above copyright notice, this
|
||||||
|
// list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer in the documentation
|
||||||
|
// and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
// https://github.com/maxogden/extract-zip
|
||||||
|
// eslint-disable-next-line node/no-unsupported-features/node-builtins
|
||||||
|
const { createWriteStream, promises: fs } = require('original-fs')
|
||||||
|
const getStream = require('get-stream')
|
||||||
|
const path = require('path')
|
||||||
|
const { promisify } = require('util')
|
||||||
|
const stream = require('stream')
|
||||||
|
const yauzl = require('yauzl')
|
||||||
|
|
||||||
|
const openZip = promisify(yauzl.open)
|
||||||
|
const pipeline = promisify(stream.pipeline)
|
||||||
|
|
||||||
|
class Extractor {
|
||||||
|
constructor (zipPath, opts) {
|
||||||
|
this.zipPath = zipPath
|
||||||
|
this.opts = opts
|
||||||
|
}
|
||||||
|
|
||||||
|
async extract () {
|
||||||
|
|
||||||
|
this.zipfile = await openZip(this.zipPath, { lazyEntries: true })
|
||||||
|
this.canceled = false
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
this.zipfile.on('error', err => {
|
||||||
|
this.canceled = true
|
||||||
|
reject(err)
|
||||||
|
})
|
||||||
|
this.zipfile.readEntry()
|
||||||
|
|
||||||
|
this.zipfile.on('close', () => {
|
||||||
|
if (!this.canceled) {
|
||||||
|
resolve()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
this.zipfile.on('entry', async entry => {
|
||||||
|
/* istanbul ignore if */
|
||||||
|
if (this.canceled) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (entry.fileName.startsWith('__MACOSX/')) {
|
||||||
|
this.zipfile.readEntry()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const destDir = path.dirname(path.join(this.opts.dir, entry.fileName))
|
||||||
|
|
||||||
|
try {
|
||||||
|
await fs.mkdir(destDir, { recursive: true })
|
||||||
|
|
||||||
|
const canonicalDestDir = await fs.realpath(destDir)
|
||||||
|
const relativeDestDir = path.relative(this.opts.dir, canonicalDestDir)
|
||||||
|
|
||||||
|
if (relativeDestDir.split(path.sep).includes('..')) {
|
||||||
|
throw new Error(`Out of bound path "${canonicalDestDir}" found while processing file ${entry.fileName}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.extractEntry(entry)
|
||||||
|
this.zipfile.readEntry()
|
||||||
|
} catch (err) {
|
||||||
|
this.canceled = true
|
||||||
|
this.zipfile.close()
|
||||||
|
reject(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async extractEntry (entry) {
|
||||||
|
/* istanbul ignore if */
|
||||||
|
if (this.canceled) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.opts.onEntry) {
|
||||||
|
this.opts.onEntry(entry, this.zipfile)
|
||||||
|
}
|
||||||
|
|
||||||
|
const dest = path.join(this.opts.dir, entry.fileName)
|
||||||
|
|
||||||
|
// convert external file attr int into a fs stat mode int
|
||||||
|
const mode = (entry.externalFileAttributes >> 16) & 0xFFFF
|
||||||
|
// check if it's a symlink or dir (using stat mode constants)
|
||||||
|
const IFMT = 61440
|
||||||
|
const IFDIR = 16384
|
||||||
|
const IFLNK = 40960
|
||||||
|
const symlink = (mode & IFMT) === IFLNK
|
||||||
|
let isDir = (mode & IFMT) === IFDIR
|
||||||
|
|
||||||
|
// Failsafe, borrowed from jsZip
|
||||||
|
if (!isDir && entry.fileName.endsWith('/')) {
|
||||||
|
isDir = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for windows weird way of specifying a directory
|
||||||
|
// https://github.com/maxogden/extract-zip/issues/13#issuecomment-154494566
|
||||||
|
const madeBy = entry.versionMadeBy >> 8
|
||||||
|
if (!isDir) isDir = (madeBy === 0 && entry.externalFileAttributes === 16)
|
||||||
|
|
||||||
|
|
||||||
|
const procMode = this.getExtractedMode(mode, isDir) & 0o777
|
||||||
|
|
||||||
|
// always ensure folders are created
|
||||||
|
const destDir = isDir ? dest : path.dirname(dest)
|
||||||
|
|
||||||
|
const mkdirOptions = { recursive: true }
|
||||||
|
if (isDir) {
|
||||||
|
mkdirOptions.mode = procMode
|
||||||
|
}
|
||||||
|
await fs.mkdir(destDir, mkdirOptions)
|
||||||
|
if (isDir) return
|
||||||
|
|
||||||
|
const readStream = await promisify(this.zipfile.openReadStream.bind(this.zipfile))(entry)
|
||||||
|
|
||||||
|
if (symlink) {
|
||||||
|
const link = await getStream(readStream)
|
||||||
|
await fs.symlink(link, dest)
|
||||||
|
} else {
|
||||||
|
await pipeline(readStream, createWriteStream(dest, { mode: procMode }))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getExtractedMode (entryMode, isDir) {
|
||||||
|
let mode = entryMode
|
||||||
|
// Set defaults, if necessary
|
||||||
|
if (mode === 0) {
|
||||||
|
if (isDir) {
|
||||||
|
if (this.opts.defaultDirMode) {
|
||||||
|
mode = parseInt(this.opts.defaultDirMode, 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mode) {
|
||||||
|
mode = 0o755
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (this.opts.defaultFileMode) {
|
||||||
|
mode = parseInt(this.opts.defaultFileMode, 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mode) {
|
||||||
|
mode = 0o644
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = async function (zipPath, opts) {
|
||||||
|
|
||||||
|
if (!path.isAbsolute(opts.dir)) {
|
||||||
|
throw new Error('Target directory is expected to be absolute')
|
||||||
|
}
|
||||||
|
|
||||||
|
await fs.mkdir(opts.dir, { recursive: true })
|
||||||
|
opts.dir = await fs.realpath(opts.dir)
|
||||||
|
return new Extractor(zipPath, opts).extract()
|
||||||
|
}
|
65
src/main/update/index.js
Normal file
65
src/main/update/index.js
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
const { app } = require('electron')
|
||||||
|
const fetch = require('electron-fetch').default
|
||||||
|
const semver = require('semver')
|
||||||
|
const util = require('util')
|
||||||
|
const path = require('path')
|
||||||
|
const fs = require('fs-extra')
|
||||||
|
const extract = require('../module/extract-zip')
|
||||||
|
const { version } = require('../../../package.json')
|
||||||
|
const { hash, sendMsg } = require('../utils')
|
||||||
|
const config = require('../config')
|
||||||
|
const i18n = require('../i18n')
|
||||||
|
const streamPipeline = util.promisify(require('stream').pipeline)
|
||||||
|
|
||||||
|
async function download(url, filePath) {
|
||||||
|
const response = await fetch(url)
|
||||||
|
if (!response.ok) throw new Error(`unexpected response ${response.statusText}`)
|
||||||
|
await streamPipeline(response.body, fs.createWriteStream(filePath))
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateInfo = {
|
||||||
|
status: 'init'
|
||||||
|
}
|
||||||
|
|
||||||
|
const isDev = !app.isPackaged
|
||||||
|
const appPath = isDev ? path.resolve(__dirname, '../../', 'update-dev/app'): app.getAppPath()
|
||||||
|
const updatePath = isDev ? path.resolve(__dirname, '../../', 'update-dev/download') : path.resolve(appPath, '..', '..', 'update')
|
||||||
|
|
||||||
|
const update = async () => {
|
||||||
|
if (isDev) return
|
||||||
|
try {
|
||||||
|
const url = 'https://earthjasonlin.github.io/zzz-signal-search-export/update'
|
||||||
|
const res = await fetch(`${url}/manifest.json?t=${Math.floor(Date.now() / (1000 * 60 * 10))}`)
|
||||||
|
const data = await res.json()
|
||||||
|
if (!data.active) return
|
||||||
|
if (semver.gt(data.version, version) && semver.gte(version, data.from)) {
|
||||||
|
await fs.emptyDir(updatePath)
|
||||||
|
const filePath = path.join(updatePath, data.name)
|
||||||
|
if (!config.autoUpdate) {
|
||||||
|
sendMsg(data.version, 'NEW_VERSION')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
updateInfo.status = 'downloading'
|
||||||
|
await download(`${url}/${data.name}`, filePath)
|
||||||
|
const buffer = await fs.readFile(filePath)
|
||||||
|
const sha256 = hash(buffer)
|
||||||
|
if (sha256 !== data.hash) return
|
||||||
|
const appPathTemp = path.join(updatePath, 'app')
|
||||||
|
await extract(filePath, { dir: appPathTemp })
|
||||||
|
updateInfo.status = 'moving'
|
||||||
|
await fs.emptyDir(appPath)
|
||||||
|
await fs.copy(appPathTemp, appPath)
|
||||||
|
updateInfo.status = 'finished'
|
||||||
|
sendMsg(i18n.log.autoUpdate.success, 'UPDATE_HINT')
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
updateInfo.status = 'failed'
|
||||||
|
sendMsg(e, 'ERROR')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getUpdateInfo = () => updateInfo
|
||||||
|
|
||||||
|
setTimeout(update, 1000)
|
||||||
|
|
||||||
|
exports.getUpdateInfo = getUpdateInfo
|
@ -327,6 +327,11 @@ onMounted(async () => {
|
|||||||
console.error(err)
|
console.error(err)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
ipcRenderer.on('UPDATE_HINT', (event, message) => {
|
||||||
|
state.log = message
|
||||||
|
state.status = 'updated'
|
||||||
|
})
|
||||||
|
|
||||||
ipcRenderer.on('AUTHKEY_TIMEOUT', (event, message) => {
|
ipcRenderer.on('AUTHKEY_TIMEOUT', (event, message) => {
|
||||||
state.authkeyTimeout = message
|
state.authkeyTimeout = message
|
||||||
})
|
})
|
||||||
|
@ -23,6 +23,12 @@
|
|||||||
<el-button type="primary" plain @click="state.showDataDialog = true">{{common.dataManage}}</el-button>
|
<el-button type="primary" plain @click="state.showDataDialog = true">{{common.dataManage}}</el-button>
|
||||||
<p class="text-gray-400 text-xs m-1.5">{{text.dataManagerHint}}</p>
|
<p class="text-gray-400 text-xs m-1.5">{{text.dataManagerHint}}</p>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item :label="text.autoUpdate">
|
||||||
|
<el-switch
|
||||||
|
@change="saveSetting"
|
||||||
|
v-model="settingForm.autoUpdate">
|
||||||
|
</el-switch>
|
||||||
|
</el-form-item>
|
||||||
<el-form-item :label="text.fetchFullHistory">
|
<el-form-item :label="text.fetchFullHistory">
|
||||||
<el-switch
|
<el-switch
|
||||||
@change="saveSetting"
|
@change="saveSetting"
|
||||||
@ -92,6 +98,7 @@ const settingForm = reactive({
|
|||||||
lang: 'zh-cn',
|
lang: 'zh-cn',
|
||||||
logType: 1,
|
logType: 1,
|
||||||
proxyMode: true,
|
proxyMode: true,
|
||||||
|
autoUpdate: true,
|
||||||
fetchFullHistory: false,
|
fetchFullHistory: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -105,7 +112,7 @@ const text = computed(() => props.i18n.ui.setting)
|
|||||||
const about = computed(() => props.i18n.ui.about)
|
const about = computed(() => props.i18n.ui.about)
|
||||||
|
|
||||||
const saveSetting = async () => {
|
const saveSetting = async () => {
|
||||||
const keys = ['lang', 'logType', 'proxyMode', 'fetchFullHistory']
|
const keys = ['lang', 'logType', 'proxyMode', 'autoUpdate', 'fetchFullHistory']
|
||||||
for (let key of keys) {
|
for (let key of keys) {
|
||||||
await ipcRenderer.invoke('SAVE_CONFIG', [key, settingForm[key]])
|
await ipcRenderer.invoke('SAVE_CONFIG', [key, settingForm[key]])
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user