🔨 Refactor: upgrade vue2 -> vue3

This commit is contained in:
PiEgg
2023-01-06 17:21:27 +08:00
parent 624e5738d1
commit 66d8d714db
46 changed files with 6584 additions and 7834 deletions

View File

@@ -2,72 +2,142 @@
<div id="plugin-view">
<div class="view-title">
{{ $T('PLUGIN_SETTINGS') }} -
<el-tooltip :content="pluginListToolTip" placement="right">
<i class="el-icon-goods" @click="goAwesomeList"></i>
<el-tooltip
:content="pluginListToolTip"
placement="right"
>
<el-icon
class="el-icon-goods"
@click="goAwesomeList"
>
<Goods />
</el-icon>
</el-tooltip>
<el-tooltip :content="importLocalPluginToolTip" placement="left">
<i class="el-icon-download" @click="handleImportLocalPlugin"/>
<el-tooltip
:content="importLocalPluginToolTip"
placement="left"
>
<el-icon
class="el-icon-download"
@click="handleImportLocalPlugin"
>
<Download />
</el-icon>
</el-tooltip>
</div>
<el-row class="handle-bar" :class="{ 'cut-width': pluginList.length > 6 }">
<el-row
class="handle-bar"
:class="{ 'cut-width': pluginList.length > 6 }"
>
<el-input
v-model="searchText"
:placeholder="$T('PLUGIN_SEARCH_PLACEHOLDER')"
size="small"
>
<i slot="suffix" class="el-input__icon el-icon-close" v-if="searchText" @click="cleanSearch" style="cursor: pointer"></i>
<template #suffix>
<el-icon
class="el-input__icon"
style="cursor: pointer;"
@click="cleanSearch"
>
<close />
</el-icon>
</template>
</el-input>
</el-row>
<el-row :gutter="10" class="plugin-list" v-loading="loading">
<el-col :span="12" v-for="item in pluginList" :key="item.fullName">
<div class="plugin-item" :class="{ 'darwin': os === 'darwin' }">
<div class="cli-only-badge" v-if="!item.gui" title="CLI only">CLI</div>
<img class="plugin-item__logo" :src="item.logo"
<el-row
v-loading="loading"
:gutter="10"
class="plugin-list"
>
<el-col
v-for="item in pluginList"
:key="item.fullName"
class="plugin-item__container"
:span="12"
>
<div
class="plugin-item"
:class="{ 'darwin': os === 'darwin' }"
>
<div
v-if="!item.gui"
class="cli-only-badge"
title="CLI only"
>
CLI
</div>
<img
class="plugin-item__logo"
:src="item.logo"
:onerror="defaultLogo"
>
<div
class="plugin-item__content"
:class="{ disabled: !item.enabled }"
>
<div class="plugin-item__name" @click="openHomepage(item.homepage)">
<div
class="plugin-item__name"
@click="openHomepage(item.homepage)"
>
{{ item.name }} <small>{{ ' ' + item.version }}</small>
</div>
<div class="plugin-item__desc" :title="item.description">
<div
class="plugin-item__desc"
:title="item.description"
>
{{ item.description }}
</div>
<div class="plugin-item__info-bar">
<span class="plugin-item__author">
{{ item.author }}
</span>
<span class="plugin-item__config" >
<span class="plugin-item__config">
<template v-if="searchText">
<template v-if="!item.hasInstall">
<span class="config-button install" v-if="!item.ing" @click="installPlugin(item)">
<span
v-if="!item.ing"
class="config-button install"
@click="installPlugin(item)"
>
{{ $T('PLUGIN_INSTALL') }}
</span>
<span v-else-if="item.ing" class="config-button ing">
<span
v-else-if="item.ing"
class="config-button ing"
>
{{ $T('PLUGIN_INSTALLING') }}
</span>
</template>
<span v-else class="config-button ing">
<span
v-else
class="config-button ing"
>
{{ $T('PLUGIN_INSTALLED') }}
</span>
</template>
<template v-else>
<span v-if="item.ing" class="config-button ing">
<span
v-if="item.ing"
class="config-button ing"
>
{{ $T('PLUGIN_DOING_SOMETHING') }}
</span>
<template v-else>
<i
<el-icon
v-if="item.enabled"
class="el-icon-setting"
@click="buildContextMenu(item)"
></i>
<i
>
<Setting />
</el-icon>
<el-icon
v-else
class="el-icon-remove-outline"
@click="buildContextMenu(item)"
></i>
>
<Remove />
</el-icon>
</template>
</template>
</span>
@@ -76,11 +146,23 @@
</div>
</el-col>
</el-row>
<el-row v-show="needReload" class="reload-mask" :class="{ 'cut-width': pluginList.length > 6 }">
<el-button type="primary" @click="reloadApp" size="mini" round>{{ $T('TIPS_NEED_RELOAD') }}</el-button>
<el-row
v-show="needReload"
class="reload-mask"
:class="{ 'cut-width': pluginList.length > 6 }"
justify="center"
>
<el-button
type="primary"
size="small"
round
@click="reloadApp"
>
{{ $T('TIPS_NEED_RELOAD') }}
</el-button>
</el-row>
<el-dialog
:visible.sync="dialogVisible"
v-model="dialogVisible"
:modal-append-to-body="false"
:title="$T('CONFIG_THING', {
c: configName
@@ -88,27 +170,35 @@
width="70%"
>
<config-form
:id="configName"
ref="$configForm"
:config="config"
:type="currentType"
:id="configName"
ref="configForm"
>
</config-form>
<span slot="footer">
<el-button @click="dialogVisible = false" round>{{ $T('CANCEL') }}</el-button>
<el-button type="primary" @click="handleConfirmConfig" round>{{ $T('CONFIRM') }}</el-button>
</span>
color-mode="white"
/>
<template #footer>
<el-button
round
@click="dialogVisible = false"
>
{{ $T('CANCEL') }}
</el-button>
<el-button
type="primary"
round
@click="handleConfirmConfig"
>
{{ $T('CONFIRM') }}
</el-button>
</template>
</el-dialog>
</div>
</template>
<script lang="ts">
import {
Component,
Vue,
Watch
} from 'vue-property-decorator'
<script lang="ts" setup>
import { Close, Download, Goods, Remove, Setting } from '@element-plus/icons-vue'
import { T as $T } from '@/i18n/index'
import ConfigForm from '@/components/ConfigForm.vue'
import { debounce } from 'lodash'
import { debounce, DebouncedFunc } from 'lodash'
import {
ipcRenderer,
IpcRendererEvent
@@ -121,326 +211,336 @@ import {
PICGO_HANDLE_PLUGIN_ING,
PICGO_TOGGLE_PLUGIN,
SHOW_PLUGIN_PAGE_MENU,
GET_PICBEDS
GET_PICBEDS,
PICGO_HANDLE_PLUGIN_DONE
} from '#/events/constants'
import { computed, ref, onBeforeMount, onBeforeUnmount, watch } from 'vue'
import { getConfig, saveConfig, sendToMain } from '@/utils/dataSender'
import { ElMessageBox } from 'element-plus'
import axios from 'axios'
const $confirm = ElMessageBox.confirm
const searchText = ref('')
const pluginList = ref<IPicGoPlugin[]>([])
const config = ref<any[]>([])
const currentType = ref<'plugin' | 'uploader' | 'transformer'>('plugin')
const configName = ref('')
const dialogVisible = ref(false)
const pluginNameList = ref<string[]>([])
const loading = ref(true)
const needReload = ref(false)
const pluginListToolTip = $T('PLUGIN_LIST')
const importLocalPluginToolTip = $T('PLUGIN_IMPORT_LOCAL')
// const id = ref('')
const os = ref('')
const defaultLogo = ref(`this.src="file://${__static.replace(/\\/g, '/')}/roundLogo.png"`)
const $configForm = ref<InstanceType<typeof ConfigForm> | null>(null)
const npmSearchText = computed(() => {
return searchText.value.match('picgo-plugin-')
? searchText.value
: searchText.value !== ''
? `picgo-plugin-${searchText.value}`
: searchText.value
})
let getSearchResult: DebouncedFunc<(val: string) => void>
@Component({
name: 'plugin',
components: {
ConfigForm
watch(npmSearchText, (val: string) => {
if (val) {
loading.value = true
pluginList.value = []
getSearchResult(val)
} else {
getPluginList()
}
})
export default class extends Vue {
searchText = ''
pluginList: IPicGoPlugin[] = []
menu: Electron.Menu | null = null
config: any[] = []
currentType = ''
configName = ''
dialogVisible = false
pluginNameList: string[] = []
loading = true
needReload = false
pluginListToolTip = this.$T('PLUGIN_LIST')
importLocalPluginToolTip = this.$T('PLUGIN_IMPORT_LOCAL')
id = ''
os = ''
defaultLogo: string = `this.src="file://${__static.replace(/\\/g, '/')}/roundLogo.png"`
get npmSearchText () {
return this.searchText.match('picgo-plugin-')
? this.searchText
: this.searchText !== ''
? `picgo-plugin-${this.searchText}`
: this.searchText
}
@Watch('npmSearchText')
onNpmSearchTextChange (val: string) {
if (val) {
this.loading = true
this.pluginList = []
this.getSearchResult(val)
} else {
this.getPluginList()
}
watch(dialogVisible, (val: boolean) => {
if (val) {
// @ts-ignore
document.querySelector('.main-content.el-row').style.zIndex = 101
} else {
// @ts-ignore
document.querySelector('.main-content.el-row').style.zIndex = 10
}
})
@Watch('dialogVisible')
onDialogVisible (val: boolean) {
if (val) {
// @ts-ignore
document.querySelector('.main-content.el-row').style.zIndex = 101
} else {
// @ts-ignore
document.querySelector('.main-content.el-row').style.zIndex = 10
}
}
async created () {
this.os = process.platform
ipcRenderer.on('hideLoading', () => {
this.loading = false
})
ipcRenderer.on('pluginList', (evt: IpcRendererEvent, list: IPicGoPlugin[]) => {
this.pluginList = list
this.pluginNameList = list.map(item => item.fullName)
this.loading = false
})
ipcRenderer.on('installPlugin', (evt: IpcRendererEvent, { success, body }: {
success: boolean,
body: string
}) => {
this.loading = false
this.pluginList.forEach(item => {
if (item.fullName === body) {
item.ing = false
item.hasInstall = success
}
})
})
ipcRenderer.on('updateSuccess', (evt: IpcRendererEvent, plugin: string) => {
this.loading = false
this.pluginList.forEach(item => {
if (item.fullName === plugin) {
item.ing = false
item.hasInstall = true
}
this.getPicBeds()
})
this.handleReload()
this.getPluginList()
})
ipcRenderer.on('uninstallSuccess', (evt: IpcRendererEvent, plugin: string) => {
this.loading = false
this.pluginList = this.pluginList.filter(item => {
if (item.fullName === plugin) { // restore Uploader & Transformer after uninstalling
if (item.config.transformer.name) {
this.handleRestoreState('transformer', item.config.transformer.name)
}
if (item.config.uploader.name) {
this.handleRestoreState('uploader', item.config.uploader.name)
}
this.getPicBeds()
}
return item.fullName !== plugin
})
this.pluginNameList = this.pluginNameList.filter(item => item !== plugin)
})
ipcRenderer.on(PICGO_CONFIG_PLUGIN, (evt: IpcRendererEvent, currentType: string, configName: string, config: any) => {
this.currentType = currentType
this.configName = configName
this.dialogVisible = true
this.config = config
})
ipcRenderer.on(PICGO_HANDLE_PLUGIN_ING, (evt: IpcRendererEvent, fullName: string) => {
this.pluginList.forEach(item => {
if (item.fullName === fullName || (item.name === fullName)) {
item.ing = true
}
})
this.loading = true
})
ipcRenderer.on(PICGO_TOGGLE_PLUGIN, (evt: IpcRendererEvent, fullName: string, enabled: boolean) => {
const plugin = this.pluginList.find(item => item.fullName === fullName)
if (plugin) {
plugin.enabled = enabled
this.getPicBeds()
this.needReload = true
onBeforeMount(async () => {
os.value = process.platform
ipcRenderer.on('hideLoading', () => {
loading.value = false
})
ipcRenderer.on(PICGO_HANDLE_PLUGIN_DONE, (evt: IpcRendererEvent, fullName: string) => {
pluginList.value.forEach(item => {
if (item.fullName === fullName || (item.name === fullName)) {
item.ing = false
}
})
this.getPluginList()
this.getSearchResult = debounce(this.getSearchResult, 50)
this.needReload = await this.getConfig<boolean>('needReload') || false
}
async buildContextMenu (plugin: IPicGoPlugin) {
ipcRenderer.send(SHOW_PLUGIN_PAGE_MENU, plugin)
}
getPluginList () {
ipcRenderer.send('getPluginList')
}
getPicBeds () {
ipcRenderer.send(GET_PICBEDS)
}
installPlugin (item: IPicGoPlugin) {
if (!item.gui) {
this.$confirm(this.$T('TIPS_PLUGIN_NOT_GUI_IMPLEMENT'), this.$T('TIPS_NOTICE'), {
confirmButtonText: this.$T('CONFIRM'),
cancelButtonText: this.$T('CANCEL'),
type: 'warning'
}).then(() => {
loading.value = false
})
ipcRenderer.on('pluginList', (evt: IpcRendererEvent, list: IPicGoPlugin[]) => {
pluginList.value = list
pluginNameList.value = list.map(item => item.fullName)
loading.value = false
})
ipcRenderer.on('installPlugin', (evt: IpcRendererEvent, { success, body }: {
success: boolean,
body: string
}) => {
loading.value = false
pluginList.value.forEach(item => {
if (item.fullName === body) {
item.ing = false
item.hasInstall = success
}
})
})
ipcRenderer.on('updateSuccess', (evt: IpcRendererEvent, plugin: string) => {
loading.value = false
pluginList.value.forEach(item => {
if (item.fullName === plugin) {
item.ing = false
item.hasInstall = true
}
getPicBeds()
})
handleReload()
getPluginList()
})
ipcRenderer.on('uninstallSuccess', (evt: IpcRendererEvent, plugin: string) => {
loading.value = false
pluginList.value = pluginList.value.filter(item => {
if (item.fullName === plugin) { // restore Uploader & Transformer after uninstalling
if (item.config.transformer.name) {
handleRestoreState('transformer', item.config.transformer.name)
}
if (item.config.uploader.name) {
handleRestoreState('uploader', item.config.uploader.name)
}
getPicBeds()
}
return item.fullName !== plugin
})
pluginNameList.value = pluginNameList.value.filter(item => item !== plugin)
})
ipcRenderer.on(PICGO_CONFIG_PLUGIN, (evt: IpcRendererEvent, _currentType: 'plugin' | 'transformer' | 'uploader', _configName: string, _config: any) => {
currentType.value = _currentType
configName.value = _configName
dialogVisible.value = true
config.value = _config
})
ipcRenderer.on(PICGO_HANDLE_PLUGIN_ING, (evt: IpcRendererEvent, fullName: string) => {
pluginList.value.forEach(item => {
if (item.fullName === fullName || (item.name === fullName)) {
item.ing = true
ipcRenderer.send('installPlugin', item.fullName)
}).catch(() => {
console.log('Install canceled')
})
} else {
}
})
loading.value = true
})
ipcRenderer.on(PICGO_TOGGLE_PLUGIN, (evt: IpcRendererEvent, fullName: string, enabled: boolean) => {
const plugin = pluginList.value.find(item => item.fullName === fullName)
if (plugin) {
plugin.enabled = enabled
getPicBeds()
needReload.value = true
}
})
getPluginList()
getSearchResult = debounce(_getSearchResult, 50)
needReload.value = await getConfig<boolean>('needReload') || false
})
async function buildContextMenu (plugin: IPicGoPlugin) {
sendToMain(SHOW_PLUGIN_PAGE_MENU, plugin)
}
function getPluginList () {
sendToMain('getPluginList')
}
function getPicBeds () {
sendToMain(GET_PICBEDS)
}
function installPlugin (item: IPicGoPlugin) {
if (!item.gui) {
$confirm($T('TIPS_PLUGIN_NOT_GUI_IMPLEMENT'), $T('TIPS_NOTICE'), {
confirmButtonText: $T('CONFIRM'),
cancelButtonText: $T('CANCEL'),
type: 'warning'
}).then(() => {
item.ing = true
ipcRenderer.send('installPlugin', item.fullName)
sendToMain('installPlugin', item.fullName)
}).catch(() => {
console.log('Install canceled')
})
} else {
item.ing = true
sendToMain('installPlugin', item.fullName)
}
}
// function uninstallPlugin (val: string) {
// pluginList.value.forEach(item => {
// if (item.name === val) {
// item.ing = true
// }
// })
// loading.value = true
// sendToMain('uninstallPlugin', val)
// }
// function updatePlugin (val: string) {
// pluginList.value.forEach(item => {
// if (item.fullName === val) {
// item.ing = true
// }
// })
// loading.value = true
// sendToMain('updatePlugin', val)
// }
function reloadApp () {
sendToMain(RELOAD_APP)
}
async function handleReload () {
saveConfig({
needReload: true
})
needReload.value = true
const successNotification = new Notification($T('PLUGIN_UPDATE_SUCCEED'), {
body: $T('TIPS_NEED_RELOAD')
})
successNotification.onclick = () => {
reloadApp()
}
}
function cleanSearch () {
searchText.value = ''
}
async function handleConfirmConfig () {
const result = (await $configForm.value?.validate() || false)
if (result !== false) {
switch (currentType.value) {
case 'plugin':
saveConfig({
[`${configName.value}`]: result
})
break
case 'uploader':
saveConfig({
[`picBed.${configName.value}`]: result
})
break
case 'transformer':
saveConfig({
[`transformer.${configName.value}`]: result
})
break
}
}
uninstallPlugin (val: string) {
this.pluginList.forEach(item => {
if (item.name === val) {
item.ing = true
}
})
this.loading = true
ipcRenderer.send('uninstallPlugin', val)
}
updatePlugin (val: string) {
this.pluginList.forEach(item => {
if (item.fullName === val) {
item.ing = true
}
})
this.loading = true
ipcRenderer.send('updatePlugin', val)
}
reloadApp () {
ipcRenderer.send(RELOAD_APP)
}
async handleReload () {
this.saveConfig({
needReload: true
})
this.needReload = true
const successNotification = new Notification(this.$T('PLUGIN_UPDATE_SUCCEED'), {
body: this.$T('TIPS_NEED_RELOAD')
const successNotification = new Notification($T('SETTINGS_RESULT'), {
body: $T('TIPS_SET_SUCCEED')
})
successNotification.onclick = () => {
this.reloadApp()
return true
}
dialogVisible.value = false
getPluginList()
}
}
cleanSearch () {
this.searchText = ''
}
async handleConfirmConfig () {
// @ts-ignore
const result = await this.$refs.configForm.validate()
if (result !== false) {
switch (this.currentType) {
case 'plugin':
this.saveConfig({
[`${this.configName}`]: result
})
break
case 'uploader':
this.saveConfig({
[`picBed.${this.configName}`]: result
})
break
case 'transformer':
this.saveConfig({
[`transformer.${this.configName}`]: result
})
break
}
const successNotification = new Notification(this.$T('SETTINGS_RESULT'), {
body: this.$T('TIPS_SET_SUCCEED')
})
successNotification.onclick = () => {
return true
}
this.dialogVisible = false
this.getPluginList()
}
}
getSearchResult (val: string) {
// this.$http.get(`https://api.npms.io/v2/search?q=${val}`)
this.$http.get(`https://registry.npmjs.com/-/v1/search?text=${val}`)
.then((res: INPMSearchResult) => {
this.pluginList = res.data.objects
.filter((item:INPMSearchResultObject) => {
return item.package.name.includes('picgo-plugin-')
})
.map((item: INPMSearchResultObject) => {
return this.handleSearchResult(item)
})
this.loading = false
})
.catch(err => {
console.log(err)
this.loading = false
})
}
handleSearchResult (item: INPMSearchResultObject) {
const name = handleStreamlinePluginName(item.package.name)
let gui = false
if (item.package.keywords && item.package.keywords.length > 0) {
if (item.package.keywords.includes('picgo-gui-plugin')) {
gui = true
}
}
return {
name: name,
fullName: item.package.name,
author: item.package.author.name,
description: item.package.description,
logo: `https://cdn.jsdelivr.net/npm/${item.package.name}/logo.png`,
config: {},
homepage: item.package.links ? item.package.links.homepage : '',
hasInstall: this.pluginNameList.some(plugin => plugin === item.package.name),
version: item.package.version,
gui,
ing: false // installing or uninstalling
}
}
// restore Uploader & Transformer
async handleRestoreState (item: string, name: string) {
if (item === 'uploader') {
const current = await this.getConfig('picBed.current')
if (current === name) {
this.saveConfig({
'picBed.current': 'smms',
'picBed.uploader': 'smms'
function _getSearchResult (val: string) {
// this.$http.get(`https://api.npms.io/v2/search?q=${val}`)
axios.get(`https://registry.npmjs.com/-/v1/search?text=${val}`)
.then((res: INPMSearchResult) => {
pluginList.value = res.data.objects
.filter((item:INPMSearchResultObject) => {
return item.package.name.includes('picgo-plugin-')
})
}
}
if (item === 'transformer') {
const current = await this.getConfig('picBed.transformer')
if (current === name) {
this.saveConfig({
'picBed.transformer': 'path'
.map((item: INPMSearchResultObject) => {
return handleSearchResult(item)
})
}
loading.value = false
})
.catch(err => {
console.log(err)
loading.value = false
})
}
function handleSearchResult (item: INPMSearchResultObject) {
const name = handleStreamlinePluginName(item.package.name)
let gui = false
if (item.package.keywords && item.package.keywords.length > 0) {
if (item.package.keywords.includes('picgo-gui-plugin')) {
gui = true
}
}
return {
name,
fullName: item.package.name,
author: item.package.author.name,
description: item.package.description,
logo: `https://cdn.jsdelivr.net/npm/${item.package.name}/logo.png`,
config: {},
homepage: item.package.links ? item.package.links.homepage : '',
hasInstall: pluginNameList.value.some(plugin => plugin === item.package.name),
version: item.package.version,
gui,
ing: false // installing or uninstalling
}
}
openHomepage (url: string) {
if (url) {
ipcRenderer.send(OPEN_URL, url)
// restore Uploader & Transformer
async function handleRestoreState (item: string, name: string) {
if (item === 'uploader') {
const current = await getConfig('picBed.current')
if (current === name) {
saveConfig({
'picBed.current': 'smms',
'picBed.uploader': 'smms'
})
}
}
goAwesomeList () {
ipcRenderer.send(OPEN_URL, 'https://github.com/PicGo/Awesome-PicGo')
if (item === 'transformer') {
const current = await getConfig('picBed.transformer')
if (current === name) {
saveConfig({
'picBed.transformer': 'path'
})
}
}
}
handleImportLocalPlugin () {
ipcRenderer.send('importLocalPlugin')
this.loading = true
function openHomepage (url: string) {
if (url) {
sendToMain(OPEN_URL, url)
}
}
beforeDestroy () {
ipcRenderer.removeAllListeners('pluginList')
ipcRenderer.removeAllListeners('installPlugin')
ipcRenderer.removeAllListeners('uninstallSuccess')
ipcRenderer.removeAllListeners('updateSuccess')
ipcRenderer.removeAllListeners('hideLoading')
}
function goAwesomeList () {
sendToMain(OPEN_URL, 'https://github.com/PicGo/Awesome-PicGo')
}
function handleImportLocalPlugin () {
sendToMain('importLocalPlugin')
loading.value = true
}
onBeforeUnmount(() => {
ipcRenderer.removeAllListeners('pluginList')
ipcRenderer.removeAllListeners('installPlugin')
ipcRenderer.removeAllListeners('uninstallSuccess')
ipcRenderer.removeAllListeners('updateSuccess')
ipcRenderer.removeAllListeners('hideLoading')
ipcRenderer.removeAllListeners(PICGO_HANDLE_PLUGIN_DONE)
})
</script>
<script lang="ts">
export default {
name: 'PluginPage'
}
</script>
<style lang='stylus'>
@@ -451,6 +551,7 @@ $darwinBg = #172426
.el-loading-mask
background-color rgba(0, 0, 0, 0.8)
.plugin-list
align-content flex-start
height: 339px;
box-sizing: border-box;
padding: 8px 15px;
@@ -471,6 +572,7 @@ $darwinBg = #172426
margin 10px auto
position relative
i.el-icon-goods
margin-left 4px
font-size 20px
vertical-align middle
cursor pointer
@@ -500,8 +602,10 @@ $darwinBg = #172426
padding 8px
user-select text
transition all .2s ease-in-out
margin-bottom 10px
position relative
&__container
height 80px
margin-bottom 10px
.cli-only-badge
position absolute
right 0px