Feature: add update progress bar and some optimization

ISSUES CLOSED: #83
This commit is contained in:
萌萌哒赫萝 2023-08-10 00:11:57 -07:00
parent 13852a5c1b
commit 517348886c
13 changed files with 1029 additions and 1056 deletions

View File

@ -32,9 +32,9 @@
"sha256": "node ./scripts/gen-sha256.js"
},
"dependencies": {
"@aws-sdk/client-s3": "^3.272.0",
"@aws-sdk/lib-storage": "^3.272.0",
"@aws-sdk/s3-request-presigner": "^3.272.0",
"@aws-sdk/client-s3": "^3.388.0",
"@aws-sdk/lib-storage": "^3.388.0",
"@aws-sdk/s3-request-presigner": "^3.388.0",
"@element-plus/icons-vue": "^2.1.0",
"@highlightjs/vue-plugin": "^2.1.0",
"@octokit/rest": "^19.0.7",
@ -48,7 +48,7 @@
"axios": "^1.4.0",
"compare-versions": "^4.1.3",
"core-js": "^3.27.1",
"cos-nodejs-sdk-v5": "^2.12.3",
"cos-nodejs-sdk-v5": "^2.12.4",
"dexie": "^3.2.4",
"electron-updater": "^6.1.1",
"element-plus": "^2.3.9",

View File

@ -94,14 +94,16 @@ import { NodeHttpHandler } from '@smithy/node-http-handler'
import http, { AgentOptions } from 'http'
import https from 'https'
// 通用获取 Agent 函数
// 工具函数
import { getAgent } from '../manage/utils/common'
import logger from '@core/picgo/logger'
const STORE_PATH = app.getPath('userData')
export default {
listen () {
picgoCoreIPC.listen()
// Upload Related IPC
// from macOS tray
ipcMain.on('uploadClipboardFiles', async () => {
const trayWindow = windowManager.get(IWindowList.TRAY_WINDOW)!
@ -137,6 +139,7 @@ export default {
return uploadChoosedFiles(evt.sender, files)
})
// ShortKey Related IPC
ipcMain.on('updateShortKey', (evt: IpcMainEvent, item: IShortKeyConfig, oldKey: string, from: string) => {
const result = shortKeyHandler.updateShortKey(item, oldKey, from)
evt.sender.send('updateShortKeyResponse', result)
@ -172,6 +175,7 @@ export default {
}
})
// Gallery image cloud delete IPC
ipcMain.handle('delete-sftp-file', async (_evt: IpcMainInvokeEvent, config: ISftpPlistConfig, fileName: string) => {
try {
const client = SSHClient.instance
@ -190,7 +194,6 @@ export default {
ipcMain.handle('delete-aws-s3-file', async (_evt: IpcMainInvokeEvent, configMap: IStringKeyMap) => {
try {
const { imgUrl, config: { accessKeyID, secretAccessKey, bucketName, region, endpoint, pathStyleAccess, rejectUnauthorized, proxy } } = configMap
console.log(JSON.stringify(configMap, null, 2))
const url = new URL(!/^https?:\/\//.test(imgUrl) ? `http://${imgUrl}` : imgUrl)
const fileKey = url.pathname.replace(/^\/+/, '')
const endpointUrl: string | undefined = endpoint
@ -242,11 +245,13 @@ export default {
const result = await client.send(command)
return result.$metadata.httpStatusCode === 204
} catch (err: any) {
console.error(err)
logger.error(err)
return false
}
})
// migrate from PicGo
ipcMain.handle('migrateFromPicGo', async () => {
const picGoConfigPath = STORE_PATH.replace('piclist', 'picgo')
const fileToMigration = [
@ -274,6 +279,8 @@ export default {
}
})
// PicList Setting page IPC
ipcMain.on('updateCustomLink', () => {
const notification = new Notification({
title: T('OPERATION_SUCCEED'),
@ -339,6 +346,8 @@ export default {
mainWindow.setAlwaysOnTop(!isAlwaysOnTop)
})
// Window operation API
ipcMain.on('openSettingWindow', () => {
windowManager.get(IWindowList.SETTING_WINDOW)!.show()
const autoCloseMiniWindow = db.get('settings.autoCloseMiniWindow') || false

View File

@ -62,9 +62,8 @@ const handleStartUpFiles = (argv: string[], cwd: string) => {
uploadChoosedFiles(win.webContents, files)
}
return true
} else {
return false
}
return false
}
autoUpdater.setFeedURL({
@ -90,9 +89,19 @@ autoUpdater.on('update-available', (info: UpdateInfo) => {
autoUpdater.downloadUpdate()
}
db.set('settings.showUpdateTip', !result.checkboxChecked)
}).catch((err) => {
logger.error(err)
})
})
autoUpdater.on('download-progress', (progressObj) => {
const percent = {
progress: progressObj.percent
}
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
window.webContents.send('updateProgress', percent)
})
autoUpdater.on('update-downloaded', () => {
dialog.showMessageBox({
type: 'info',
@ -100,9 +109,13 @@ autoUpdater.on('update-downloaded', () => {
buttons: ['Yes', 'No'],
message: T('TIPS_UPDATE_DOWNLOADED')
}).then((result) => {
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
window.webContents.send('updateProgress', { progress: 100 })
if (result.response === 0) {
autoUpdater.quitAndInstall()
}
}).catch((err) => {
logger.error(err)
})
})

View File

@ -47,6 +47,15 @@
</el-icon>
</div>
</div>
<el-progress
v-if="progressShow"
:percentage="progressPercentage"
:stroke-width="7"
:text-inside="true"
:show-text="false"
status="success"
class="progress-bar"
/>
<el-row
style="padding-top: 22px;"
class="main-content"
@ -311,9 +320,11 @@ const qrcodeVisible = ref(false)
const picBedConfigString = ref('')
const choosedPicBedForQRCode: Ref<string[]> = ref([])
const isAlwaysOnTop = ref(false)
const keepAlivePages = $router.getRoutes().filter(item => item.meta.keepAlive).map(item => item.name as string)
const progressShow = ref(true)
const progressPercentage = ref(0)
onBeforeMount(() => {
os.value = process.platform
sendToMain(GET_PICBEDS)
@ -325,6 +336,10 @@ onBeforeMount(() => {
ipcRenderer.on(SHOW_MAIN_PAGE_DONATION, () => {
visible.value = true
})
ipcRenderer.on('updateProgress', (_event: IpcRendererEvent, data: { progress: number}) => {
progressShow.value = data.progress !== 100 && data.progress !== 0
progressPercentage.value = data.progress
})
})
watch(() => choosedPicBedForQRCode, (val) => {
@ -420,6 +435,9 @@ onBeforeRouteUpdate(async (to) => {
onBeforeUnmount(() => {
ipcRenderer.removeListener(GET_PICBEDS, getPicBeds)
ipcRenderer.removeAllListeners(SHOW_MAIN_PAGE_QRCODE)
ipcRenderer.removeAllListeners(SHOW_MAIN_PAGE_DONATION)
ipcRenderer.removeAllListeners('updateProgress')
})
</script>

View File

@ -1641,6 +1641,8 @@ function stopRefreshDownloadTask () {
refreshDownloadTaskId.value && clearInterval(refreshDownloadTaskId.value)
}
//
function handleViewChange (val: 'list' | 'grid') {
saveConfig('settings.isShowList', val === 'list')
layoutStyle.value = val

View File

@ -294,90 +294,89 @@ import { formatEndpoint } from '~/main/manage/utils/common'
//
import { T as $T } from '@/i18n'
const manageStore = useManageStore()
const router = useRouter()
const isLoading = ref(false)
const activeName = ref('login')
const configResult:IStringKeyMap = reactive({})
const existingConfiguration = reactive({} as IStringKeyMap)
const dataForTable = reactive([] as any[])
const allConfigAliasMap = reactive({} as IStringKeyMap)
const router = useRouter()
const manageStore = useManageStore()
const isLoading = ref(false)
const currentAliasList = reactive([] as string[])
const rules = ruleMap(supportedPicBedList)
const sortedAllConfigAliasMap = computed(() => {
const sorted = Object.values(allConfigAliasMap).sort((a, b) => {
return Object.values(allConfigAliasMap).sort((a, b) => {
return a.picBedName.localeCompare(b.picBedName)
})
return sorted
})
const currentAliasList = reactive([] as string[])
const importedNewConfig: IStringKeyMap = {}
const ruleMap = (options: IStringKeyMap) => {
function ruleMap (options: IStringKeyMap) {
const rule:any = {}
Object.keys(options).forEach((key) => {
const item = options[key].options
item.forEach((option: string) => {
const keyName = key + '.' + option
if (options[key].configOptions[option].rule) {
rule[keyName] = options[key].configOptions[option].rule
for (const key in options) {
const { options: itemOptions, configOptions } = options[key]
for (const option of itemOptions) {
const keyName = `${key}.${option}`
const configOption = configOptions[option]
if (configOption.rule) {
rule[keyName] = configOption.rule
}
if (options[key].configOptions[option].default) {
configResult[keyName] = options[key].configOptions[option].default
if (configOption.default) {
configResult[keyName] = configOption.default
}
})
})
}
}
return rule
}
const rules = ruleMap(supportedPicBedList)
const getDataForTable = () => {
function getDataForTable () {
for (const key in existingConfiguration) {
const obj = {} as IStringKeyMap
for (const option in existingConfiguration[key]) {
obj[option] = existingConfiguration[key][option]
}
dataForTable.push(obj)
dataForTable.push({ ...existingConfiguration[key] as IStringKeyMap })
}
}
const getExistingConfig = async (name:string) => {
async function getExistingConfig (name:string) {
if (name === 'login') {
getAllConfigAliasArray()
return
}
currentAliasList.length = 0
const result = await getConfig<any>('picBed')
if (!result) {
existingConfiguration[name] = { fail: '暂无配置' }
}
for (const key in existingConfiguration) {
delete existingConfiguration[key]
}
for (const key in result) {
if (result[key].picBedName === name) {
existingConfiguration[key] = result[key]
currentAliasList.push(key)
if (!result || typeof result !== 'object' || Object.keys(result).length === 0) {
existingConfiguration[name] = { fail: '暂无配置' }
} else {
for (const key in result) {
if (result[key].picBedName === name) {
existingConfiguration[key] = result[key]
currentAliasList.push(key)
}
}
}
dataForTable.length = 0
getDataForTable()
handleConfigImport(currentAliasList[0])
}
const getAliasList = () => {
const aliasList = [] as string[]
for (const key in existingConfiguration) {
aliasList.push(existingConfiguration[key].alias)
}
return aliasList
function getAliasList () {
return Object.values(existingConfiguration).map(item => item.alias)
}
const handleConfigChange = async (name: string) => {
async function handleConfigChange (name: string) {
const aliasList = getAliasList()
const allKeys = Object.keys(supportedPicBedList[name].configOptions)
const resultMap:IStringKeyMap = {}
const reg = /^[\u4e00-\u9fa5_a-zA-Z0-9-]+$/
const reg = /^[\u4e00-\u9fff_a-zA-Z0-9-]+$/
for (const key of allKeys) {
const resultKey = name + '.' + key
if (supportedPicBedList[name].configOptions[key].required) {
@ -472,10 +471,14 @@ const handleConfigChange = async (name: string) => {
}
const handleConfigReset = (name: string) => {
let keys = Object.keys(configResult)
keys = keys.filter((key) => key.startsWith(name))
const keys = Object.keys(configResult).filter((key) => key.startsWith(name))
keys.forEach((key) => {
configResult[key] = supportedPicBedList[name].configOptions[key.split('.')[1]].default || ''
const optionKey = key.split('.')[1]
const configOption = supportedPicBedList[name]?.configOptions?.[optionKey]
if (configOption) {
configResult[key] = configOption.default || ''
}
})
}
@ -516,14 +519,12 @@ const getAllConfigAliasArray = async () => {
delete allConfigAliasMap[key]
}
if (!result) return
let i = 0
Object.keys(result).forEach((key) => {
allConfigAliasMap[i] = {
alias: result[key].alias,
picBedName: result[key].picBedName,
config: result[key]
Object.entries(result).forEach(([, value]: [string, any], index) => {
allConfigAliasMap[index] = {
alias: value.alias,
picBedName: value.picBedName,
config: value
}
i++
})
}
@ -552,30 +553,22 @@ const handleConfigClick = async (item: any) => {
function handleConfigImport (alias: string) {
const selectedConfig = existingConfiguration[alias]
if (selectedConfig) {
supportedPicBedList[selectedConfig.picBedName].options.forEach((option: any) => {
if (selectedConfig[option] !== undefined) {
configResult[selectedConfig.picBedName + '.' + option] = selectedConfig[option]
}
if (typeof selectedConfig[option] === 'boolean') {
configResult[selectedConfig.picBedName + '.' + option] = selectedConfig[option]
}
})
}
}
if (!selectedConfig) return
const importedNewConfig: IStringKeyMap = {}
supportedPicBedList[selectedConfig.picBedName].forEach((option: any) => {
if (selectedConfig[option] !== undefined) {
configResult[selectedConfig.picBedName + '.' + option] = selectedConfig[option]
}
})
}
async function getCurrentConfigList () {
const configList = await getPicBedsConfig<any>('uploader') ?? {}
const pbList = ['aliyun', 'tcyun', 'upyun', 'qiniu', 'smms', 'qiniu', 'github', 'webdavplist', 'aws-s3', 'imgur', 'local']
const pbList = ['aliyun', 'aws-s3', 'github', 'imgur', 'local', 'qiniu', 'smms', 'tcyun', 'upyun', 'webdavplist']
const filteredConfigList = pbList.flatMap((pb) => {
const config = configList[pb]
if (config && config.configList.length > 0) {
return config.configList.map((item: any) => ({ ...item, type: pb }))
} else {
return []
}
return config?.configList?.length ? config.configList.map((item: any) => ({ ...item, type: pb })) : []
})
await getAllConfigAliasArray()
const autoImport = await getPicBedsConfig<boolean>('settings.autoImport') || false

View File

@ -306,17 +306,22 @@ import { T as $T } from '@/i18n'
const manageStore = useManageStore() as any
const route = useRoute()
const router = useRouter()
const currentAlias = ref(route.query.alias as string)
const currentPicBedName = ref(route.query.picBedName as string)
let allPicBedConfigure = JSON.parse(route.query.allPicBedConfigure as string)
let currentPagePicBedConfig = reactive(JSON.parse(route.query.config as string))
const picBedSwitchDialogVisible = ref(false)
const newBucketConfigResult: IStringKeyMap = reactive({})
const bucketList = ref({} as IStringKeyMap)
const currentSelectedBucket = ref('')
const isLoadingBucketList = ref(false)
const bucketNameList = ref([] as string[])
const isLoadingBucketList = ref(false)
const nweBucketDrawerVisible = ref(false)
const picBedSwitchDialogVisible = ref(false)
watch(route, async (newRoute) => {
if (newRoute.fullPath.split('?')[0] === '/main-page/manage-main-page') {
currentAlias.value = newRoute.query.alias as string
@ -342,53 +347,66 @@ const urlMap : IStringKeyMap = {
local: 'https://piclist.cn'
}
const openPicBedUrl = () => shell.openExternal(urlMap[currentPagePicBedConfig.picBedName])
const showNewIconList = ['aliyun', 'qiniu', 'tcyun']
const ruleMap = (options: IStringKeyMap) => {
const rule: IStringKeyMap = {}
Object.keys(options).forEach((key) => {
const item = options[key].options
item.forEach((option: string) => {
const keyName = `${key}.${option}`
if (options[key].configOptions[option].rule) {
rule[keyName] = options[key].configOptions[option].rule
}
if (options[key].configOptions[option].default) {
newBucketConfigResult[keyName] = options[key].configOptions[option].default
}
})
})
return rule
const bucketT = $T('MANAGE_MAIN_PAGE_BUCKET')
const galleryT = $T('MANAGE_MAIN_PAGE_GALLERY')
const repositoryT = $T('MANAGE_MAIN_PAGE_REPOSITORY')
const menuTitleMap:IStringKeyMap = {
aliyun: bucketT,
qiniu: bucketT,
tcyun: bucketT,
upyun: bucketT,
s3plist: bucketT,
smms: galleryT,
imgur: galleryT,
github: repositoryT,
webdavplist: '',
local: ''
}
const rules = ruleMap(newBucketConfig)
const openNewBucketDrawer = () => {
const openPicBedUrl = () => shell.openExternal(urlMap[currentPagePicBedConfig.picBedName])
function ruleMap (options: IStringKeyMap) {
return Object.keys(options).reduce((result, key) => {
options[key].options.forEach((option: string) => {
const keyName = `${key}.${option}`
const configOption = options[key].configOptions[option]
if (configOption.rule) {
result[keyName] = configOption.rule
}
if (configOption.default) {
newBucketConfigResult[keyName] = configOption.default
}
})
return result
}, {} as IStringKeyMap)
}
function openNewBucketDrawer () {
nweBucketDrawerVisible.value = true
}
const createNewBucket = (picBedName: string) => {
const allKeys = Object.keys(newBucketConfig[picBedName].configOptions)
const resultMap: IStringKeyMap = {}
for (const key of allKeys) {
function createNewBucket (picBedName: string) {
const configOptions = newBucketConfig[picBedName].configOptions
const resultMap: IStringKeyMap = Object.keys(configOptions).reduce((result, key) => {
const resultKey = `${picBedName}.${key}`
if (newBucketConfig[picBedName].configOptions[key].default !== undefined && newBucketConfigResult[resultKey] === '') {
resultMap[key] = newBucketConfig[picBedName].configOptions[key].default
} else if (newBucketConfigResult[resultKey] === undefined) {
if (newBucketConfig[picBedName].configOptions[key].default !== undefined) {
resultMap[key] = newBucketConfig[picBedName].configOptions[key].default
} else {
resultMap[key] = ''
}
} else {
resultMap[key] = newBucketConfigResult[resultKey]
}
}
const defaultValue = configOptions[key].default
const resultValue = newBucketConfigResult[resultKey]
result[key] = resultValue === '' && defaultValue !== undefined
? defaultValue
: resultValue === undefined ? defaultValue ?? '' : resultValue
return result
}, {} as IStringKeyMap)
if (currentPicBedName.value === 'tcyun') {
resultMap.BucketName = resultMap.BucketName + '-' + currentPagePicBedConfig.appId
resultMap.BucketName = `${resultMap.BucketName}-${currentPagePicBedConfig.appId}`
}
const res = invokeToMain('createBucket', currentAlias, resultMap)
res.then((result: any) => {
invokeToMain('createBucket', currentAlias, resultMap).then((result: any) => {
if (result) {
ElNotification({
title: $T('MANAGE_MAIN_PAGE_TIPS'),
@ -409,12 +427,14 @@ const createNewBucket = (picBedName: string) => {
})
}
const getBucketList = async () => {
async function getBucketList () {
bucketList.value = {}
bucketNameList.value = []
isLoadingBucketList.value = true
const result = await invokeToMain('getBucketList', currentAlias.value)
isLoadingBucketList.value = false
if (result.length > 0) {
result.forEach((item: any) => {
bucketList.value[item.Name] = item
@ -423,33 +443,27 @@ const getBucketList = async () => {
}
}
const handleSelectMenu = (bucketName: string) => {
const transformedConfig = JSON.parse(manageStore.config.picBed[currentAlias.value].transformedConfig ?? '{}')
let prefix = transformedConfig[bucketName]?.baseDir
if (prefix === '' || prefix === undefined) {
prefix = '/'
} else {
!prefix.startsWith('/') && (prefix = `/${prefix}`)
!prefix.endsWith('/') && (prefix = `${prefix}/`)
}
const customUrl = transformedConfig[bucketName]?.customUrl ?? ''
const picBedName = manageStore.config.picBed[currentAlias.value].picBedName ?? currentPicBedName.value
const alias = currentAlias.value
const cdnUrl = manageStore.config.picBed[currentAlias.value].customUrl
const bucketConfig = bucketList.value[bucketName]
const webPath = manageStore.config.picBed[currentAlias.value].webPath || ''
function handleSelectMenu (bucketName: string) {
const currentPicBedConfig = manageStore.config.picBed[currentAlias.value]
const transformedConfig = JSON.parse(currentPicBedConfig.transformedConfig ?? '{}')
let prefix = transformedConfig[bucketName]?.baseDir || '/'
prefix = prefix.startsWith('/') ? prefix : `/${prefix}`
prefix = prefix.endsWith('/') ? prefix : `${prefix}/`
const configMap = {
prefix,
bucketName,
customUrl,
picBedName,
alias,
bucketConfig,
cdnUrl,
customUrl: transformedConfig[bucketName]?.customUrl ?? '',
picBedName: currentPicBedConfig.picBedName ?? currentPicBedName.value,
alias: currentAlias.value,
bucketConfig: bucketList.value[bucketName],
cdnUrl: currentPicBedConfig.customUrl,
baseDir: prefix,
webPath
webPath: currentPicBedConfig.webPath || ''
}
currentSelectedBucket.value = bucketName
router.push({
path: '/main-page/manage-main-page/manage-bucket-page',
query: {
@ -458,61 +472,38 @@ const handleSelectMenu = (bucketName: string) => {
})
}
const nweBucketDrawerVisible = ref(false)
const bucketT = $T('MANAGE_MAIN_PAGE_BUCKET')
const galleryT = $T('MANAGE_MAIN_PAGE_GALLERY')
const repositoryT = $T('MANAGE_MAIN_PAGE_REPOSITORY')
const menuTitleMap:IStringKeyMap = {
aliyun: bucketT,
qiniu: bucketT,
tcyun: bucketT,
upyun: bucketT,
s3plist: bucketT,
smms: galleryT,
imgur: galleryT,
github: repositoryT,
webdavplist: '',
local: ''
}
const showNewIconList = ['aliyun', 'qiniu', 'tcyun']
function switchPicBed (picBedAlias:string) {
if (picBedAlias === 'main') {
router.push({
path: '/main-page/manage-login-page'
})
} else {
if (route.fullPath.startsWith('/main-page/manage-main-page/manage-bucket-page') || route.fullPath.startsWith('/main-page/manage-main-page/manage-setting-page')
) {
picBedSwitchDialogVisible.value = false
router.push({
path: '/main-page/manage-main-page',
query: {
alias: picBedAlias,
picBedName: allPicBedConfigure[picBedAlias].picBedName,
config: JSON.stringify(allPicBedConfigure[picBedAlias]),
allPicBedConfigure: JSON.stringify(allPicBedConfigure)
}
})
} else {
currentAlias.value = picBedAlias
currentPicBedName.value = allPicBedConfigure[picBedAlias].picBedName
currentPagePicBedConfig = allPicBedConfigure[picBedAlias]
picBedSwitchDialogVisible.value = false
currentSelectedBucket.value = ''
getBucketList()
}
}
if (route.fullPath.startsWith('/main-page/manage-main-page/manage-bucket-page') || route.fullPath.startsWith('/main-page/manage-main-page/manage-setting-page')
) {
picBedSwitchDialogVisible.value = false
router.push({
path: '/main-page/manage-main-page',
query: {
alias: picBedAlias,
picBedName: allPicBedConfigure[picBedAlias].picBedName,
config: JSON.stringify(allPicBedConfigure[picBedAlias]),
allPicBedConfigure: JSON.stringify(allPicBedConfigure)
}
})
}
currentAlias.value = picBedAlias
currentPicBedName.value = allPicBedConfigure[picBedAlias].picBedName
currentPagePicBedConfig = allPicBedConfigure[picBedAlias]
picBedSwitchDialogVisible.value = false
currentSelectedBucket.value = ''
getBucketList()
}
const changePicBed = () => {
function changePicBed () {
picBedSwitchDialogVisible.value = true
}
const openBucketPageSetting = () => {
function openBucketPageSetting () {
router.push({
path: '/main-page/manage-main-page/manage-setting-page'
})

View File

@ -612,21 +612,21 @@ async function initData () {
form.timestampRename = config.settings.timestampRename ?? false
form.randomStringRename = config.settings.randomStringRename ?? false
form.customRename = config.settings.customRename ?? false
customRenameFormat.value = config.settings.customRenameFormat ?? '{filename}'
customPasteFormat.value = config.settings.customPasteFormat ?? '$url'
pasteFormat.value = config.settings.pasteFormat ?? 'markdown'
downloadDir.value = config.settings.downloadDir ?? ''
form.isAutoRefresh = config.settings.isAutoRefresh ?? false
form.isShowThumbnail = config.settings.isShowThumbnail ?? false
form.isShowList = config.settings.isShowList ?? false
form.isIgnoreCase = config.settings.isIgnoreCase ?? false
form.isForceCustomUrlHttps = config.settings.isForceCustomUrlHttps ?? true
form.isEncodeUrl = config.settings.isEncodeUrl ?? false
PreSignedExpire.value = config.settings.PreSignedExpire ?? 14400
maxDownloadFileCount.value = config.settings.maxDownloadFileCount ?? 5
form.isUploadKeepDirStructure = config.settings.isUploadKeepDirStructure ?? true
form.isDownloadFileKeepDirStructure = config.settings.isDownloadKeepDirStructure ?? false
form.isDownloadFolderKeepDirStructure = config.settings.isDownloadFolderKeepDirStructure ?? true
PreSignedExpire.value = config.settings.PreSignedExpire ?? 14400
maxDownloadFileCount.value = config.settings.maxDownloadFileCount ?? 5
customRenameFormat.value = config.settings.customRenameFormat ?? '{filename}'
customPasteFormat.value = config.settings.customPasteFormat ?? '$url'
pasteFormat.value = config.settings.pasteFormat ?? 'markdown'
downloadDir.value = config.settings.downloadDir ?? ''
}
async function handleDownloadDirClick () {

View File

@ -19,37 +19,38 @@ export interface IFileCache {
* new picbed will add a plist suffix to distinguish from picgo
*/
export class FileCacheDb extends Dexie {
tcyun: Table<IFileCache, string>
aliyun: Table<IFileCache, string>
qiniu: Table<IFileCache, string>
github: Table<IFileCache, string>
smms: Table<IFileCache, string>
upyun: Table<IFileCache, string>
imgur: Table<IFileCache, string>
s3plist: Table<IFileCache, string>
webdavplist: Table<IFileCache, string>
local: Table<IFileCache, string>
tcyun: Table<IFileCache, string>
qiniu: Table<IFileCache, string>
smms: Table<IFileCache, string>
s3plist: Table<IFileCache, string>
sftpplist: Table<IFileCache, string>
upyun: Table<IFileCache, string>
webdavplist: Table<IFileCache, string>
constructor () {
super('bucketFileDb')
const tableNames = ['tcyun', 'aliyun', 'qiniu', 'github', 'smms', 'upyun', 'imgur', 's3plist', 'webdavplist', 'local', 'sftpplist']
const tableNames = ['aliyun', 'github', 'imgur', 'local', 'qiniu', 's3plist', 'sftpplist', 'smms', 'tcyun', 'upyun', 'webdavplist']
const tableNamesMap = tableNames.reduce((acc, cur) => {
acc[cur] = '&key, value'
return acc
}, {} as IStringKeyMap)
this.version(4).stores(tableNamesMap)
this.tcyun = this.table('tcyun')
this.aliyun = this.table('aliyun')
this.qiniu = this.table('qiniu')
this.github = this.table('github')
this.imgur = this.table('imgur')
this.local = this.table('local')
this.qiniu = this.table('qiniu')
this.tcyun = this.table('tcyun')
this.s3plist = this.table('s3plist')
this.sftpplist = this.table('sftpplist')
this.smms = this.table('smms')
this.upyun = this.table('upyun')
this.imgur = this.table('imgur')
this.s3plist = this.table('s3plist')
this.webdavplist = this.table('webdavplist')
this.local = this.table('local')
this.sftpplist = this.table('sftpplist')
}
}

View File

@ -1479,6 +1479,7 @@ import pkg from 'root/package.json'
//
import { PICGO_OPEN_FILE, OPEN_URL, GET_PICBEDS, HIDE_DOCK } from '#/events/constants'
import { IRPCActionType } from '~/universal/types/enum'
// Electron
import {
@ -1492,13 +1493,12 @@ import { i18nManager, T as $T } from '@/i18n/index'
import { enforceNumber } from '~/universal/utils/common'
import { getLatestVersion } from '#/utils/getLatestVersion'
import { compare } from 'compare-versions'
import { STABLE_RELEASE_URL } from '#/utils/static'
// Vue
import { computed, onBeforeMount, onBeforeUnmount, reactive, ref, toRaw } from 'vue'
//
import { getConfig, saveConfig, sendToMain } from '@/utils/dataSender'
import { getConfig, saveConfig, sendRPC, sendToMain } from '@/utils/dataSender'
// Vue Router
import { useRouter } from 'vue-router'
@ -2049,7 +2049,7 @@ async function checkUpdate () {
function confirmCheckVersion () {
if (needUpdate.value) {
sendToMain(OPEN_URL, STABLE_RELEASE_URL)
sendRPC(IRPCActionType.RELOAD_APP)
}
checkUpdateVisible.value = false
}

View File

@ -4,15 +4,9 @@ import { isReactive, isRef, toRaw, unref } from 'vue'
* get raw data from reactive or ref
*/
export const getRawData = (args: any): any => {
if (isRef(args)) {
return unref(args)
}
if (isReactive(args)) {
return toRaw(args)
}
if (Array.isArray(args)) {
return args.map(getRawData)
}
if (isRef(args)) return unref(args)
if (isReactive(args)) return toRaw(args)
if (Array.isArray(args)) return args.map(getRawData)
if (typeof args === 'object' && args !== null) {
const data = {} as Record<string, any>
for (const key in args) {

View File

@ -117,7 +117,8 @@ const config = {
linux: {
icon: 'build/icons/',
asarUnpack: [
'**/node_modules/sharp/**'
'**/node_modules/sharp/**',
'**/node_modules/ssh2-no-cpu-features/**'
]
},
snap: {

1633
yarn.lock

File diff suppressed because it is too large Load Diff