mirror of
https://github.com/Kuingsmile/PicList.git
synced 2026-06-01 19:39:40 +08:00
🔨 Refactor: upgrade vue2 -> vue3
This commit is contained in:
@@ -1,65 +1,105 @@
|
||||
<template>
|
||||
<div id="gallery-view">
|
||||
<div class="view-title">
|
||||
{{ $T('GALLERY') }} - {{ filterList.length }} <i class="el-icon-caret-bottom" @click="toggleHandleBar" :class="{'active': handleBarActive}"></i>
|
||||
{{ $T('GALLERY') }} - {{ filterList.length }}
|
||||
<el-icon
|
||||
style="margin-left: 4px"
|
||||
class="cursor-pointer"
|
||||
@click="toggleHandleBar"
|
||||
>
|
||||
<CaretBottom v-show="!handleBarActive" />
|
||||
<CaretTop v-show="handleBarActive" />
|
||||
</el-icon>
|
||||
</div>
|
||||
<transition name="el-zoom-in-top">
|
||||
<el-row v-show="handleBarActive">
|
||||
<el-col :span="20" :offset="2">
|
||||
<el-row class="handle-bar" :gutter="16">
|
||||
<el-col
|
||||
:span="20"
|
||||
:offset="2"
|
||||
>
|
||||
<el-row
|
||||
class="handle-bar"
|
||||
:gutter="16"
|
||||
>
|
||||
<el-col :span="12">
|
||||
<el-select
|
||||
v-model="choosedPicBed"
|
||||
multiple
|
||||
collapse-tags
|
||||
size="mini"
|
||||
size="small"
|
||||
style="width: 100%"
|
||||
:placeholder="$T('CHOOSE_SHOWED_PICBED')">
|
||||
:placeholder="$T('CHOOSE_SHOWED_PICBED')"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in picBed"
|
||||
:key="item.type"
|
||||
:label="item.name"
|
||||
:value="item.type">
|
||||
</el-option>
|
||||
:value="item.type"
|
||||
/>
|
||||
</el-select>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-select
|
||||
v-model="pasteStyle"
|
||||
size="mini"
|
||||
size="small"
|
||||
style="width: 100%"
|
||||
:placeholder="$T('CHOOSE_PASTE_FORMAT')"
|
||||
@change="handlePasteStyleChange"
|
||||
:placeholder="$T('CHOOSE_PASTE_FORMAT')">
|
||||
>
|
||||
<el-option
|
||||
v-for="(value, key) in pasteStyleMap"
|
||||
:key="key"
|
||||
:label="key"
|
||||
:value="value">
|
||||
</el-option>
|
||||
:value="value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="handle-bar" :gutter="16">
|
||||
<el-row
|
||||
class="handle-bar"
|
||||
:gutter="16"
|
||||
>
|
||||
<el-col :span="12">
|
||||
<el-input
|
||||
v-model="searchText"
|
||||
:placeholder="$T('SEARCH')"
|
||||
size="mini"
|
||||
v-model="searchText">
|
||||
<i slot="suffix" class="el-input__icon el-icon-close" v-if="searchText" @click="cleanSearch" style="cursor: pointer"></i>
|
||||
size="small"
|
||||
>
|
||||
<template #suffix>
|
||||
<el-icon
|
||||
class="el-input__icon"
|
||||
style="cursor: pointer;"
|
||||
@click="cleanSearch"
|
||||
>
|
||||
<close />
|
||||
</el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<div class="item-base copy round" :class="{ active: isMultiple(choosedList)}" @click="multiCopy">
|
||||
<div
|
||||
class="item-base copy round"
|
||||
:class="{ active: isMultiple(choosedList)}"
|
||||
@click="multiCopy"
|
||||
>
|
||||
{{ $T('COPY') }}
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<div class="item-base delete round" :class="{ active: isMultiple(choosedList)}" @click="multiRemove">
|
||||
<div
|
||||
class="item-base delete round"
|
||||
:class="{ active: isMultiple(choosedList)}"
|
||||
@click="multiRemove"
|
||||
>
|
||||
{{ $T('DELETE') }}
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<div class="item-base all-pick round" :class="{ active: filterList.length > 0}" @click="toggleSelectAll">
|
||||
<div
|
||||
class="item-base all-pick round"
|
||||
:class="{ active: filterList.length > 0}"
|
||||
@click="toggleSelectAll"
|
||||
>
|
||||
{{ isAllSelected ? $T('CANCEL') : $T('SELECT_ALL') }}
|
||||
</div>
|
||||
</el-col>
|
||||
@@ -67,398 +107,470 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
</transition>
|
||||
<el-row class="gallery-list" :class="{ small: handleBarActive }">
|
||||
<el-col :span="20" :offset="2">
|
||||
<el-row
|
||||
class="gallery-list"
|
||||
:class="{ small: handleBarActive }"
|
||||
>
|
||||
<el-col
|
||||
:span="20"
|
||||
:offset="2"
|
||||
>
|
||||
<el-row :gutter="16">
|
||||
<gallerys
|
||||
:images="filterList"
|
||||
:index="idx"
|
||||
@close="handleClose"
|
||||
:options="options"
|
||||
></gallerys>
|
||||
<el-col :span="6" v-for="(item, index) in filterList" :key="item.id" class="gallery-list__img">
|
||||
<photo-slider
|
||||
:items="filterList"
|
||||
:visible="gallerySliderControl.visible"
|
||||
:index="gallerySliderControl.index"
|
||||
:should-transition="true"
|
||||
@change-index="zoomImage"
|
||||
@click-mask="handleClose"
|
||||
@close-modal="handleClose"
|
||||
/>
|
||||
<el-col
|
||||
v-for="(item, index) in filterList"
|
||||
:key="item.id"
|
||||
:span="6"
|
||||
class="gallery-list__img"
|
||||
>
|
||||
<div
|
||||
class="gallery-list__item"
|
||||
@click="zoomImage(index)"
|
||||
>
|
||||
<img v-lazy="item.imgUrl" class="gallery-list__item-img">
|
||||
<img
|
||||
v-lazy="item.imgUrl"
|
||||
class="gallery-list__item-img"
|
||||
>
|
||||
</div>
|
||||
<div class="gallery-list__file-name" :title="item.fileName">
|
||||
<div
|
||||
class="gallery-list__file-name"
|
||||
:title="item.fileName"
|
||||
>
|
||||
{{ item.fileName }}
|
||||
</div>
|
||||
<div class="gallery-list__tool-panel">
|
||||
<i class="el-icon-document" @click="copy(item)"></i>
|
||||
<i class="el-icon-edit-outline" @click="openDialog(item)"></i>
|
||||
<i class="el-icon-delete" @click="remove(item.id)"></i>
|
||||
<el-checkbox v-model="choosedList[item.id ? item.id : '']" class="pull-right" @change="(val) => handleChooseImage(val, index)"></el-checkbox>
|
||||
</div>
|
||||
<el-row
|
||||
class="gallery-list__tool-panel"
|
||||
justify="space-between"
|
||||
align="middle"
|
||||
>
|
||||
<el-row>
|
||||
<el-icon
|
||||
class="cursor-pointer document"
|
||||
@click="copy(item)"
|
||||
>
|
||||
<Document />
|
||||
</el-icon>
|
||||
<el-icon
|
||||
class="cursor-pointer edit"
|
||||
@click="openDialog(item)"
|
||||
>
|
||||
<Edit />
|
||||
</el-icon>
|
||||
<el-icon
|
||||
class="cursor-pointer delete"
|
||||
@click="remove(item.id)"
|
||||
>
|
||||
<Delete />
|
||||
</el-icon>
|
||||
</el-row>
|
||||
<el-checkbox
|
||||
v-model="choosedList[item.id ? item.id : '']"
|
||||
@change="(val) => handleChooseImage(val, index)"
|
||||
/>
|
||||
</el-row>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-dialog
|
||||
:visible.sync="dialogVisible"
|
||||
v-model="dialogVisible"
|
||||
:title="$T('CHANGE_IMAGE_URL')"
|
||||
width="500px"
|
||||
:modal-append-to-body="false"
|
||||
>
|
||||
<el-input v-model="imgInfo.imgUrl"></el-input>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="dialogVisible = false">{{ $T('CANCEL') }}</el-button>
|
||||
<el-button type="primary" @click="confirmModify">{{ $T('CONFIRM') }}</el-button>
|
||||
</span>
|
||||
<el-input v-model="imgInfo.imgUrl" />
|
||||
<template
|
||||
#footer
|
||||
>
|
||||
<el-button @click="dialogVisible = false">
|
||||
{{ $T('CANCEL') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="confirmModify"
|
||||
>
|
||||
{{ $T('CONFIRM') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
// @ts-ignore
|
||||
import gallerys from 'vue-gallery'
|
||||
import { Component, Vue, Watch } from 'vue-property-decorator'
|
||||
import { IResult } from '@picgo/store/dist/types'
|
||||
<script lang="ts" setup>
|
||||
import type { IResult } from '@picgo/store/dist/types'
|
||||
import { PASTE_TEXT, GET_PICBEDS } from '#/events/constants'
|
||||
import { CheckboxValueType, ElMessageBox } from 'element-plus'
|
||||
import { Close, CaretBottom, Document, Edit, Delete, CaretTop } from '@element-plus/icons-vue'
|
||||
import {
|
||||
ipcRenderer,
|
||||
clipboard,
|
||||
IpcRendererEvent
|
||||
} from 'electron'
|
||||
@Component({
|
||||
name: 'gallery',
|
||||
components: {
|
||||
gallerys
|
||||
import { computed, nextTick, onActivated, onBeforeUnmount, onBeforeMount, reactive, ref, watch } from 'vue'
|
||||
import { getConfig, saveConfig, sendToMain } from '@/utils/dataSender'
|
||||
import { onBeforeRouteUpdate } from 'vue-router'
|
||||
import { T as $T } from '@/i18n/index'
|
||||
import $$db from '@/utils/db'
|
||||
const images = ref<ImgInfo[]>([])
|
||||
const dialogVisible = ref(false)
|
||||
const imgInfo = reactive({
|
||||
id: '',
|
||||
imgUrl: ''
|
||||
})
|
||||
const $confirm = ElMessageBox.confirm
|
||||
const choosedList: IObjT<boolean> = reactive({})
|
||||
const gallerySliderControl = reactive({
|
||||
visible: false,
|
||||
index: 0
|
||||
})
|
||||
const choosedPicBed = ref<string[]>([])
|
||||
const lastChoosed = ref<number>(-1)
|
||||
const isShiftKeyPress = ref<boolean>(false)
|
||||
const searchText = ref<string>('')
|
||||
const handleBarActive = ref<boolean>(false)
|
||||
const pasteStyle = ref<string>('')
|
||||
const pasteStyleMap = {
|
||||
Markdown: 'markdown',
|
||||
HTML: 'HTML',
|
||||
URL: 'URL',
|
||||
UBB: 'UBB',
|
||||
Custom: 'Custom'
|
||||
}
|
||||
const picBed = ref<IPicBedType[]>([])
|
||||
onBeforeRouteUpdate((to, from) => {
|
||||
if (from.name === 'gallery') {
|
||||
clearChoosedList()
|
||||
}
|
||||
if (to.name === 'gallery') {
|
||||
updateGallery()
|
||||
}
|
||||
})
|
||||
export default class extends Vue {
|
||||
images: ImgInfo[] = []
|
||||
idx: null | number = null
|
||||
options = {
|
||||
titleProperty: 'fileName',
|
||||
urlProperty: 'imgUrl',
|
||||
closeOnSlideClick: true
|
||||
}
|
||||
|
||||
dialogVisible = false
|
||||
imgInfo = {
|
||||
id: '',
|
||||
imgUrl: ''
|
||||
}
|
||||
|
||||
choosedList: IObjT<boolean> = {}
|
||||
choosedPicBed: string[] = []
|
||||
lastChoosed: number = -1
|
||||
isShiftKeyPress: boolean = false
|
||||
searchText = ''
|
||||
handleBarActive = false
|
||||
pasteStyle = ''
|
||||
pasteStyleMap = {
|
||||
Markdown: 'markdown',
|
||||
HTML: 'HTML',
|
||||
URL: 'URL',
|
||||
UBB: 'UBB',
|
||||
Custom: 'Custom'
|
||||
}
|
||||
|
||||
picBed: IPicBedType[] = []
|
||||
@Watch('$route')
|
||||
handleRouteUpdate (to: any, from: any) {
|
||||
if (from.name === 'gallery') {
|
||||
this.clearChoosedList()
|
||||
}
|
||||
if (to.name === 'gallery') {
|
||||
this.updateGallery()
|
||||
}
|
||||
}
|
||||
|
||||
async created () {
|
||||
ipcRenderer.on('updateGallery', () => {
|
||||
this.$nextTick(async () => {
|
||||
this.updateGallery()
|
||||
})
|
||||
onBeforeMount(async () => {
|
||||
ipcRenderer.on('updateGallery', () => {
|
||||
nextTick(async () => {
|
||||
updateGallery()
|
||||
})
|
||||
ipcRenderer.send(GET_PICBEDS)
|
||||
ipcRenderer.on(GET_PICBEDS, this.getPicBeds)
|
||||
this.updateGallery()
|
||||
}
|
||||
})
|
||||
sendToMain(GET_PICBEDS)
|
||||
ipcRenderer.on(GET_PICBEDS, getPicBeds)
|
||||
updateGallery()
|
||||
|
||||
mounted () {
|
||||
document.addEventListener('keydown', this.handleDetectShiftKey)
|
||||
document.addEventListener('keyup', this.handleDetectShiftKey)
|
||||
}
|
||||
document.addEventListener('keydown', handleDetectShiftKey)
|
||||
document.addEventListener('keyup', handleDetectShiftKey)
|
||||
})
|
||||
|
||||
handleDetectShiftKey (event: KeyboardEvent) {
|
||||
if (event.key === 'Shift') {
|
||||
if (event.type === 'keydown') {
|
||||
this.isShiftKeyPress = true
|
||||
} else if (event.type === 'keyup') {
|
||||
this.isShiftKeyPress = false
|
||||
function handleDetectShiftKey (event: KeyboardEvent) {
|
||||
if (event.key === 'Shift') {
|
||||
if (event.type === 'keydown') {
|
||||
isShiftKeyPress.value = true
|
||||
} else if (event.type === 'keyup') {
|
||||
isShiftKeyPress.value = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const filterList = computed(() => {
|
||||
return getGallery()
|
||||
})
|
||||
|
||||
const isAllSelected = computed(() => {
|
||||
const values = Object.values(choosedList)
|
||||
if (values.length === 0) {
|
||||
return false
|
||||
} else {
|
||||
return filterList.value.every(item => {
|
||||
return choosedList[item.id!]
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
function getPicBeds (event: IpcRendererEvent, picBeds: IPicBedType[]) {
|
||||
picBed.value = picBeds
|
||||
}
|
||||
|
||||
function getGallery (): IGalleryItem[] {
|
||||
if (searchText.value || choosedPicBed.value.length > 0) {
|
||||
return images.value
|
||||
.filter(item => {
|
||||
let isInChoosedPicBed = true
|
||||
let isIncludesSearchText = true
|
||||
if (choosedPicBed.value.length > 0) {
|
||||
isInChoosedPicBed = choosedPicBed.value.some(type => type === item.type)
|
||||
}
|
||||
if (searchText.value) {
|
||||
isIncludesSearchText = item.fileName?.includes(searchText.value) || false
|
||||
}
|
||||
return isIncludesSearchText && isInChoosedPicBed
|
||||
}).map(item => {
|
||||
return {
|
||||
...item,
|
||||
src: item.imgUrl || '',
|
||||
key: (item.id || `${Date.now()}`),
|
||||
intro: item.fileName || ''
|
||||
}
|
||||
})
|
||||
} else {
|
||||
return images.value.map(item => {
|
||||
return {
|
||||
...item,
|
||||
src: item.imgUrl || '',
|
||||
key: (item.id || `${Date.now()}`),
|
||||
intro: item.fileName || ''
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
async function updateGallery () {
|
||||
images.value = (await $$db.get({ orderBy: 'desc' })).data
|
||||
}
|
||||
|
||||
watch(() => filterList, () => {
|
||||
clearChoosedList()
|
||||
})
|
||||
|
||||
function handleChooseImage (val: CheckboxValueType, index: number) {
|
||||
if (val === true) {
|
||||
handleBarActive.value = true
|
||||
if (lastChoosed.value !== -1 && isShiftKeyPress.value) {
|
||||
const min = Math.min(lastChoosed.value, index)
|
||||
const max = Math.max(lastChoosed.value, index)
|
||||
for (let i = min + 1; i < max; i++) {
|
||||
const id = filterList.value[i].id!
|
||||
choosedList[id] = true
|
||||
}
|
||||
}
|
||||
lastChoosed.value = index
|
||||
}
|
||||
}
|
||||
|
||||
get filterList () {
|
||||
return this.getGallery()
|
||||
function clearChoosedList () {
|
||||
isShiftKeyPress.value = false
|
||||
Object.keys(choosedList).forEach(key => {
|
||||
choosedList[key] = false
|
||||
})
|
||||
lastChoosed.value = -1
|
||||
}
|
||||
|
||||
function zoomImage (index: number) {
|
||||
gallerySliderControl.index = index
|
||||
gallerySliderControl.visible = true
|
||||
changeZIndexForGallery(true)
|
||||
}
|
||||
|
||||
function changeZIndexForGallery (isOpen: boolean) {
|
||||
if (isOpen) {
|
||||
// @ts-ignore
|
||||
document.querySelector('.main-content.el-row').style.zIndex = 101
|
||||
} else {
|
||||
// @ts-ignore
|
||||
document.querySelector('.main-content.el-row').style.zIndex = 10
|
||||
}
|
||||
}
|
||||
|
||||
get isAllSelected () {
|
||||
const values = Object.values(this.choosedList)
|
||||
if (values.length === 0) {
|
||||
return false
|
||||
} else {
|
||||
return this.filterList.every(item => {
|
||||
return this.choosedList[item.id!]
|
||||
})
|
||||
}
|
||||
function handleClose () {
|
||||
gallerySliderControl.index = 0
|
||||
gallerySliderControl.visible = false
|
||||
changeZIndexForGallery(false)
|
||||
}
|
||||
|
||||
async function copy (item: ImgInfo) {
|
||||
const copyLink = await ipcRenderer.invoke(PASTE_TEXT, item)
|
||||
const obj = {
|
||||
title: $T('COPY_LINK_SUCCEED'),
|
||||
body: copyLink
|
||||
// sometimes will cause lagging
|
||||
// icon: item.url || item.imgUrl
|
||||
}
|
||||
|
||||
getPicBeds (event: IpcRendererEvent, picBeds: IPicBedType[]) {
|
||||
this.picBed = picBeds
|
||||
const myNotification = new Notification(obj.title, obj)
|
||||
myNotification.onclick = () => {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
getGallery (): ImgInfo[] {
|
||||
if (this.searchText || this.choosedPicBed.length > 0) {
|
||||
return this.images
|
||||
.filter(item => {
|
||||
let isInChoosedPicBed = true
|
||||
let isIncludesSearchText = true
|
||||
if (this.choosedPicBed.length > 0) {
|
||||
isInChoosedPicBed = this.choosedPicBed.some(type => type === item.type)
|
||||
}
|
||||
if (this.searchText) {
|
||||
isIncludesSearchText = item.fileName?.includes(this.searchText) || false
|
||||
}
|
||||
return isIncludesSearchText && isInChoosedPicBed
|
||||
})
|
||||
} else {
|
||||
return this.images
|
||||
}
|
||||
}
|
||||
|
||||
async updateGallery () {
|
||||
this.images = (await this.$$db.get({ orderBy: 'desc' })).data
|
||||
}
|
||||
|
||||
@Watch('filterList')
|
||||
handleFilterListChange () {
|
||||
this.clearChoosedList()
|
||||
}
|
||||
|
||||
handleChooseImage (val: boolean, index: number) {
|
||||
if (val === true) {
|
||||
this.handleBarActive = true
|
||||
if (this.lastChoosed !== -1 && this.isShiftKeyPress) {
|
||||
const min = Math.min(this.lastChoosed, index)
|
||||
const max = Math.max(this.lastChoosed, index)
|
||||
for (let i = min + 1; i < max; i++) {
|
||||
const id = this.filterList[i].id!
|
||||
this.$set(this.choosedList, id, true)
|
||||
}
|
||||
}
|
||||
this.lastChoosed = index
|
||||
}
|
||||
}
|
||||
|
||||
clearChoosedList () {
|
||||
this.isShiftKeyPress = false
|
||||
Object.keys(this.choosedList).forEach(key => {
|
||||
this.choosedList[key] = false
|
||||
})
|
||||
this.lastChoosed = -1
|
||||
}
|
||||
|
||||
zoomImage (index: number) {
|
||||
this.idx = index
|
||||
this.changeZIndexForGallery(true)
|
||||
}
|
||||
|
||||
changeZIndexForGallery (isOpen: boolean) {
|
||||
if (isOpen) {
|
||||
// @ts-ignore
|
||||
document.querySelector('.main-content.el-row').style.zIndex = 101
|
||||
} else {
|
||||
// @ts-ignore
|
||||
document.querySelector('.main-content.el-row').style.zIndex = 10
|
||||
}
|
||||
}
|
||||
|
||||
handleClose () {
|
||||
this.idx = null
|
||||
this.changeZIndexForGallery(false)
|
||||
}
|
||||
|
||||
async copy (item: ImgInfo) {
|
||||
const copyLink = await ipcRenderer.invoke(PASTE_TEXT, item)
|
||||
const obj = {
|
||||
title: this.$T('COPY_LINK_SUCCEED'),
|
||||
body: copyLink
|
||||
// sometimes will cause lagging
|
||||
// icon: item.url || item.imgUrl
|
||||
}
|
||||
const myNotification = new Notification(obj.title, obj)
|
||||
myNotification.onclick = () => {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
remove (id?: string) {
|
||||
if (id) {
|
||||
this.$confirm(this.$T('TIPS_REMOVE_LINK'), this.$T('TIPS_NOTICE'), {
|
||||
confirmButtonText: this.$T('CONFIRM'),
|
||||
cancelButtonText: this.$T('CANCEL'),
|
||||
type: 'warning'
|
||||
}).then(async () => {
|
||||
const file = await this.$$db.getById(id)
|
||||
await this.$$db.removeById(id)
|
||||
ipcRenderer.send('removeFiles', [file])
|
||||
const obj = {
|
||||
title: this.$T('OPERATION_SUCCEED'),
|
||||
body: ''
|
||||
}
|
||||
const myNotification = new Notification(obj.title, obj)
|
||||
myNotification.onclick = () => {
|
||||
return true
|
||||
}
|
||||
this.updateGallery()
|
||||
}).catch((e) => {
|
||||
console.log(e)
|
||||
return true
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
openDialog (item: ImgInfo) {
|
||||
this.imgInfo.id = item.id!
|
||||
this.imgInfo.imgUrl = item.imgUrl as string
|
||||
this.dialogVisible = true
|
||||
}
|
||||
|
||||
async confirmModify () {
|
||||
await this.$$db.updateById(this.imgInfo.id, {
|
||||
imgUrl: this.imgInfo.imgUrl
|
||||
})
|
||||
const obj = {
|
||||
title: this.$T('CHANGE_IMAGE_URL_SUCCEED'),
|
||||
body: this.imgInfo.imgUrl
|
||||
// icon: this.imgInfo.imgUrl
|
||||
}
|
||||
const myNotification = new Notification(obj.title, obj)
|
||||
myNotification.onclick = () => {
|
||||
return true
|
||||
}
|
||||
this.dialogVisible = false
|
||||
this.updateGallery()
|
||||
}
|
||||
|
||||
choosePicBed (type: string) {
|
||||
const idx = this.choosedPicBed.indexOf(type)
|
||||
if (idx !== -1) {
|
||||
this.choosedPicBed.splice(idx, 1)
|
||||
} else {
|
||||
this.choosedPicBed.push(type)
|
||||
}
|
||||
}
|
||||
|
||||
cleanSearch () {
|
||||
this.searchText = ''
|
||||
}
|
||||
|
||||
isMultiple (obj: IObj) {
|
||||
return Object.values(obj).some(item => item)
|
||||
}
|
||||
|
||||
toggleSelectAll () {
|
||||
const result = !this.isAllSelected
|
||||
this.filterList.forEach(item => {
|
||||
this.$set(this.choosedList, item.id!, result)
|
||||
})
|
||||
}
|
||||
|
||||
multiRemove () {
|
||||
// choosedList -> { [id]: true or false }; true means choosed. false means not choosed.
|
||||
const multiRemoveNumber = Object.values(this.choosedList).filter(item => item).length
|
||||
if (multiRemoveNumber) {
|
||||
this.$confirm(this.$T('TIPS_WILL_REMOVE_CHOOSED_IMAGES', {
|
||||
m: multiRemoveNumber
|
||||
}), this.$T('TIPS_NOTICE'), {
|
||||
confirmButtonText: this.$T('CONFIRM'),
|
||||
cancelButtonText: this.$T('CANCEL'),
|
||||
type: 'warning'
|
||||
}).then(async () => {
|
||||
const files: IResult<ImgInfo>[] = []
|
||||
const imageIDList = Object.keys(this.choosedList)
|
||||
for (let i = 0; i < imageIDList.length; i++) {
|
||||
const key = imageIDList[i]
|
||||
if (this.choosedList[key]) {
|
||||
const file = await this.$$db.getById<ImgInfo>(key)
|
||||
if (file) {
|
||||
files.push(file)
|
||||
await this.$$db.removeById(key)
|
||||
}
|
||||
}
|
||||
}
|
||||
this.clearChoosedList()
|
||||
this.choosedList = {} // 只有删除才能将这个置空
|
||||
const obj = {
|
||||
title: this.$T('OPERATION_SUCCEED'),
|
||||
body: ''
|
||||
}
|
||||
ipcRenderer.send('removeFiles', files)
|
||||
const myNotification = new Notification(obj.title, obj)
|
||||
myNotification.onclick = () => {
|
||||
return true
|
||||
}
|
||||
this.updateGallery()
|
||||
}).catch(() => {
|
||||
return true
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
async multiCopy () {
|
||||
if (Object.values(this.choosedList).some(item => item)) {
|
||||
const copyString: string[] = []
|
||||
// choosedList -> { [id]: true or false }; true means choosed. false means not choosed.
|
||||
const imageIDList = Object.keys(this.choosedList)
|
||||
for (let i = 0; i < imageIDList.length; i++) {
|
||||
const key = imageIDList[i]
|
||||
if (this.choosedList[key]) {
|
||||
const item = await this.$$db.getById<ImgInfo>(key)
|
||||
if (item) {
|
||||
const txt = await ipcRenderer.invoke(PASTE_TEXT, item)
|
||||
copyString.push(txt)
|
||||
this.choosedList[key] = false
|
||||
}
|
||||
}
|
||||
}
|
||||
function remove (id?: string) {
|
||||
if (id) {
|
||||
$confirm($T('TIPS_REMOVE_LINK'), $T('TIPS_NOTICE'), {
|
||||
confirmButtonText: $T('CONFIRM'),
|
||||
cancelButtonText: $T('CANCEL'),
|
||||
type: 'warning'
|
||||
}).then(async () => {
|
||||
const file = await $$db.getById(id)
|
||||
await $$db.removeById(id)
|
||||
sendToMain('removeFiles', [file])
|
||||
const obj = {
|
||||
title: this.$T('BATCH_COPY_LINK_SUCCEED'),
|
||||
body: copyString.join('\n')
|
||||
title: $T('OPERATION_SUCCEED'),
|
||||
body: ''
|
||||
}
|
||||
const myNotification = new Notification(obj.title, obj)
|
||||
clipboard.writeText(copyString.join('\n'))
|
||||
myNotification.onclick = () => {
|
||||
return true
|
||||
}
|
||||
updateGallery()
|
||||
}).catch((e) => {
|
||||
console.log(e)
|
||||
return true
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function openDialog (item: ImgInfo) {
|
||||
imgInfo.id = item.id!
|
||||
imgInfo.imgUrl = item.imgUrl as string
|
||||
dialogVisible.value = true
|
||||
}
|
||||
|
||||
async function confirmModify () {
|
||||
await $$db.updateById(imgInfo.id, {
|
||||
imgUrl: imgInfo.imgUrl
|
||||
})
|
||||
const obj = {
|
||||
title: $T('CHANGE_IMAGE_URL_SUCCEED'),
|
||||
body: imgInfo.imgUrl
|
||||
// icon: this.imgInfo.imgUrl
|
||||
}
|
||||
const myNotification = new Notification(obj.title, obj)
|
||||
myNotification.onclick = () => {
|
||||
return true
|
||||
}
|
||||
dialogVisible.value = false
|
||||
updateGallery()
|
||||
}
|
||||
|
||||
// function choosePicBed (type: string) {
|
||||
// const idx = choosedPicBed.value.indexOf(type)
|
||||
// if (idx !== -1) {
|
||||
// choosedPicBed.value.splice(idx, 1)
|
||||
// } else {
|
||||
// choosedPicBed.value.push(type)
|
||||
// }
|
||||
// }
|
||||
|
||||
function cleanSearch () {
|
||||
searchText.value = ''
|
||||
}
|
||||
|
||||
function isMultiple (obj: IObj) {
|
||||
return Object.values(obj).some(item => item)
|
||||
}
|
||||
|
||||
function toggleSelectAll () {
|
||||
const result = !isAllSelected.value
|
||||
filterList.value.forEach(item => {
|
||||
choosedList[item.id!] = result
|
||||
})
|
||||
}
|
||||
|
||||
function multiRemove () {
|
||||
// choosedList -> { [id]: true or false }; true means choosed. false means not choosed.
|
||||
const multiRemoveNumber = Object.values(choosedList).filter(item => item).length
|
||||
if (multiRemoveNumber) {
|
||||
$confirm($T('TIPS_WILL_REMOVE_CHOOSED_IMAGES', {
|
||||
m: multiRemoveNumber
|
||||
}), $T('TIPS_NOTICE'), {
|
||||
confirmButtonText: $T('CONFIRM'),
|
||||
cancelButtonText: $T('CANCEL'),
|
||||
type: 'warning'
|
||||
}).then(async () => {
|
||||
const files: IResult<ImgInfo>[] = []
|
||||
const imageIDList = Object.keys(choosedList)
|
||||
for (let i = 0; i < imageIDList.length; i++) {
|
||||
const key = imageIDList[i]
|
||||
if (choosedList[key]) {
|
||||
const file = await $$db.getById<ImgInfo>(key)
|
||||
if (file) {
|
||||
files.push(file)
|
||||
await $$db.removeById(key)
|
||||
}
|
||||
}
|
||||
}
|
||||
clearChoosedList()
|
||||
// TODO: check this
|
||||
// choosedList = {} // 只有删除才能将这个置空
|
||||
const obj = {
|
||||
title: $T('OPERATION_SUCCEED'),
|
||||
body: ''
|
||||
}
|
||||
sendToMain('removeFiles', files)
|
||||
const myNotification = new Notification(obj.title, obj)
|
||||
myNotification.onclick = () => {
|
||||
return true
|
||||
}
|
||||
updateGallery()
|
||||
}).catch(() => {
|
||||
return true
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
async function multiCopy () {
|
||||
if (Object.values(choosedList).some(item => item)) {
|
||||
const copyString: string[] = []
|
||||
// choosedList -> { [id]: true or false }; true means choosed. false means not choosed.
|
||||
const imageIDList = Object.keys(choosedList)
|
||||
for (let i = 0; i < imageIDList.length; i++) {
|
||||
const key = imageIDList[i]
|
||||
if (choosedList[key]) {
|
||||
const item = await $$db.getById<ImgInfo>(key)
|
||||
if (item) {
|
||||
const txt = await ipcRenderer.invoke(PASTE_TEXT, item)
|
||||
copyString.push(txt)
|
||||
choosedList[key] = false
|
||||
}
|
||||
}
|
||||
}
|
||||
const obj = {
|
||||
title: $T('BATCH_COPY_LINK_SUCCEED'),
|
||||
body: copyString.join('\n')
|
||||
}
|
||||
const myNotification = new Notification(obj.title, obj)
|
||||
clipboard.writeText(copyString.join('\n'))
|
||||
myNotification.onclick = () => {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
toggleHandleBar () {
|
||||
this.handleBarActive = !this.handleBarActive
|
||||
}
|
||||
function toggleHandleBar () {
|
||||
handleBarActive.value = !handleBarActive.value
|
||||
}
|
||||
|
||||
// getPasteStyle () {
|
||||
// this.pasteStyle = this.$db.get('settings.pasteStyle') || 'markdown'
|
||||
// }
|
||||
async handlePasteStyleChange (val: string) {
|
||||
this.saveConfig('settings.pasteStyle', val)
|
||||
this.pasteStyle = val
|
||||
}
|
||||
async function handlePasteStyleChange (val: string) {
|
||||
saveConfig('settings.pasteStyle', val)
|
||||
pasteStyle.value = val
|
||||
}
|
||||
|
||||
beforeDestroy () {
|
||||
ipcRenderer.removeAllListeners('updateGallery')
|
||||
ipcRenderer.removeListener(GET_PICBEDS, this.getPicBeds)
|
||||
}
|
||||
onBeforeUnmount(() => {
|
||||
console.log('unmounted')
|
||||
ipcRenderer.removeAllListeners('updateGallery')
|
||||
ipcRenderer.removeListener(GET_PICBEDS, getPicBeds)
|
||||
})
|
||||
|
||||
onActivated(async () => {
|
||||
pasteStyle.value = (await getConfig('settings.pasteStyle')) || 'markdown'
|
||||
})
|
||||
|
||||
</script>
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'GalleryPage'
|
||||
}
|
||||
</script>
|
||||
<style lang='stylus'>
|
||||
.PhotoSlider
|
||||
&__BannerIcon
|
||||
&:nth-child(1)
|
||||
display none
|
||||
&__Counter
|
||||
margin-top 20px
|
||||
.view-title
|
||||
color #eee
|
||||
font-size 20px
|
||||
@@ -473,6 +585,8 @@ export default class extends Vue {
|
||||
transform: rotate(180deg)
|
||||
#gallery-view
|
||||
height 100%
|
||||
.cursor-pointer
|
||||
cursor pointer
|
||||
.item-base
|
||||
background #2E2E2E
|
||||
text-align center
|
||||
@@ -523,9 +637,9 @@ export default class extends Vue {
|
||||
height: 287px
|
||||
top: 113px
|
||||
&__img
|
||||
height 150px
|
||||
// height 150px
|
||||
position relative
|
||||
margin-bottom 16px
|
||||
margin-bottom 8px
|
||||
&__item
|
||||
width 100%
|
||||
height 120px
|
||||
@@ -534,6 +648,7 @@ export default class extends Vue {
|
||||
margin-bottom 4px
|
||||
overflow hidden
|
||||
display flex
|
||||
margin-bottom 6px
|
||||
&-fake
|
||||
position absolute
|
||||
top 0
|
||||
@@ -549,16 +664,20 @@ export default class extends Vue {
|
||||
&__tool-panel
|
||||
color #ddd
|
||||
margin-bottom 4px
|
||||
display flex
|
||||
.el-checkbox
|
||||
height 16px
|
||||
i
|
||||
cursor pointer
|
||||
transition all .2s ease-in-out
|
||||
&.el-icon-document
|
||||
margin-right 4px
|
||||
&.document
|
||||
&:hover
|
||||
color #49B1F5
|
||||
&.el-icon-edit-outline
|
||||
&.edit
|
||||
&:hover
|
||||
color #69C282
|
||||
&.el-icon-delete
|
||||
&.delete
|
||||
&:hover
|
||||
color #F15140
|
||||
&__file-name
|
||||
@@ -571,6 +690,4 @@ export default class extends Vue {
|
||||
.handle-bar
|
||||
color #ddd
|
||||
margin-bottom 10px
|
||||
.el-input__inner
|
||||
border-radius 14px
|
||||
</style>
|
||||
|
||||
@@ -1,187 +1,198 @@
|
||||
<template>
|
||||
<div id="mini-page"
|
||||
<div
|
||||
id="mini-page"
|
||||
:style="{ backgroundImage: 'url(' + logo + ')' }"
|
||||
:class="{ linux: os === 'linux' }"
|
||||
>
|
||||
<!-- <i class="el-icon-upload2"></i> -->
|
||||
<div
|
||||
id="upload-area"
|
||||
:class="{ 'is-dragover': dragover, uploading: showProgress, linux: os === 'linux' }" @drop.prevent="onDrop" @dragover.prevent="dragover = true" @dragleave.prevent="dragover = false"
|
||||
:style="{ backgroundPosition: '0 ' + progress + '%'}"
|
||||
>
|
||||
<div id="upload-dragger" @dblclick="openUploadWindow">
|
||||
<input type="file" id="file-uploader" @change="onChange" multiple>
|
||||
<div
|
||||
id="upload-area"
|
||||
:class="{ 'is-dragover': dragover, uploading: showProgress, linux: os === 'linux' }"
|
||||
:style="{ backgroundPosition: '0 ' + progress + '%'}"
|
||||
@drop.prevent="onDrop"
|
||||
@dragover.prevent="dragover = true"
|
||||
@dragleave.prevent="dragover = false"
|
||||
>
|
||||
<div
|
||||
id="upload-dragger"
|
||||
@dblclick="openUploadWindow"
|
||||
>
|
||||
<input
|
||||
id="file-uploader"
|
||||
type="file"
|
||||
multiple
|
||||
@change="onChange"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import mixin from '@/utils/mixin'
|
||||
import { Component, Vue, Watch } from 'vue-property-decorator'
|
||||
<script lang="ts" setup>
|
||||
// import mixin from '@/utils/mixin'
|
||||
// import { Component, Vue, Watch } from 'vue-property-decorator'
|
||||
import { T as $T } from '@/i18n/index'
|
||||
import { ElMessage as $message } from 'element-plus'
|
||||
import {
|
||||
ipcRenderer,
|
||||
IpcRendererEvent
|
||||
} from 'electron'
|
||||
import { onBeforeUnmount, onBeforeMount, ref, watch } from 'vue'
|
||||
import { SHOW_MINI_PAGE_MENU, SET_MINI_WINDOW_POS } from '~/universal/events/constants'
|
||||
import {
|
||||
isUrl
|
||||
} from '~/universal/utils/common'
|
||||
@Component({
|
||||
name: 'mini-page',
|
||||
mixins: [mixin]
|
||||
import { sendToMain } from '@/utils/dataSender'
|
||||
const logo = require('../assets/squareLogo.png')
|
||||
const dragover = ref(false)
|
||||
const progress = ref(0)
|
||||
const showProgress = ref(false)
|
||||
const showError = ref(false)
|
||||
const dragging = ref(false)
|
||||
const wX = ref(-1)
|
||||
const wY = ref(-1)
|
||||
const screenX = ref(-1)
|
||||
const screenY = ref(-1)
|
||||
const os = ref('')
|
||||
|
||||
onBeforeMount(() => {
|
||||
os.value = process.platform
|
||||
ipcRenderer.on('uploadProgress', (event: IpcRendererEvent, _progress: number) => {
|
||||
if (_progress !== -1) {
|
||||
showProgress.value = true
|
||||
progress.value = _progress
|
||||
} else {
|
||||
progress.value = 100
|
||||
showError.value = true
|
||||
}
|
||||
})
|
||||
window.addEventListener('mousedown', handleMouseDown, false)
|
||||
window.addEventListener('mousemove', handleMouseMove, false)
|
||||
window.addEventListener('mouseup', handleMouseUp, false)
|
||||
})
|
||||
export default class extends Vue {
|
||||
logo = require('../assets/squareLogo.png')
|
||||
dragover = false
|
||||
progress = 0
|
||||
showProgress = false
|
||||
showError = false
|
||||
dragging = false
|
||||
wX: number = -1
|
||||
wY: number = -1
|
||||
screenX: number = -1
|
||||
screenY: number = -1
|
||||
menu: Electron.Menu | null = null
|
||||
os = ''
|
||||
picBed: IPicBedType[] = []
|
||||
created () {
|
||||
this.os = process.platform
|
||||
ipcRenderer.on('uploadProgress', (event: IpcRendererEvent, progress: number) => {
|
||||
if (progress !== -1) {
|
||||
this.showProgress = true
|
||||
this.progress = progress
|
||||
} else {
|
||||
this.progress = 100
|
||||
this.showError = true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
mounted () {
|
||||
window.addEventListener('mousedown', this.handleMouseDown, false)
|
||||
window.addEventListener('mousemove', this.handleMouseMove, false)
|
||||
window.addEventListener('mouseup', this.handleMouseUp, false)
|
||||
watch(progress, (val) => {
|
||||
if (val === 100) {
|
||||
setTimeout(() => {
|
||||
showProgress.value = false
|
||||
showError.value = false
|
||||
}, 1000)
|
||||
setTimeout(() => {
|
||||
progress.value = 0
|
||||
}, 1200)
|
||||
}
|
||||
})
|
||||
|
||||
@Watch('progress')
|
||||
onProgressChange (val: number) {
|
||||
if (val === 100) {
|
||||
setTimeout(() => {
|
||||
this.showProgress = false
|
||||
this.showError = false
|
||||
}, 1000)
|
||||
setTimeout(() => {
|
||||
this.progress = 0
|
||||
}, 1200)
|
||||
}
|
||||
}
|
||||
|
||||
onDrop (e: DragEvent) {
|
||||
this.dragover = false
|
||||
const items = e.dataTransfer!.items
|
||||
if (items.length === 2 && items[0].type === 'text/uri-list') {
|
||||
this.handleURLDrag(items, e.dataTransfer!)
|
||||
} else if (items[0].type === 'text/plain') {
|
||||
const str = e.dataTransfer!.getData(items[0].type)
|
||||
if (isUrl(str)) {
|
||||
ipcRenderer.send('uploadChoosedFiles', [{ path: str }])
|
||||
} else {
|
||||
this.$message.error(this.$T('TIPS_DRAG_VALID_PICTURE_OR_URL'))
|
||||
}
|
||||
function onDrop (e: DragEvent) {
|
||||
dragover.value = false
|
||||
const items = e.dataTransfer!.items
|
||||
if (items.length === 2 && items[0].type === 'text/uri-list') {
|
||||
handleURLDrag(items, e.dataTransfer!)
|
||||
} else if (items[0].type === 'text/plain') {
|
||||
const str = e.dataTransfer!.getData(items[0].type)
|
||||
if (isUrl(str)) {
|
||||
sendToMain('uploadChoosedFiles', [{ path: str }])
|
||||
} else {
|
||||
this.ipcSendFiles(e.dataTransfer!.files)
|
||||
$message.error($T('TIPS_DRAG_VALID_PICTURE_OR_URL'))
|
||||
}
|
||||
} else {
|
||||
ipcSendFiles(e.dataTransfer!.files)
|
||||
}
|
||||
}
|
||||
|
||||
handleURLDrag (items: DataTransferItemList, dataTransfer: DataTransfer) {
|
||||
// text/html
|
||||
// Use this data to get a more precise URL
|
||||
const urlString = dataTransfer.getData(items[1].type)
|
||||
const urlMatch = urlString.match(/<img.*src="(.*?)"/)
|
||||
if (urlMatch) {
|
||||
ipcRenderer.send('uploadChoosedFiles', [
|
||||
{
|
||||
path: urlMatch[1]
|
||||
}
|
||||
])
|
||||
} else {
|
||||
this.$message.error(this.$T('TIPS_DRAG_VALID_PICTURE_OR_URL'))
|
||||
}
|
||||
}
|
||||
|
||||
openUploadWindow () {
|
||||
// @ts-ignore
|
||||
document.getElementById('file-uploader').click()
|
||||
}
|
||||
|
||||
onChange (e: any) {
|
||||
this.ipcSendFiles(e.target.files)
|
||||
// @ts-ignore
|
||||
document.getElementById('file-uploader').value = ''
|
||||
}
|
||||
|
||||
ipcSendFiles (files: FileList) {
|
||||
const sendFiles: IFileWithPath[] = []
|
||||
Array.from(files).forEach((item) => {
|
||||
const obj = {
|
||||
name: item.name,
|
||||
path: item.path
|
||||
function handleURLDrag (items: DataTransferItemList, dataTransfer: DataTransfer) {
|
||||
// text/html
|
||||
// Use this data to get a more precise URL
|
||||
const urlString = dataTransfer.getData(items[1].type)
|
||||
const urlMatch = urlString.match(/<img.*src="(.*?)"/)
|
||||
if (urlMatch) {
|
||||
sendToMain('uploadChoosedFiles', [
|
||||
{
|
||||
path: urlMatch[1]
|
||||
}
|
||||
sendFiles.push(obj)
|
||||
])
|
||||
} else {
|
||||
$message.error($T('TIPS_DRAG_VALID_PICTURE_OR_URL'))
|
||||
}
|
||||
}
|
||||
|
||||
function openUploadWindow () {
|
||||
// @ts-ignore
|
||||
document.getElementById('file-uploader').click()
|
||||
}
|
||||
|
||||
function onChange (e: any) {
|
||||
ipcSendFiles(e.target.files)
|
||||
// @ts-ignore
|
||||
document.getElementById('file-uploader').value = ''
|
||||
}
|
||||
|
||||
function ipcSendFiles (files: FileList) {
|
||||
const sendFiles: IFileWithPath[] = []
|
||||
Array.from(files).forEach((item) => {
|
||||
const obj = {
|
||||
name: item.name,
|
||||
path: item.path
|
||||
}
|
||||
sendFiles.push(obj)
|
||||
})
|
||||
sendToMain('uploadChoosedFiles', sendFiles)
|
||||
}
|
||||
|
||||
function handleMouseDown (e: MouseEvent) {
|
||||
dragging.value = true
|
||||
wX.value = e.pageX
|
||||
wY.value = e.pageY
|
||||
screenX.value = e.screenX
|
||||
screenY.value = e.screenY
|
||||
}
|
||||
|
||||
function handleMouseMove (e: MouseEvent) {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
if (dragging.value) {
|
||||
const xLoc = e.screenX - wX.value
|
||||
const yLoc = e.screenY - wY.value
|
||||
sendToMain(SET_MINI_WINDOW_POS, {
|
||||
x: xLoc,
|
||||
y: yLoc,
|
||||
width: 64,
|
||||
height: 64
|
||||
})
|
||||
ipcRenderer.send('uploadChoosedFiles', sendFiles)
|
||||
// remote.BrowserWindow.getFocusedWindow()!.setBounds({
|
||||
// x: xLoc,
|
||||
// y: yLoc,
|
||||
// width: 64,
|
||||
// height: 64
|
||||
// })
|
||||
}
|
||||
}
|
||||
|
||||
handleMouseDown (e: MouseEvent) {
|
||||
this.dragging = true
|
||||
this.wX = e.pageX
|
||||
this.wY = e.pageY
|
||||
this.screenX = e.screenX
|
||||
this.screenY = e.screenY
|
||||
}
|
||||
|
||||
handleMouseMove (e: MouseEvent) {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
if (this.dragging) {
|
||||
const xLoc = e.screenX - this.wX
|
||||
const yLoc = e.screenY - this.wY
|
||||
ipcRenderer.send(SET_MINI_WINDOW_POS, {
|
||||
x: xLoc,
|
||||
y: yLoc,
|
||||
width: 64,
|
||||
height: 64
|
||||
})
|
||||
// remote.BrowserWindow.getFocusedWindow()!.setBounds({
|
||||
// x: xLoc,
|
||||
// y: yLoc,
|
||||
// width: 64,
|
||||
// height: 64
|
||||
// })
|
||||
function handleMouseUp (e: MouseEvent) {
|
||||
dragging.value = false
|
||||
if (screenX.value === e.screenX && screenY.value === e.screenY) {
|
||||
if (e.button === 0) { // left mouse
|
||||
openUploadWindow()
|
||||
} else {
|
||||
openContextMenu()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handleMouseUp (e: MouseEvent) {
|
||||
this.dragging = false
|
||||
if (this.screenX === e.screenX && this.screenY === e.screenY) {
|
||||
if (e.button === 0) { // left mouse
|
||||
this.openUploadWindow()
|
||||
} else {
|
||||
this.openContextMenu()
|
||||
}
|
||||
}
|
||||
}
|
||||
function openContextMenu () {
|
||||
sendToMain(SHOW_MINI_PAGE_MENU)
|
||||
}
|
||||
|
||||
openContextMenu () {
|
||||
ipcRenderer.send(SHOW_MINI_PAGE_MENU)
|
||||
}
|
||||
onBeforeUnmount(() => {
|
||||
ipcRenderer.removeAllListeners('uploadProgress')
|
||||
window.removeEventListener('mousedown', handleMouseDown, false)
|
||||
window.removeEventListener('mousemove', handleMouseMove, false)
|
||||
window.removeEventListener('mouseup', handleMouseUp, false)
|
||||
})
|
||||
|
||||
beforeDestroy () {
|
||||
ipcRenderer.removeAllListeners('uploadProgress')
|
||||
window.removeEventListener('mousedown', this.handleMouseDown, false)
|
||||
window.removeEventListener('mousemove', this.handleMouseMove, false)
|
||||
window.removeEventListener('mouseup', this.handleMouseUp, false)
|
||||
}
|
||||
</script>
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'MiniPage'
|
||||
}
|
||||
</script>
|
||||
<style lang='stylus'>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div id="rename-page">
|
||||
<el-form
|
||||
@submit.native.prevent
|
||||
@submit.prevent
|
||||
>
|
||||
<el-form-item
|
||||
:label="$T('FILE_RENAME')"
|
||||
@@ -9,54 +9,67 @@
|
||||
<el-input
|
||||
v-model="fileName"
|
||||
size="small"
|
||||
@keyup.enter.native="confirmName"
|
||||
></el-input>
|
||||
@keyup.enter="confirmName"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-row>
|
||||
<div class="pull-right">
|
||||
<el-button @click="cancel" round size="mini">{{ $T('CANCEL') }}</el-button>
|
||||
<el-button type="primary" @click="confirmName" round size="mini">{{ $T('CONFIRM') }}</el-button>
|
||||
<el-button
|
||||
round
|
||||
size="small"
|
||||
@click="cancel"
|
||||
>
|
||||
{{ $T('CANCEL') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
round
|
||||
size="small"
|
||||
@click="confirmName"
|
||||
>
|
||||
{{ $T('CONFIRM') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
<script lang="ts" setup>
|
||||
import { RENAME_FILE_NAME } from '#/events/constants'
|
||||
import { Component, Vue } from 'vue-property-decorator'
|
||||
import mixin from '@/utils/mixin'
|
||||
import { sendToMain } from '@/utils/dataSender'
|
||||
import {
|
||||
ipcRenderer,
|
||||
IpcRendererEvent
|
||||
} from 'electron'
|
||||
@Component({
|
||||
name: 'rename-page',
|
||||
mixins: [mixin]
|
||||
import { onBeforeUnmount, onBeforeMount, ref } from 'vue'
|
||||
const fileName = ref('')
|
||||
const originName = ref('')
|
||||
const id = ref<string | null>(null)
|
||||
onBeforeMount(() => {
|
||||
ipcRenderer.on(RENAME_FILE_NAME, (event: IpcRendererEvent, newName: string, _originName: string, _id: string) => {
|
||||
fileName.value = newName
|
||||
originName.value = _originName
|
||||
id.value = _id
|
||||
})
|
||||
})
|
||||
export default class extends Vue {
|
||||
fileName: string = ''
|
||||
originName: string = ''
|
||||
id: string | null = null
|
||||
created () {
|
||||
ipcRenderer.on(RENAME_FILE_NAME, (event: IpcRendererEvent, newName: string, originName: string, id: string) => {
|
||||
this.fileName = newName
|
||||
this.originName = originName
|
||||
this.id = id
|
||||
})
|
||||
}
|
||||
|
||||
confirmName () {
|
||||
ipcRenderer.send(`${RENAME_FILE_NAME}${this.id}`, this.fileName)
|
||||
}
|
||||
function confirmName () {
|
||||
sendToMain(`${RENAME_FILE_NAME}${id.value}`, fileName.value)
|
||||
}
|
||||
|
||||
cancel () {
|
||||
// if cancel, use origin file name
|
||||
ipcRenderer.send(`${RENAME_FILE_NAME}${this.id}`, this.originName)
|
||||
}
|
||||
function cancel () {
|
||||
// if cancel, use origin file name
|
||||
sendToMain(`${RENAME_FILE_NAME}${id.value}`, originName.value)
|
||||
}
|
||||
|
||||
beforeDestroy () {
|
||||
ipcRenderer.removeAllListeners('rename')
|
||||
}
|
||||
onBeforeUnmount(() => {
|
||||
ipcRenderer.removeAllListeners('rename')
|
||||
})
|
||||
|
||||
</script>
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'RenamePage'
|
||||
}
|
||||
</script>
|
||||
<style lang='stylus'>
|
||||
|
||||
@@ -4,18 +4,21 @@
|
||||
{{ $T('SETTINGS_SET_SHORTCUT') }}
|
||||
</div>
|
||||
<el-row>
|
||||
<el-col :span="20" :offset="2">
|
||||
<el-col
|
||||
:span="20"
|
||||
:offset="2"
|
||||
>
|
||||
<el-table
|
||||
class="shortcut-page-table-border"
|
||||
:data="list"
|
||||
size="mini"
|
||||
size="small"
|
||||
header-cell-class-name="shortcut-page-table-border"
|
||||
cell-class-name="shortcut-page-table-border"
|
||||
>
|
||||
<el-table-column
|
||||
:label="$T('SHORTCUT_NAME')"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<template #default="scope">
|
||||
{{ scope.row.label ? scope.row.label : scope.row.name }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -23,14 +26,13 @@
|
||||
width="160px"
|
||||
:label="$T('SHORTCUT_BIND')"
|
||||
prop="key"
|
||||
>
|
||||
</el-table-column>
|
||||
/>
|
||||
<el-table-column
|
||||
:label="$T('SHORTCUT_STATUS')"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<template #default="scope">
|
||||
<el-tag
|
||||
size="mini"
|
||||
size="small"
|
||||
:type="scope.row.enable ? 'success' : 'danger'"
|
||||
>
|
||||
{{ scope.row.enable ? $T('SHORTCUT_ENABLED') : $T('SHORTCUT_DISABLED') }}
|
||||
@@ -41,38 +43,43 @@
|
||||
:label="$T('SHORTCUT_SOURCE')"
|
||||
width="100px"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<template #default="scope">
|
||||
{{ calcOriginShowName(scope.row.from) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
:label="$T('SHORTCUT_HANDLE')"
|
||||
width="100px"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
@click="toggleEnable(scope.row)"
|
||||
size="mini"
|
||||
:class="{
|
||||
disabled: scope.row.enable
|
||||
}"
|
||||
type="text">
|
||||
{{ scope.row.enable ? $T('SHORTCUT_DISABLE') : $T('SHORTCUT_ENABLE') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
class="edit"
|
||||
size="mini"
|
||||
@click="openKeyBindingDialog(scope.row, scope.$index)"
|
||||
type="text">
|
||||
{{ $T('SHORTCUT_EDIT') }}
|
||||
</el-button>
|
||||
<template #default="scope">
|
||||
<el-row>
|
||||
<el-button
|
||||
size="small"
|
||||
:class="{
|
||||
disabled: scope.row.enable
|
||||
}"
|
||||
type="text"
|
||||
@click="toggleEnable(scope.row)"
|
||||
>
|
||||
{{ scope.row.enable ? $T('SHORTCUT_DISABLE') : $T('SHORTCUT_ENABLE') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
class="edit"
|
||||
size="small"
|
||||
type="text"
|
||||
@click="openKeyBindingDialog(scope.row, scope.$index)"
|
||||
>
|
||||
{{ $T('SHORTCUT_EDIT') }}
|
||||
</el-button>
|
||||
</el-row>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-dialog
|
||||
v-model="keyBindingVisible"
|
||||
:title="$T('SHORTCUT_CHANGE_UPLOAD')"
|
||||
:visible.sync="keyBindingVisible"
|
||||
:modal-append-to-body="false"
|
||||
>
|
||||
<el-form
|
||||
@@ -81,101 +88,109 @@
|
||||
>
|
||||
<el-form-item>
|
||||
<el-input
|
||||
class="align-center"
|
||||
@keydown.native.prevent="keyDetect($event)"
|
||||
v-model="shortKey"
|
||||
class="align-center"
|
||||
:autofocus="true"
|
||||
></el-input>
|
||||
@keydown.prevent="keyDetect($event as KeyboardEvent)"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<span slot="footer">
|
||||
<el-button @click="cancelKeyBinding" round>
|
||||
<template #footer>
|
||||
<el-button
|
||||
round
|
||||
@click="cancelKeyBinding"
|
||||
>
|
||||
{{ $T('CANCEL') }}
|
||||
</el-button>
|
||||
<el-button type="primary" @click="confirmKeyBinding" round>
|
||||
<el-button
|
||||
type="primary"
|
||||
round
|
||||
@click="confirmKeyBinding"
|
||||
>
|
||||
{{ $T('CONFIRM') }}
|
||||
</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { Component, Vue, Watch } from 'vue-property-decorator'
|
||||
import keyDetect from '@/utils/key-binding'
|
||||
<script lang="ts" setup>
|
||||
import keyBinding from '@/utils/key-binding'
|
||||
import { ipcRenderer, IpcRendererEvent } from 'electron'
|
||||
import { TOGGLE_SHORTKEY_MODIFIED_MODE } from '#/events/constants'
|
||||
import { onBeforeUnmount, onBeforeMount, ref, watch } from 'vue'
|
||||
import { getConfig, sendToMain } from '@/utils/dataSender'
|
||||
|
||||
@Component({
|
||||
name: 'shortkey-page'
|
||||
const list = ref<IShortKeyConfig[]>([])
|
||||
const keyBindingVisible = ref(false)
|
||||
const command = ref('')
|
||||
const shortKey = ref('')
|
||||
const currentIndex = ref(0)
|
||||
|
||||
onBeforeMount(async () => {
|
||||
const shortKeyConfig = (await getConfig<IShortKeyConfigs>('settings.shortKey'))!
|
||||
list.value = Object.keys(shortKeyConfig).map(item => {
|
||||
return {
|
||||
...shortKeyConfig[item],
|
||||
from: calcOrigin(item)
|
||||
}
|
||||
})
|
||||
})
|
||||
export default class extends Vue {
|
||||
list: IShortKeyConfig[] = []
|
||||
keyBindingVisible = false
|
||||
command = ''
|
||||
shortKey = ''
|
||||
currentIndex = 0
|
||||
async created () {
|
||||
const shortKeyConfig = (await this.getConfig<IShortKeyConfigs>('settings.shortKey'))!
|
||||
this.list = Object.keys(shortKeyConfig).map(item => {
|
||||
return {
|
||||
...shortKeyConfig[item],
|
||||
from: this.calcOrigin(item)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@Watch('keyBindingVisible')
|
||||
onKeyBindingVisibleChange (val: boolean) {
|
||||
ipcRenderer.send(TOGGLE_SHORTKEY_MODIFIED_MODE, val)
|
||||
}
|
||||
watch(keyBindingVisible, (val: boolean) => {
|
||||
sendToMain(TOGGLE_SHORTKEY_MODIFIED_MODE, val)
|
||||
})
|
||||
|
||||
calcOrigin (item: string) {
|
||||
const [origin] = item.split(':')
|
||||
return origin
|
||||
}
|
||||
function calcOrigin (item: string) {
|
||||
const [origin] = item.split(':')
|
||||
return origin
|
||||
}
|
||||
|
||||
calcOriginShowName (item: string) {
|
||||
return item.replace('picgo-plugin-', '')
|
||||
}
|
||||
function calcOriginShowName (item: string) {
|
||||
return item.replace('picgo-plugin-', '')
|
||||
}
|
||||
|
||||
toggleEnable (item: IShortKeyConfig) {
|
||||
const status = !item.enable
|
||||
item.enable = status
|
||||
ipcRenderer.send('bindOrUnbindShortKey', item, item.from)
|
||||
}
|
||||
function toggleEnable (item: IShortKeyConfig) {
|
||||
const status = !item.enable
|
||||
item.enable = status
|
||||
sendToMain('bindOrUnbindShortKey', item, item.from)
|
||||
}
|
||||
|
||||
keyDetect (event: KeyboardEvent) {
|
||||
this.shortKey = keyDetect(event).join('+')
|
||||
}
|
||||
function keyDetect (event: KeyboardEvent) {
|
||||
shortKey.value = keyBinding(event).join('+')
|
||||
}
|
||||
|
||||
async openKeyBindingDialog (config: IShortKeyConfig, index: number) {
|
||||
this.command = `${config.from}:${config.name}`
|
||||
this.shortKey = await this.getConfig(`settings.shortKey.${this.command}.key`) || ''
|
||||
this.currentIndex = index
|
||||
this.keyBindingVisible = true
|
||||
}
|
||||
async function openKeyBindingDialog (config: IShortKeyConfig, index: number) {
|
||||
command.value = `${config.from}:${config.name}`
|
||||
shortKey.value = await getConfig(`settings.shortKey.${command.value}.key`) || ''
|
||||
currentIndex.value = index
|
||||
keyBindingVisible.value = true
|
||||
}
|
||||
|
||||
async cancelKeyBinding () {
|
||||
this.keyBindingVisible = false
|
||||
this.shortKey = await this.getConfig<string>(`settings.shortKey.${this.command}.key`) || ''
|
||||
}
|
||||
async function cancelKeyBinding () {
|
||||
keyBindingVisible.value = false
|
||||
shortKey.value = await getConfig<string>(`settings.shortKey.${command.value}.key`) || ''
|
||||
}
|
||||
|
||||
async confirmKeyBinding () {
|
||||
const oldKey = await this.getConfig<string>(`settings.shortKey.${this.command}.key`)
|
||||
const config = Object.assign({}, this.list[this.currentIndex])
|
||||
config.key = this.shortKey
|
||||
ipcRenderer.send('updateShortKey', config, oldKey, config.from)
|
||||
ipcRenderer.once('updateShortKeyResponse', (evt: IpcRendererEvent, result) => {
|
||||
if (result) {
|
||||
this.keyBindingVisible = false
|
||||
this.list[this.currentIndex].key = this.shortKey
|
||||
}
|
||||
})
|
||||
}
|
||||
async function confirmKeyBinding () {
|
||||
const oldKey = await getConfig<string>(`settings.shortKey.${command.value}.key`)
|
||||
const config = Object.assign({}, list.value[currentIndex.value])
|
||||
config.key = shortKey.value
|
||||
sendToMain('updateShortKey', config, oldKey, config.from)
|
||||
ipcRenderer.once('updateShortKeyResponse', (evt: IpcRendererEvent, result) => {
|
||||
if (result) {
|
||||
keyBindingVisible.value = false
|
||||
list.value[currentIndex.value].key = shortKey.value
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
beforeDestroy () {
|
||||
ipcRenderer.send(TOGGLE_SHORTKEY_MODIFIED_MODE, false)
|
||||
}
|
||||
onBeforeUnmount(() => {
|
||||
sendToMain(TOGGLE_SHORTKEY_MODIFIED_MODE, false)
|
||||
})
|
||||
</script>
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'ShortkeyPage'
|
||||
}
|
||||
</script>
|
||||
<style lang='stylus'>
|
||||
@@ -191,6 +206,9 @@ export default class extends Vue {
|
||||
color: #F56C6C
|
||||
&.edit
|
||||
color: #67C23A
|
||||
&--text
|
||||
padding-left 4px
|
||||
padding-right 4px
|
||||
.el-table
|
||||
background-color: transparent
|
||||
color #ddd
|
||||
@@ -209,4 +227,6 @@ export default class extends Vue {
|
||||
tr:hover
|
||||
&>td
|
||||
background #333
|
||||
.el-button+.el-button
|
||||
margin-left 4px
|
||||
</style>
|
||||
|
||||
@@ -1,24 +1,59 @@
|
||||
<template>
|
||||
<div id="tray-page">
|
||||
<div class="open-main-window" @click="openSettingWindow">{{ $T('OPEN_MAIN_WINDOW') }}</div>
|
||||
<div
|
||||
class="open-main-window"
|
||||
@click="openSettingWindow"
|
||||
>
|
||||
{{ $T('OPEN_MAIN_WINDOW') }}
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="wait-upload-img" v-if="clipboardFiles.length > 0">
|
||||
<div class="list-title">{{ $T('WAIT_TO_UPLOAD') }}</div>
|
||||
<div v-for="(item, index) in clipboardFiles" :key="index" class="img-list">
|
||||
<div
|
||||
v-if="clipboardFiles.length > 0"
|
||||
class="wait-upload-img"
|
||||
>
|
||||
<div class="list-title">
|
||||
{{ $T('WAIT_TO_UPLOAD') }}
|
||||
</div>
|
||||
<div
|
||||
v-for="(item, index) in clipboardFiles"
|
||||
:key="index"
|
||||
class="img-list"
|
||||
>
|
||||
<div
|
||||
class="upload-img__container"
|
||||
:class="{ upload: uploadFlag }"
|
||||
@click="uploadClipboardFiles">
|
||||
<img :src="item.imgUrl" class="upload-img">
|
||||
@click="uploadClipboardFiles"
|
||||
>
|
||||
<img
|
||||
:src="item.imgUrl"
|
||||
class="upload-img"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="uploaded-img">
|
||||
<div class="list-title">{{ $T('ALREADY_UPLOAD') }}</div>
|
||||
<div v-for="item in files" :key="item.imgUrl" class="img-list">
|
||||
<div class="upload-img__container" @click="copyTheLink(item)">
|
||||
<img v-lazy="item.imgUrl" class="upload-img">
|
||||
<div class="upload-img__title" :title="item.fileName">{{ item.fileName }}</div>
|
||||
<div class="list-title">
|
||||
{{ $T('ALREADY_UPLOAD') }}
|
||||
</div>
|
||||
<div
|
||||
v-for="item in files"
|
||||
:key="item.imgUrl"
|
||||
class="img-list"
|
||||
>
|
||||
<div
|
||||
class="upload-img__container"
|
||||
@click="copyTheLink(item)"
|
||||
>
|
||||
<img
|
||||
v-lazy="item.imgUrl"
|
||||
class="upload-img"
|
||||
>
|
||||
<div
|
||||
class="upload-img__title"
|
||||
:title="item.fileName"
|
||||
>
|
||||
{{ item.fileName }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -26,99 +61,100 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from 'vue-property-decorator'
|
||||
import mixin from '@/utils/mixin'
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref, onBeforeUnmount, onBeforeMount } from 'vue'
|
||||
import { ipcRenderer } from 'electron'
|
||||
import $$db from '@/utils/db'
|
||||
import { T as $T } from '@/i18n/index'
|
||||
import { IResult } from '@picgo/store/dist/types'
|
||||
import { PASTE_TEXT, OPEN_WINDOW } from '#/events/constants'
|
||||
import { IWindowList } from '#/types/enum'
|
||||
import { sendToMain } from '@/utils/dataSender'
|
||||
|
||||
@Component({
|
||||
name: 'tray-page',
|
||||
mixins: [mixin]
|
||||
const files = ref<IResult<ImgInfo>[]>([])
|
||||
const notification = reactive({
|
||||
title: $T('COPY_LINK_SUCCEED'),
|
||||
body: ''
|
||||
})
|
||||
export default class extends Vue {
|
||||
files: IResult<ImgInfo>[] = []
|
||||
notification = {
|
||||
title: this.$T('COPY_LINK_SUCCEED'),
|
||||
body: ''
|
||||
}
|
||||
|
||||
clipboardFiles: ImgInfo[] = []
|
||||
uploadFlag = false
|
||||
get reverseList () {
|
||||
return this.files.slice().reverse()
|
||||
}
|
||||
const clipboardFiles = ref<ImgInfo[]>([])
|
||||
const uploadFlag = ref(false)
|
||||
|
||||
openSettingWindow () {
|
||||
this.sendToMain(OPEN_WINDOW, IWindowList.SETTING_WINDOW)
|
||||
}
|
||||
// const reverseList = computed(() => files.value.slice().reverse())
|
||||
|
||||
async getData () {
|
||||
this.files = (await this.$$db.get<ImgInfo>({ orderBy: 'desc', limit: 5 })).data
|
||||
}
|
||||
function openSettingWindow () {
|
||||
sendToMain(OPEN_WINDOW, IWindowList.SETTING_WINDOW)
|
||||
}
|
||||
|
||||
async copyTheLink (item: ImgInfo) {
|
||||
this.notification.body = item.imgUrl!
|
||||
const myNotification = new Notification(this.notification.title, this.notification)
|
||||
ipcRenderer.invoke(PASTE_TEXT, item)
|
||||
myNotification.onclick = () => {
|
||||
return true
|
||||
async function getData () {
|
||||
files.value = (await $$db.get<ImgInfo>({ orderBy: 'desc', limit: 5 })).data
|
||||
}
|
||||
|
||||
async function copyTheLink (item: ImgInfo) {
|
||||
notification.body = item.imgUrl!
|
||||
const myNotification = new Notification(notification.title, notification)
|
||||
ipcRenderer.invoke(PASTE_TEXT, item)
|
||||
myNotification.onclick = () => {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// function calcHeight (width: number, height: number): number {
|
||||
// return height * 160 / width
|
||||
// }
|
||||
|
||||
function disableDragFile () {
|
||||
window.addEventListener('dragover', (e) => {
|
||||
e = e || event
|
||||
e.preventDefault()
|
||||
}, false)
|
||||
window.addEventListener('drop', (e) => {
|
||||
e = e || event
|
||||
e.preventDefault()
|
||||
}, false)
|
||||
}
|
||||
|
||||
function uploadClipboardFiles () {
|
||||
if (uploadFlag.value) {
|
||||
return
|
||||
}
|
||||
uploadFlag.value = true
|
||||
sendToMain('uploadClipboardFiles')
|
||||
}
|
||||
|
||||
onBeforeMount(() => {
|
||||
disableDragFile()
|
||||
getData()
|
||||
ipcRenderer.on('dragFiles', async (event: Event, _files: string[]) => {
|
||||
for (let i = 0; i < _files.length; i++) {
|
||||
const item = _files[i]
|
||||
await $$db.insert(item)
|
||||
}
|
||||
}
|
||||
files.value = (await $$db.get<ImgInfo>({ orderBy: 'desc', limit: 5 })).data
|
||||
})
|
||||
ipcRenderer.on('clipboardFiles', (event: Event, files: ImgInfo[]) => {
|
||||
clipboardFiles.value = files
|
||||
})
|
||||
ipcRenderer.on('uploadFiles', async () => {
|
||||
files.value = (await $$db.get<ImgInfo>({ orderBy: 'desc', limit: 5 })).data
|
||||
uploadFlag.value = false
|
||||
})
|
||||
ipcRenderer.on('updateFiles', () => {
|
||||
getData()
|
||||
})
|
||||
})
|
||||
|
||||
calcHeight (width: number, height: number): number {
|
||||
return height * 160 / width
|
||||
}
|
||||
onBeforeUnmount(() => {
|
||||
ipcRenderer.removeAllListeners('dragFiles')
|
||||
ipcRenderer.removeAllListeners('clipboardFiles')
|
||||
ipcRenderer.removeAllListeners('uploadClipboardFiles')
|
||||
ipcRenderer.removeAllListeners('updateFiles')
|
||||
})
|
||||
</script>
|
||||
|
||||
disableDragFile () {
|
||||
window.addEventListener('dragover', (e) => {
|
||||
e = e || event
|
||||
e.preventDefault()
|
||||
}, false)
|
||||
window.addEventListener('drop', (e) => {
|
||||
e = e || event
|
||||
e.preventDefault()
|
||||
}, false)
|
||||
}
|
||||
|
||||
uploadClipboardFiles () {
|
||||
if (this.uploadFlag) {
|
||||
return
|
||||
}
|
||||
this.uploadFlag = true
|
||||
ipcRenderer.send('uploadClipboardFiles')
|
||||
}
|
||||
|
||||
mounted () {
|
||||
this.disableDragFile()
|
||||
this.getData()
|
||||
ipcRenderer.on('dragFiles', async (event: Event, files: string[]) => {
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
const item = files[i]
|
||||
await this.$$db.insert(item)
|
||||
}
|
||||
this.files = (await this.$$db.get<ImgInfo>({ orderBy: 'desc', limit: 5 })).data
|
||||
})
|
||||
ipcRenderer.on('clipboardFiles', (event: Event, files: ImgInfo[]) => {
|
||||
this.clipboardFiles = files
|
||||
})
|
||||
ipcRenderer.on('uploadFiles', async () => {
|
||||
this.files = (await this.$$db.get<ImgInfo>({ orderBy: 'desc', limit: 5 })).data
|
||||
this.uploadFlag = false
|
||||
})
|
||||
ipcRenderer.on('updateFiles', () => {
|
||||
this.getData()
|
||||
})
|
||||
}
|
||||
|
||||
beforeDestroy () {
|
||||
ipcRenderer.removeAllListeners('dragFiles')
|
||||
ipcRenderer.removeAllListeners('clipboardFiles')
|
||||
ipcRenderer.removeAllListeners('uploadClipboardFiles')
|
||||
ipcRenderer.removeAllListeners('updateFiles')
|
||||
}
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'TrayPage'
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -179,11 +215,20 @@ body::-webkit-scrollbar
|
||||
background #49B1F5
|
||||
.upload-img__index
|
||||
color #fff
|
||||
.upload-img__container
|
||||
display flex
|
||||
flex-direction column
|
||||
justify-content center
|
||||
align-items center
|
||||
.upload-img
|
||||
width 100%
|
||||
max-width 100%
|
||||
object-fit scale-down
|
||||
margin 0 auto
|
||||
&__container
|
||||
display flex
|
||||
flex-direction column
|
||||
justify-content center
|
||||
align-items center
|
||||
width 100%
|
||||
padding 8px 8px 4px
|
||||
height 100%
|
||||
|
||||
@@ -1,9 +1,18 @@
|
||||
<template>
|
||||
<div id="upload-view">
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="20" :offset="2">
|
||||
<el-col
|
||||
:span="20"
|
||||
:offset="2"
|
||||
>
|
||||
<div class="view-title">
|
||||
{{ $T('PICTURE_UPLOAD') }} - {{ picBedName }} <i class="el-icon-caret-bottom" @click="handleChangePicBed"></i>
|
||||
{{ $T('PICTURE_UPLOAD') }} - {{ picBedName }}
|
||||
<el-icon
|
||||
style="cursor: pointer; margin-left: 4px;"
|
||||
@click="handleChangePicBed"
|
||||
>
|
||||
<CaretBottom />
|
||||
</el-icon>
|
||||
</div>
|
||||
<div
|
||||
id="upload-area"
|
||||
@@ -12,12 +21,22 @@
|
||||
@dragover.prevent="dragover = true"
|
||||
@dragleave.prevent="dragover = false"
|
||||
>
|
||||
<div id="upload-dragger" @click="openUplodWindow">
|
||||
<i class="el-icon-upload"></i>
|
||||
<div
|
||||
id="upload-dragger"
|
||||
@click="openUplodWindow"
|
||||
>
|
||||
<el-icon>
|
||||
<UploadFilled />
|
||||
</el-icon>
|
||||
<div class="upload-dragger__text">
|
||||
{{ $T('DRAG_FILE_TO_HERE') }} <span>{{ $T('CLICK_TO_UPLOAD') }}</span>
|
||||
</div>
|
||||
<input type="file" id="file-uploader" @change="onChange" multiple>
|
||||
<input
|
||||
id="file-uploader"
|
||||
type="file"
|
||||
multiple
|
||||
@change="onChange"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<el-progress
|
||||
@@ -26,42 +45,69 @@
|
||||
class="upload-progress"
|
||||
:class="{ 'show': showProgress }"
|
||||
:status="showError ? 'exception' : undefined"
|
||||
></el-progress>
|
||||
/>
|
||||
<div class="paste-style">
|
||||
<div class="el-col-16">
|
||||
<div class="paste-style__text">
|
||||
{{ $T('LINK_FORMAT') }}
|
||||
</div>
|
||||
<el-radio-group v-model="pasteStyle" size="mini"
|
||||
<el-radio-group
|
||||
v-model="pasteStyle"
|
||||
size="small"
|
||||
@change="handlePasteStyleChange"
|
||||
>
|
||||
<el-radio-button label="markdown">
|
||||
Markdown
|
||||
</el-radio-button>
|
||||
<el-radio-button label="HTML"></el-radio-button>
|
||||
<el-radio-button label="URL"></el-radio-button>
|
||||
<el-radio-button label="UBB"></el-radio-button>
|
||||
<el-radio-button label="Custom" :title="$T('CUSTOM')"></el-radio-button>
|
||||
<el-radio-button label="HTML" />
|
||||
<el-radio-button label="URL" />
|
||||
<el-radio-button label="UBB" />
|
||||
<el-radio-button
|
||||
label="Custom"
|
||||
:title="$T('CUSTOM')"
|
||||
/>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<div class="el-col-8">
|
||||
<div class="paste-style__text">
|
||||
{{ $T('QUICK_UPLOAD') }}
|
||||
</div>
|
||||
<el-button type="primary" round size="mini" @click="uploadClipboardFiles" class="quick-upload" style="width: 50%">{{ $T('CLIPBOARD_PICTURE') }}</el-button>
|
||||
<el-button type="primary" round size="mini" @click="uploadURLFiles" class="quick-upload" style="width: 46%; margin-left: 6px">URL</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
round
|
||||
size="small"
|
||||
class="quick-upload"
|
||||
style="width: 50%"
|
||||
@click="uploadClipboardFiles"
|
||||
>
|
||||
{{ $T('CLIPBOARD_PICTURE') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
round
|
||||
size="small"
|
||||
class="quick-upload"
|
||||
style="width: 46%; margin-left: 6px"
|
||||
@click="uploadURLFiles"
|
||||
>
|
||||
URL
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { Component, Vue, Watch } from 'vue-property-decorator'
|
||||
<script lang="ts" setup>
|
||||
// import { Component, Vue, Watch } from 'vue-property-decorator'
|
||||
import { UploadFilled, CaretBottom } from '@element-plus/icons-vue'
|
||||
import {
|
||||
ipcRenderer,
|
||||
IpcRendererEvent
|
||||
} from 'electron'
|
||||
import { ref, onBeforeMount, onBeforeUnmount, watch } from 'vue'
|
||||
import { T as $T } from '@/i18n'
|
||||
import $bus from '@/utils/bus'
|
||||
import {
|
||||
SHOW_INPUT_BOX,
|
||||
SHOW_INPUT_BOX_RESPONSE,
|
||||
@@ -71,170 +117,176 @@ import {
|
||||
import {
|
||||
isUrl
|
||||
} from '~/universal/utils/common'
|
||||
@Component({
|
||||
name: 'upload'
|
||||
import { ElMessage as $message } from 'element-plus'
|
||||
import { getConfig, saveConfig, sendToMain } from '@/utils/dataSender'
|
||||
const dragover = ref(false)
|
||||
const progress = ref(0)
|
||||
const showProgress = ref(false)
|
||||
const showError = ref(false)
|
||||
const pasteStyle = ref('')
|
||||
const picBed = ref<IPicBedType[]>([])
|
||||
const picBedName = ref('')
|
||||
onBeforeMount(() => {
|
||||
ipcRenderer.on('uploadProgress', (event: IpcRendererEvent, _progress: number) => {
|
||||
if (_progress !== -1) {
|
||||
showProgress.value = true
|
||||
progress.value = _progress
|
||||
} else {
|
||||
progress.value = 100
|
||||
showError.value = true
|
||||
}
|
||||
})
|
||||
getPasteStyle()
|
||||
getDefaultPicBed()
|
||||
ipcRenderer.on('syncPicBed', () => {
|
||||
getDefaultPicBed()
|
||||
})
|
||||
sendToMain(GET_PICBEDS)
|
||||
ipcRenderer.on(GET_PICBEDS, getPicBeds)
|
||||
$bus.on(SHOW_INPUT_BOX_RESPONSE, handleInputBoxValue)
|
||||
})
|
||||
export default class extends Vue {
|
||||
dragover = false
|
||||
progress = 0
|
||||
showProgress = false
|
||||
showError = false
|
||||
pasteStyle = ''
|
||||
picBed: IPicBedType[] = []
|
||||
picBedName = ''
|
||||
mounted () {
|
||||
ipcRenderer.on('uploadProgress', (event: IpcRendererEvent, progress: number) => {
|
||||
if (progress !== -1) {
|
||||
this.showProgress = true
|
||||
this.progress = progress
|
||||
} else {
|
||||
this.progress = 100
|
||||
this.showError = true
|
||||
}
|
||||
})
|
||||
this.getPasteStyle()
|
||||
this.getDefaultPicBed()
|
||||
ipcRenderer.on('syncPicBed', () => {
|
||||
this.getDefaultPicBed()
|
||||
})
|
||||
ipcRenderer.send(GET_PICBEDS)
|
||||
ipcRenderer.on(GET_PICBEDS, this.getPicBeds)
|
||||
this.$bus.$on(SHOW_INPUT_BOX_RESPONSE, this.handleInputBoxValue)
|
||||
}
|
||||
|
||||
@Watch('progress')
|
||||
onProgressChange (val: number) {
|
||||
if (val === 100) {
|
||||
setTimeout(() => {
|
||||
this.showProgress = false
|
||||
this.showError = false
|
||||
}, 1000)
|
||||
setTimeout(() => {
|
||||
this.progress = 0
|
||||
}, 1200)
|
||||
}
|
||||
}
|
||||
watch(progress, onProgressChange)
|
||||
|
||||
beforeDestroy () {
|
||||
this.$bus.$off(SHOW_INPUT_BOX_RESPONSE)
|
||||
ipcRenderer.removeAllListeners('uploadProgress')
|
||||
ipcRenderer.removeAllListeners('syncPicBed')
|
||||
ipcRenderer.removeListener(GET_PICBEDS, this.getPicBeds)
|
||||
function onProgressChange (val: number) {
|
||||
if (val === 100) {
|
||||
setTimeout(() => {
|
||||
showProgress.value = false
|
||||
showError.value = false
|
||||
}, 1000)
|
||||
setTimeout(() => {
|
||||
progress.value = 0
|
||||
}, 1200)
|
||||
}
|
||||
}
|
||||
|
||||
onDrop (e: DragEvent) {
|
||||
this.dragover = false
|
||||
const items = e.dataTransfer!.items
|
||||
if (items.length === 2 && items[0].type === 'text/uri-list') {
|
||||
this.handleURLDrag(items, e.dataTransfer!)
|
||||
} else if (items[0].type === 'text/plain') {
|
||||
const str = e.dataTransfer!.getData(items[0].type)
|
||||
if (isUrl(str)) {
|
||||
ipcRenderer.send('uploadChoosedFiles', [{ path: str }])
|
||||
} else {
|
||||
this.$message.error(this.$T('TIPS_DRAG_VALID_PICTURE_OR_URL'))
|
||||
}
|
||||
onBeforeUnmount(() => {
|
||||
$bus.off(SHOW_INPUT_BOX_RESPONSE)
|
||||
ipcRenderer.removeAllListeners('uploadProgress')
|
||||
ipcRenderer.removeAllListeners('syncPicBed')
|
||||
ipcRenderer.removeListener(GET_PICBEDS, getPicBeds)
|
||||
})
|
||||
|
||||
function onDrop (e: DragEvent) {
|
||||
dragover.value = false
|
||||
const items = e.dataTransfer!.items
|
||||
if (items.length === 2 && items[0].type === 'text/uri-list') {
|
||||
handleURLDrag(items, e.dataTransfer!)
|
||||
} else if (items[0].type === 'text/plain') {
|
||||
const str = e.dataTransfer!.getData(items[0].type)
|
||||
if (isUrl(str)) {
|
||||
sendToMain('uploadChoosedFiles', [{ path: str }])
|
||||
} else {
|
||||
this.ipcSendFiles(e.dataTransfer!.files)
|
||||
$message.error($T('TIPS_DRAG_VALID_PICTURE_OR_URL'))
|
||||
}
|
||||
} else {
|
||||
ipcSendFiles(e.dataTransfer!.files)
|
||||
}
|
||||
}
|
||||
|
||||
handleURLDrag (items: DataTransferItemList, dataTransfer: DataTransfer) {
|
||||
// text/html
|
||||
// Use this data to get a more precise URL
|
||||
const urlString = dataTransfer.getData(items[1].type)
|
||||
const urlMatch = urlString.match(/<img.*src="(.*?)"/)
|
||||
if (urlMatch) {
|
||||
ipcRenderer.send('uploadChoosedFiles', [
|
||||
{
|
||||
path: urlMatch[1]
|
||||
}
|
||||
])
|
||||
} else {
|
||||
this.$message.error(this.$T('TIPS_DRAG_VALID_PICTURE_OR_URL'))
|
||||
}
|
||||
}
|
||||
|
||||
openUplodWindow () {
|
||||
document.getElementById('file-uploader')!.click()
|
||||
}
|
||||
|
||||
onChange (e: any) {
|
||||
this.ipcSendFiles(e.target.files);
|
||||
(document.getElementById('file-uploader') as HTMLInputElement).value = ''
|
||||
}
|
||||
|
||||
ipcSendFiles (files: FileList) {
|
||||
const sendFiles: IFileWithPath[] = []
|
||||
Array.from(files).forEach((item) => {
|
||||
const obj = {
|
||||
name: item.name,
|
||||
path: item.path
|
||||
function handleURLDrag (items: DataTransferItemList, dataTransfer: DataTransfer) {
|
||||
// text/html
|
||||
// Use this data to get a more precise URL
|
||||
const urlString = dataTransfer.getData(items[1].type)
|
||||
const urlMatch = urlString.match(/<img.*src="(.*?)"/)
|
||||
if (urlMatch) {
|
||||
sendToMain('uploadChoosedFiles', [
|
||||
{
|
||||
path: urlMatch[1]
|
||||
}
|
||||
sendFiles.push(obj)
|
||||
})
|
||||
ipcRenderer.send('uploadChoosedFiles', sendFiles)
|
||||
])
|
||||
} else {
|
||||
$message.error($T('TIPS_DRAG_VALID_PICTURE_OR_URL'))
|
||||
}
|
||||
}
|
||||
|
||||
async getPasteStyle () {
|
||||
this.pasteStyle = await this.getConfig('settings.pasteStyle') || 'markdown'
|
||||
}
|
||||
function openUplodWindow () {
|
||||
document.getElementById('file-uploader')!.click()
|
||||
}
|
||||
|
||||
handlePasteStyleChange (val: string) {
|
||||
this.saveConfig({
|
||||
'settings.pasteStyle': val
|
||||
})
|
||||
}
|
||||
function onChange (e: any) {
|
||||
ipcSendFiles(e.target.files);
|
||||
(document.getElementById('file-uploader') as HTMLInputElement).value = ''
|
||||
}
|
||||
|
||||
uploadClipboardFiles () {
|
||||
ipcRenderer.send('uploadClipboardFilesFromUploadPage')
|
||||
}
|
||||
|
||||
async uploadURLFiles () {
|
||||
const str = await navigator.clipboard.readText()
|
||||
this.$bus.$emit(SHOW_INPUT_BOX, {
|
||||
value: isUrl(str) ? str : '',
|
||||
title: this.$T('TIPS_INPUT_URL'),
|
||||
placeholder: this.$T('TIPS_HTTP_PREFIX')
|
||||
})
|
||||
}
|
||||
|
||||
handleInputBoxValue (val: string) {
|
||||
if (val === '') return false
|
||||
if (isUrl(val)) {
|
||||
ipcRenderer.send('uploadChoosedFiles', [{
|
||||
path: val
|
||||
}])
|
||||
} else {
|
||||
this.$message.error(this.$T('TIPS_INPUT_VALID_URL'))
|
||||
function ipcSendFiles (files: FileList) {
|
||||
const sendFiles: IFileWithPath[] = []
|
||||
Array.from(files).forEach((item) => {
|
||||
const obj = {
|
||||
name: item.name,
|
||||
path: item.path
|
||||
}
|
||||
}
|
||||
sendFiles.push(obj)
|
||||
})
|
||||
sendToMain('uploadChoosedFiles', sendFiles)
|
||||
}
|
||||
|
||||
async getDefaultPicBed () {
|
||||
const currentPicBed = await this.getConfig<string>('picBed.current')
|
||||
this.picBed.forEach(item => {
|
||||
if (item.type === currentPicBed) {
|
||||
this.picBedName = item.name
|
||||
}
|
||||
})
|
||||
}
|
||||
async function getPasteStyle () {
|
||||
pasteStyle.value = await getConfig('settings.pasteStyle') || 'markdown'
|
||||
}
|
||||
|
||||
getPicBeds (event: Event, picBeds: IPicBedType[]) {
|
||||
this.picBed = picBeds
|
||||
this.getDefaultPicBed()
|
||||
}
|
||||
function handlePasteStyleChange (val: string | number | boolean) {
|
||||
saveConfig({
|
||||
'settings.pasteStyle': val
|
||||
})
|
||||
}
|
||||
|
||||
async handleChangePicBed () {
|
||||
ipcRenderer.send(SHOW_UPLOAD_PAGE_MENU)
|
||||
function uploadClipboardFiles () {
|
||||
sendToMain('uploadClipboardFilesFromUploadPage')
|
||||
}
|
||||
|
||||
async function uploadURLFiles () {
|
||||
const str = await navigator.clipboard.readText()
|
||||
$bus.emit(SHOW_INPUT_BOX, {
|
||||
value: isUrl(str) ? str : '',
|
||||
title: $T('TIPS_INPUT_URL'),
|
||||
placeholder: $T('TIPS_HTTP_PREFIX')
|
||||
})
|
||||
}
|
||||
|
||||
function handleInputBoxValue (val: string) {
|
||||
if (val === '') return
|
||||
if (isUrl(val)) {
|
||||
sendToMain('uploadChoosedFiles', [{
|
||||
path: val
|
||||
}])
|
||||
} else {
|
||||
$message.error($T('TIPS_INPUT_VALID_URL'))
|
||||
}
|
||||
}
|
||||
|
||||
async function getDefaultPicBed () {
|
||||
const currentPicBed = await getConfig<string>('picBed.current')
|
||||
picBed.value.forEach(item => {
|
||||
if (item.type === currentPicBed) {
|
||||
picBedName.value = item.name
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function getPicBeds (event: Event, picBeds: IPicBedType[]) {
|
||||
picBed.value = picBeds
|
||||
getDefaultPicBed()
|
||||
}
|
||||
|
||||
async function handleChangePicBed () {
|
||||
sendToMain(SHOW_UPLOAD_PAGE_MENU)
|
||||
}
|
||||
</script>
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'UploadPage'
|
||||
}
|
||||
</script>
|
||||
<style lang='stylus'>
|
||||
.view-title
|
||||
display flex
|
||||
color #eee
|
||||
font-size 20px
|
||||
text-align center
|
||||
margin 10px auto
|
||||
align-items center
|
||||
justify-content center
|
||||
#upload-view
|
||||
.view-title
|
||||
margin 20px auto
|
||||
@@ -275,6 +327,8 @@ export default class extends Vue {
|
||||
.paste-style
|
||||
text-align center
|
||||
margin-top 16px
|
||||
display flex
|
||||
align-items flex-end
|
||||
&__text
|
||||
font-size 12px
|
||||
color #eeeeee
|
||||
|
||||
@@ -3,11 +3,17 @@
|
||||
<div class="view-title">
|
||||
{{ $T('SETTINGS') }}
|
||||
</div>
|
||||
<el-row :gutter="15" justify="space-between" align="center" type="flex" class="config-list">
|
||||
<el-row
|
||||
:gutter="15"
|
||||
justify="space-between"
|
||||
align="middle"
|
||||
type="flex"
|
||||
class="config-list"
|
||||
>
|
||||
<el-col
|
||||
class="config-item-col"
|
||||
v-for="item in curConfigList"
|
||||
:key="item._id"
|
||||
class="config-item-col"
|
||||
:span="11"
|
||||
:offset="1"
|
||||
>
|
||||
@@ -15,12 +21,32 @@
|
||||
:class="`config-item ${defaultConfigId === item._id ? 'selected' : ''}`"
|
||||
@click="() => selectItem(item._id)"
|
||||
>
|
||||
<div class="config-name">{{item._configName}}</div>
|
||||
<div class="config-update-time">{{formatTime(item._updatedAt)}}</div>
|
||||
<div v-if="defaultConfigId === item._id" class="default-text">{{$T('SELECTED_SETTING_HINT')}}</div>
|
||||
<div class="config-name">
|
||||
{{ item._configName }}
|
||||
</div>
|
||||
<div class="config-update-time">
|
||||
{{ formatTime(item._updatedAt) }}
|
||||
</div>
|
||||
<div
|
||||
v-if="defaultConfigId === item._id"
|
||||
class="default-text"
|
||||
>
|
||||
{{ $T('SELECTED_SETTING_HINT') }}
|
||||
</div>
|
||||
<div class="operation-container">
|
||||
<i class="el-icon-edit" @click="openEditPage(item._id)"></i>
|
||||
<i :class="`el-icon-delete ${curConfigList.length <= 1 ? 'disabled' : ''}`" @click.stop="() => deleteConfig(item._id)"></i>
|
||||
<el-icon
|
||||
class="el-icon-edit"
|
||||
@click="openEditPage(item._id)"
|
||||
>
|
||||
<Edit />
|
||||
</el-icon>
|
||||
<el-icon
|
||||
class="el-icon-delete"
|
||||
:class="curConfigList.length <= 1 ? 'disabled' : ''"
|
||||
@click.stop="() => deleteConfig(item._id)"
|
||||
>
|
||||
<Delete />
|
||||
</el-icon>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
@@ -33,96 +59,132 @@
|
||||
class="config-item config-item-add"
|
||||
@click="addNewConfig"
|
||||
>
|
||||
<i class="el-icon-plus"></i>
|
||||
<el-icon
|
||||
class="el-icon-plus"
|
||||
>
|
||||
<Plus />
|
||||
</el-icon>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row type="flex" justify="center" :span="24" class="set-default-container">
|
||||
<el-button class="set-default-btn" type="success" @click="setDefaultPicBed(type)" round :disabled="defaultPicBed === type">{{ $T('SETTINGS_SET_DEFAULT_PICBED') }}</el-button>
|
||||
<el-row
|
||||
type="flex"
|
||||
justify="center"
|
||||
:span="24"
|
||||
class="set-default-container"
|
||||
>
|
||||
<el-button
|
||||
class="set-default-btn"
|
||||
type="success"
|
||||
round
|
||||
:disabled="store?.state.defaultPicBed === type"
|
||||
@click="setDefaultPicBed(type)"
|
||||
>
|
||||
{{ $T('SETTINGS_SET_DEFAULT_PICBED') }}
|
||||
</el-button>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from 'vue-property-decorator'
|
||||
<script lang="ts" setup>
|
||||
import { Edit, Delete, Plus } from '@element-plus/icons-vue'
|
||||
import { saveConfig, triggerRPC } from '@/utils/dataSender'
|
||||
import dayjs from 'dayjs'
|
||||
import mixin from '@/utils/ConfirmButtonMixin'
|
||||
import { IRPCActionType } from '~/universal/types/enum'
|
||||
import { T as $T } from '@/i18n/index'
|
||||
import { useRouter, useRoute, onBeforeRouteUpdate } from 'vue-router'
|
||||
import { onBeforeMount, ref } from 'vue'
|
||||
import { PICBEDS_PAGE, UPLOADER_CONFIG_PAGE } from '@/router/config'
|
||||
import { useStore } from '@/hooks/useStore'
|
||||
const $router = useRouter()
|
||||
const $route = useRoute()
|
||||
|
||||
@Component({
|
||||
name: 'UploaderConfigPage',
|
||||
mixins: [mixin]
|
||||
const type = ref('')
|
||||
const curConfigList = ref<IStringKeyMap[]>([])
|
||||
const defaultConfigId = ref('')
|
||||
const store = useStore()
|
||||
|
||||
async function selectItem (id: string) {
|
||||
await triggerRPC<void>(IRPCActionType.SELECT_UPLOADER, type.value, id)
|
||||
defaultConfigId.value = id
|
||||
}
|
||||
|
||||
onBeforeRouteUpdate((to, from, next) => {
|
||||
if (to.params.type && (to.name === UPLOADER_CONFIG_PAGE)) {
|
||||
type.value = to.params.type as string
|
||||
getCurrentConfigList()
|
||||
console.log(type.value)
|
||||
}
|
||||
next()
|
||||
})
|
||||
export default class extends Vue {
|
||||
type!: string;
|
||||
curConfigList: IStringKeyMap[] = [];
|
||||
defaultConfigId = '';
|
||||
|
||||
async selectItem (id: string) {
|
||||
await this.triggerRPC<void>(IRPCActionType.SELECT_UPLOADER, this.type, id)
|
||||
this.defaultConfigId = id
|
||||
}
|
||||
onBeforeMount(() => {
|
||||
type.value = $route.params.type as string
|
||||
console.log(type.value)
|
||||
getCurrentConfigList()
|
||||
})
|
||||
|
||||
created () {
|
||||
this.type = this.$route.params.type
|
||||
this.getCurrentConfigList()
|
||||
}
|
||||
async function getCurrentConfigList () {
|
||||
const configList = await triggerRPC<IUploaderConfigItem>(IRPCActionType.GET_PICBED_CONFIG_LIST, type.value)
|
||||
console.log(configList)
|
||||
curConfigList.value = configList?.configList ?? []
|
||||
defaultConfigId.value = configList?.defaultId ?? ''
|
||||
}
|
||||
|
||||
async getCurrentConfigList () {
|
||||
const configList = await this.triggerRPC<IUploaderConfigItem>(IRPCActionType.GET_PICBED_CONFIG_LIST, this.type)
|
||||
this.curConfigList = configList?.configList ?? []
|
||||
this.defaultConfigId = configList?.defaultId ?? ''
|
||||
}
|
||||
|
||||
openEditPage (configId: string) {
|
||||
this.$router.push({
|
||||
name: 'picbeds',
|
||||
params: {
|
||||
type: this.type,
|
||||
configId
|
||||
},
|
||||
query: {
|
||||
defaultConfigId: this.defaultConfigId
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
formatTime (time: number):string {
|
||||
return dayjs(time).format('YYYY-MM-DD HH:mm:ss')
|
||||
}
|
||||
|
||||
async deleteConfig (id: string) {
|
||||
const res = await this.triggerRPC<IUploaderConfigItem | undefined>(IRPCActionType.DELETE_PICBED_CONFIG, this.type, id)
|
||||
if (!res) return
|
||||
this.curConfigList = res.configList
|
||||
this.defaultConfigId = res.defaultId
|
||||
}
|
||||
|
||||
addNewConfig () {
|
||||
this.$router.push({
|
||||
name: 'picbeds',
|
||||
params: {
|
||||
type: this.type,
|
||||
configId: ''
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
setDefaultPicBed (type: string) {
|
||||
this.saveConfig({
|
||||
'picBed.current': type,
|
||||
'picBed.uploader': type
|
||||
})
|
||||
// @ts-ignore 来自mixin的数据
|
||||
this.defaultPicBed = type
|
||||
const successNotification = new Notification(this.$T('SETTINGS_DEFAULT_PICBED'), {
|
||||
body: this.$T('TIPS_SET_SUCCEED')
|
||||
})
|
||||
successNotification.onclick = () => {
|
||||
return true
|
||||
function openEditPage (configId: string) {
|
||||
console.log(configId, type.value, defaultConfigId.value)
|
||||
$router.push({
|
||||
name: PICBEDS_PAGE,
|
||||
params: {
|
||||
type: type.value,
|
||||
configId
|
||||
},
|
||||
query: {
|
||||
defaultConfigId: defaultConfigId.value
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function formatTime (time: number): string {
|
||||
return dayjs(time).format('YYYY-MM-DD HH:mm:ss')
|
||||
}
|
||||
|
||||
async function deleteConfig (id: string) {
|
||||
const res = await triggerRPC<IUploaderConfigItem | undefined>(IRPCActionType.DELETE_PICBED_CONFIG, type.value, id)
|
||||
if (!res) return
|
||||
curConfigList.value = res.configList
|
||||
defaultConfigId.value = res.defaultId
|
||||
}
|
||||
|
||||
function addNewConfig () {
|
||||
$router.push({
|
||||
name: PICBEDS_PAGE,
|
||||
params: {
|
||||
type: type.value,
|
||||
configId: ''
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function setDefaultPicBed (type: string) {
|
||||
saveConfig({
|
||||
'picBed.current': type,
|
||||
'picBed.uploader': type
|
||||
})
|
||||
|
||||
store?.setDefaultPicBed(type)
|
||||
const successNotification = new Notification($T('SETTINGS_DEFAULT_PICBED'), {
|
||||
body: $T('TIPS_SET_SUCCEED')
|
||||
})
|
||||
successNotification.onclick = () => {
|
||||
return true
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'UploaderConfigPage'
|
||||
}
|
||||
</script>
|
||||
<style lang='stylus'>
|
||||
#config-list-view
|
||||
position relative
|
||||
|
||||
@@ -1,104 +1,104 @@
|
||||
<template>
|
||||
<div id="others-view">
|
||||
<el-row :gutter="20" class="setting-list">
|
||||
<el-col :span="20" :offset="2">
|
||||
<div id="picbeds-page">
|
||||
<el-row
|
||||
:gutter="20"
|
||||
class="setting-list"
|
||||
>
|
||||
<el-col
|
||||
:span="20"
|
||||
:offset="2"
|
||||
>
|
||||
<div class="view-title">
|
||||
{{ picBedName }} {{ $T('SETTINGS') }}
|
||||
</div>
|
||||
<config-form
|
||||
v-if="config.length > 0"
|
||||
:id="type"
|
||||
ref="$configForm"
|
||||
:config="config"
|
||||
type="uploader"
|
||||
ref="configForm"
|
||||
:id="type"
|
||||
>
|
||||
<el-form-item>
|
||||
<el-button class="confirm-btn" type="primary" @click="handleConfirm" round>{{ $T('CONFIRM') }}</el-button>
|
||||
<el-button
|
||||
class="confirm-btn"
|
||||
type="primary"
|
||||
round
|
||||
@click="handleConfirm"
|
||||
>
|
||||
{{ $T('CONFIRM') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</config-form>
|
||||
<div v-else class="single">
|
||||
<div class="notice">{{ $T('SETTINGS_NOT_CONFIG_OPTIONS') }}</div>
|
||||
<div
|
||||
v-else
|
||||
class="single"
|
||||
>
|
||||
<div class="notice">
|
||||
{{ $T('SETTINGS_NOT_CONFIG_OPTIONS') }}
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from 'vue-property-decorator'
|
||||
<script lang="ts" setup>
|
||||
import { IRPCActionType } from '~/universal/types/enum'
|
||||
import { ref, onBeforeUnmount, onBeforeMount } from 'vue'
|
||||
import { T as $T } from '@/i18n/index'
|
||||
import { sendToMain, triggerRPC } from '@/utils/dataSender'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import ConfigForm from '@/components/ConfigForm.vue'
|
||||
import mixin from '@/utils/ConfirmButtonMixin'
|
||||
// import mixin from '@/utils/ConfirmButtonMixin'
|
||||
import {
|
||||
ipcRenderer,
|
||||
IpcRendererEvent
|
||||
} from 'electron'
|
||||
import { IRPCActionType } from '~/universal/types/enum'
|
||||
const type = ref('')
|
||||
const config = ref<IPicGoPluginConfig[]>([])
|
||||
const picBedName = ref('')
|
||||
const $route = useRoute()
|
||||
const $router = useRouter()
|
||||
const $configForm = ref<InstanceType<typeof ConfigForm> | null>(null)
|
||||
type.value = $route.params.type as string
|
||||
console.log('picbed type', $route.params.type)
|
||||
|
||||
@Component({
|
||||
name: 'OtherPicBed',
|
||||
mixins: [mixin],
|
||||
components: {
|
||||
ConfigForm
|
||||
}
|
||||
onBeforeMount(() => {
|
||||
sendToMain('getPicBedConfig', $route.params.type)
|
||||
ipcRenderer.on('getPicBedConfig', getPicBeds)
|
||||
})
|
||||
export default class extends Vue {
|
||||
type: string = ''
|
||||
config: any[] = []
|
||||
picBedName: string = ''
|
||||
created () {
|
||||
this.type = this.$route.params.type
|
||||
ipcRenderer.send('getPicBedConfig', this.$route.params.type)
|
||||
ipcRenderer.on('getPicBedConfig', this.getPicBeds)
|
||||
}
|
||||
|
||||
async handleConfirm () {
|
||||
// @ts-ignore
|
||||
const result = await this.$refs.configForm.validate()
|
||||
if (result !== false) {
|
||||
await this.triggerRPC<void>(IRPCActionType.UPDATE_UPLOADER_CONFIG, this.type, result?._id, result)
|
||||
const successNotification = new Notification(this.$T('SETTINGS_RESULT'), {
|
||||
body: this.$T('TIPS_SET_SUCCEED')
|
||||
})
|
||||
successNotification.onclick = () => {
|
||||
return true
|
||||
}
|
||||
this.$router.back()
|
||||
}
|
||||
}
|
||||
|
||||
shouldUpdateDefaultConfig (item: IStringKeyMap) {
|
||||
const curDefaultConfigId = this.$route.query.defaultConfigId
|
||||
if (item._id === curDefaultConfigId) {
|
||||
this.saveConfig(`picBed.${this.type}`, item)
|
||||
}
|
||||
}
|
||||
|
||||
setDefaultPicBed (type: string) {
|
||||
this.saveConfig({
|
||||
'picBed.current': type,
|
||||
'picBed.uploader': type
|
||||
})
|
||||
// @ts-ignore 来自mixin的数据
|
||||
this.defaultPicBed = type
|
||||
const successNotification = new Notification(this.$T('SETTINGS_DEFAULT_PICBED'), {
|
||||
body: this.$T('TIPS_SET_SUCCEED')
|
||||
const handleConfirm = async () => {
|
||||
const result = (await $configForm.value?.validate()) || false
|
||||
console.log(result)
|
||||
if (result !== false) {
|
||||
await triggerRPC<void>(IRPCActionType.UPDATE_UPLOADER_CONFIG, type.value, result?._id, result)
|
||||
const successNotification = new Notification($T('SETTINGS_RESULT'), {
|
||||
body: $T('TIPS_SET_SUCCEED')
|
||||
})
|
||||
successNotification.onclick = () => {
|
||||
return true
|
||||
}
|
||||
$router.back()
|
||||
}
|
||||
}
|
||||
|
||||
getPicBeds (event: IpcRendererEvent, config: any[], name: string) {
|
||||
this.config = config
|
||||
this.picBedName = name
|
||||
}
|
||||
function getPicBeds (event: IpcRendererEvent, _config: IPicGoPluginConfig[], name: string) {
|
||||
config.value = _config
|
||||
picBedName.value = name
|
||||
}
|
||||
|
||||
beforeDestroy () {
|
||||
ipcRenderer.removeListener('getPicBedConfig', this.getPicBeds)
|
||||
}
|
||||
onBeforeUnmount(() => {
|
||||
ipcRenderer.removeListener('getPicBedConfig', getPicBeds)
|
||||
})
|
||||
|
||||
</script>
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'PicbedsPage'
|
||||
}
|
||||
</script>
|
||||
<style lang='stylus'>
|
||||
#others-view
|
||||
#picbeds-page
|
||||
.setting-list
|
||||
height 425px
|
||||
overflow-y auto
|
||||
@@ -111,13 +111,11 @@ export default class extends Vue {
|
||||
padding-bottom 0
|
||||
color #eee
|
||||
&-item
|
||||
margin-bottom 11px
|
||||
margin-bottom 16px
|
||||
.el-button-group
|
||||
width 100%
|
||||
.el-button
|
||||
width 50%
|
||||
.el-input__inner
|
||||
border-radius 19px
|
||||
.el-radio-group
|
||||
margin-left 25px
|
||||
.el-switch__label
|
||||
|
||||
Reference in New Issue
Block a user