🎨 Style(custom): format with prettier

This commit is contained in:
Kuingsmile
2024-06-15 19:37:50 +08:00
parent 096f564c31
commit 5af8a6b529
157 changed files with 21365 additions and 22952 deletions

View File

@@ -5,7 +5,7 @@
allowpopups
autosize="on"
scrollbars="none"
style="width: 100%; height: 100%;"
style="width: 100%; height: 100%"
/>
</template>
@@ -20,14 +20,13 @@ import { configPaths } from '#/utils/configPaths'
const srcUrl = ref('https://piclist.cn/app.html')
const updateUrl = async () => {
const lang = await getConfig(configPaths.settings.language) || II18nLanguage.ZH_CN
const lang = (await getConfig(configPaths.settings.language)) || II18nLanguage.ZH_CN
srcUrl.value = lang === II18nLanguage.ZH_CN ? 'https://piclist.cn/app.html' : 'https://piclist.cn/en/app.html'
}
onMounted(() => {
updateUrl()
})
</script>
<script lang="ts">

View File

@@ -1,21 +1,12 @@
<template>
<div
id="gallery-view"
:style="handleBarActive? 'height: 85%;': 'height: 95%;'"
>
<div id="gallery-view" :style="handleBarActive ? 'height: 85%;' : 'height: 95%;'">
<div class="view-title">
{{ $T('GALLERY') }} - {{ filterList.length }}
<el-icon
style="margin-left: 4px"
class="cursor-pointer"
@click="toggleHandleBar"
>
<el-icon style="margin-left: 4px" class="cursor-pointer" @click="toggleHandleBar">
<CaretBottom v-show="!handleBarActive" />
<CaretTop v-show="handleBarActive" />
</el-icon>
<span
style="position: absolute; right: 0; top: 0; margin-right: 20px; font-size: 0.8em; color: #fff;"
>
<span style="position: absolute; right: 0; top: 0; margin-right: 20px; font-size: 0.8em; color: #fff">
{{ $T('GALLERY_SYNC_DELETE') }}
<el-switch
v-model="deleteCloud"
@@ -23,11 +14,7 @@
:inactive-text="$T('SETTINGS_CLOSE')"
@change="handleDeleteCloudFile"
/>
<el-button
type="primary"
:link="true"
@click="refreshPage"
>
<el-button type="primary" :link="true" @click="refreshPage">
<el-tooltip
class="item"
effect="dark"
@@ -36,10 +23,7 @@
:persistent="false"
teleported
>
<el-icon
size="25"
style="cursor: pointer; margin-left: 10px;"
>
<el-icon size="25" style="cursor: pointer; margin-left: 10px">
<Refresh />
</el-icon>
</el-tooltip>
@@ -48,14 +32,8 @@
</div>
<transition name="el-zoom-in-top">
<el-row v-show="handleBarActive">
<el-col
:span="22"
:offset="1"
>
<el-row
class="handle-bar"
:gutter="16"
>
<el-col :span="22" :offset="1">
<el-row class="handle-bar" :gutter="16">
<el-col :span="5">
<el-select
v-model="choosedPicBed"
@@ -67,12 +45,7 @@
:persistent="false"
teleported
>
<el-option
v-for="item in picBedGlobal"
:key="item.type"
:label="item.name"
:value="item.type"
/>
<el-option v-for="item in picBedGlobal" :key="item.type" :label="item.name" :value="item.type" />
</el-select>
</el-col>
<el-col :span="10">
@@ -88,11 +61,7 @@
/>
</el-col>
<el-col :span="1">
<el-divider
direction="vertical"
style="height: 100%;"
border-style="hidden"
/>
<el-divider direction="vertical" style="height: 100%" border-style="hidden" />
</el-col>
<el-col :span="3">
<el-select
@@ -104,12 +73,7 @@
teleported
@change="handlePasteStyleChange"
>
<el-option
v-for="(value, key) in pasteStyleMap"
:key="key"
:label="key"
:value="value"
/>
<el-option v-for="(value, key) in pasteStyleMap" :key="key" :label="key" :value="value" />
</el-select>
</el-col>
<el-col :span="3">
@@ -122,23 +86,12 @@
teleported
@change="handleUseShortUrlChange"
>
<el-option
v-for="(value, key) in shortURLMap"
:key="key"
:label="key"
:value="value"
/>
<el-option v-for="(value, key) in shortURLMap" :key="key" :label="key" :value="value" />
</el-select>
</el-col>
<el-col :span="2">
<el-dropdown
teleported
>
<el-button
size="small"
type="primary"
:icon="Sort"
>
<el-dropdown teleported>
<el-button size="small" type="primary" :icon="Sort">
{{ $T('MANAGE_BUCKET_SORT_TITLE') }}
</el-button>
<template #dropdown>
@@ -158,57 +111,30 @@
</el-dropdown>
</el-col>
</el-row>
<el-row
class="handle-bar"
:gutter="16"
>
<el-row class="handle-bar" :gutter="16">
<el-col :span="5">
<el-input
v-model="searchText"
:placeholder="$T('GALLERY_SEARCH_FILENAME')"
size="small"
>
<el-input v-model="searchText" :placeholder="$T('GALLERY_SEARCH_FILENAME')" size="small">
<template #suffix>
<el-icon
class="el-input__icon"
style="cursor: pointer;"
@click="cleanSearch"
>
<el-icon class="el-input__icon" style="cursor: pointer" @click="cleanSearch">
<close />
</el-icon>
</template>
</el-input>
</el-col>
<el-col :span="6">
<el-input
v-model="searchTextURL"
:placeholder="$T('GALLERY_SEARCH_URL')"
size="small"
>
<el-input v-model="searchTextURL" :placeholder="$T('GALLERY_SEARCH_URL')" size="small">
<template #suffix>
<el-icon
class="el-input__icon"
style="cursor: pointer;"
@click="cleanSearchUrl"
>
<el-icon class="el-input__icon" style="cursor: pointer" @click="cleanSearchUrl">
<close />
</el-icon>
</template>
</el-input>
</el-col>
<el-col :span="1">
<el-divider
direction="vertical"
style="height: 100%;"
border-style="hidden"
/>
<el-divider direction="vertical" style="height: 100%" border-style="hidden" />
</el-col>
<el-col :span="3">
<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>
@@ -216,41 +142,27 @@
<div
class="item-base all-pick round"
:class="{ active: filterList.length > 0 }"
@click="() => isShowBatchRenameDialog = true"
@click="() => (isShowBatchRenameDialog = true)"
>
{{ $T('GALLERY_CHANGE_URL') }}
</div>
</el-col>
<el-col :span="3">
<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="3">
<div
class="item-base all-pick round"
:class="{ active: filterList.length > 0 }"
@click="toggleSelectAll"
>
{{ isAllSelected? $T('CANCEL'): $T('SELECT_ALL') }}
<div class="item-base all-pick round" :class="{ active: filterList.length > 0 }" @click="toggleSelectAll">
{{ isAllSelected ? $T('CANCEL') : $T('SELECT_ALL') }}
</div>
</el-col>
</el-row>
</el-col>
</el-row>
</transition>
<el-row
class="gallery-list"
:class="{ small: handleBarActive }"
>
<el-col
:span="22"
:offset="1"
>
<el-row class="gallery-list" :class="{ small: handleBarActive }">
<el-col :span="22" :offset="1">
<el-row :gutter="16">
<photo-slider
:items="filterList"
@@ -271,43 +183,21 @@
:xl="2"
class="gallery-list__img"
>
<div
class="gallery-list__item"
@click="zoomImage(index)"
>
<img
v-lazy="item.galleryPath || item.imgUrl"
class="gallery-list__item-img"
>
<div class="gallery-list__item" @click="zoomImage(index)">
<img v-lazy="item.galleryPath || 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">
{{ formatFileName(item.fileName || '') }}
</div>
<el-row
class="gallery-list__tool-panel"
justify="space-between"
align="middle"
>
<el-row class="gallery-list__tool-panel" justify="space-between" align="middle">
<el-row>
<el-icon
class="cursor-pointer document"
@click="copy(item)"
>
<el-icon class="cursor-pointer document" @click="copy(item)">
<Document />
</el-icon>
<el-icon
class="cursor-pointer edit"
@click="openDialog(item)"
>
<el-icon class="cursor-pointer edit" @click="openDialog(item)">
<Edit />
</el-icon>
<el-icon
class="cursor-pointer delete"
@click="remove(item)"
>
<el-icon class="cursor-pointer delete" @click="remove(item)">
<Delete />
</el-icon>
</el-row>
@@ -332,10 +222,7 @@
<el-button @click="dialogVisible = false">
{{ $T('CANCEL') }}
</el-button>
<el-button
type="primary"
@click="confirmModify"
>
<el-button type="primary" @click="confirmModify">
{{ $T('CONFIRM') }}
</el-button>
</template>
@@ -349,10 +236,7 @@
destroy-on-close
append-to-body
>
<el-link
:underline="false"
style="margin-bottom: 10px;"
>
<el-link :underline="false" style="margin-bottom: 10px">
<span>
{{ $T('MANAGE_BUCKET_RENAME_FILE_INPUT_A') + $T('GALLERY_MATCHED') + mathcedCount + ' ' }}
<el-tooltip
@@ -362,9 +246,7 @@
:persistent="false"
teleported
>
<el-icon
color="#409EFF"
>
<el-icon color="#409EFF">
<InfoFilled />
</el-icon>
</el-tooltip>
@@ -375,31 +257,16 @@
:placeholder="$T('MANAGE_BUCKET_RENAME_FILE_INPUT_A_PLACEHOLDER')"
clearable
/>
<el-link
:underline="false"
style="margin-bottom: 10px;margin-top: 10px;"
>
<el-link :underline="false" style="margin-bottom: 10px; margin-top: 10px">
<span>
{{ $T('MANAGE_BUCKET_RENAME_FILE_INPUT_B') }}
<el-popover
effect="light"
placement="right"
width="280"
:persistent="false"
teleported
>
<el-popover effect="light" placement="right" width="280" :persistent="false" teleported>
<template #reference>
<el-icon
color="#409EFF"
>
<el-icon color="#409EFF">
<InfoFilled />
</el-icon>
</template>
<el-descriptions
:column="1"
style="width: 250px;"
border
>
<el-descriptions :column="1" style="width: 250px" border>
<el-descriptions-item
v-for="(item, index) in customRenameFormatTable"
:key="index"
@@ -410,7 +277,7 @@
{{ item.description }}
</el-descriptions-item>
<el-descriptions-item
v-for="(item, index) in customRenameFormatTable.slice(0, customRenameFormatTable.length-1)"
v-for="(item, index) in customRenameFormatTable.slice(0, customRenameFormatTable.length - 1)"
:key="index"
:label="item.placeholderB"
align="center"
@@ -418,40 +285,29 @@
>
{{ item.descriptionB }}
</el-descriptions-item>
<el-descriptions-item
label="{auto}"
align="center"
label-style="width: 100px;"
>
<el-descriptions-item label="{auto}" align="center" label-style="width: 100px;">
{{ $T('MANAGE_BUCKET_RENAME_FILE_TABLE_IID') }}
</el-descriptions-item>
</el-descriptions>
</el-popover>
</span>
</el-link>
<el-input
v-model="batchRenameReplace"
placeholder="Ex. {Y}-{m}-{uuid}"
clearable
/>
<div
style="margin-top: 10px;align-items: center;display: flex;justify-content: flex-end;"
>
<el-input v-model="batchRenameReplace" placeholder="Ex. {Y}-{m}-{uuid}" clearable />
<div style="margin-top: 10px; align-items: center; display: flex; justify-content: flex-end">
<el-button
type="danger"
style="margin-right: 30px;"
style="margin-right: 30px"
plain
:icon="Close"
@click="() => {isShowBatchRenameDialog = false}"
@click="
() => {
isShowBatchRenameDialog = false
}
"
>
{{ $T('MANAGE_BUCKET_RENAME_FILE_CANCEL') }}
</el-button>
<el-button
type="primary"
plain
:icon="Edit"
@click="handleBatchRename()"
>
<el-button type="primary" plain :icon="Edit" @click="handleBatchRename()">
{{ $T('MANAGE_BUCKET_RENAME_FILE_CONFIRM') }}
</el-button>
</div>
@@ -460,12 +316,19 @@
</template>
<script lang="ts" setup>
import {
ipcRenderer,
clipboard
} from 'electron'
import { ipcRenderer, clipboard } from 'electron'
import { CheckboxValueType, ElMessageBox, ElNotification, ElMessage } from 'element-plus'
import { InfoFilled, Close, CaretBottom, Document, Edit, Delete, CaretTop, Sort, Refresh } from '@element-plus/icons-vue'
import {
InfoFilled,
Close,
CaretBottom,
Document,
Edit,
Delete,
CaretTop,
Sort,
Refresh
} from '@element-plus/icons-vue'
import path from 'path'
import { computed, nextTick, onActivated, onBeforeUnmount, onBeforeMount, reactive, ref, watch } from 'vue'
import { onBeforeRouteUpdate } from 'vue-router'
@@ -538,8 +401,8 @@ onBeforeRouteUpdate((to, from) => {
})
// init deleteCloud
async function initDeleteCloud () {
const config = await getConfig() as any
async function initDeleteCloud() {
const config = (await getConfig()) as any
deleteCloud.value = config.settings.deleteCloudFile || false
}
@@ -555,7 +418,7 @@ onBeforeMount(async () => {
document.addEventListener('keyup', handleDetectShiftKey)
})
function handleDetectShiftKey (event: KeyboardEvent) {
function handleDetectShiftKey(event: KeyboardEvent) {
if (event.key === 'Shift') {
if (event.type === 'keydown') {
isShiftKeyPress.value = true
@@ -580,11 +443,11 @@ const isAllSelected = computed(() => {
}
})
function formatFileName (name: string) {
function formatFileName(name: string) {
return path.basename(name)
}
function getGallery (): IGalleryItem[] {
function getGallery(): IGalleryItem[] {
if (searchText.value || choosedPicBed.value.length > 0 || searchTextURL.value || dateRange.value) {
return images.value
.filter(item => {
@@ -607,11 +470,12 @@ function getGallery (): IGalleryItem[] {
isIncludesDateRange = date >= new Date(start).getTime() && date <= new Date(end).getTime() + 86400000
}
return isIncludesSearchText && isInChoosedPicBed && isIncludesSearchTextURL && isIncludesDateRange
}).map(item => {
})
.map(item => {
return {
...item,
src: item.imgUrl || '',
key: (item.id || `${Date.now()}`),
key: item.id || `${Date.now()}`,
intro: item.fileName || ''
}
})
@@ -620,22 +484,25 @@ function getGallery (): IGalleryItem[] {
return {
...item,
src: item.imgUrl || '',
key: (item.id || `${Date.now()}`),
key: item.id || `${Date.now()}`,
intro: item.fileName || ''
}
})
}
}
async function updateGallery () {
async function updateGallery() {
images.value = (await $$db.get({ orderBy: 'desc' }))!.data
}
watch(() => filterList, () => {
clearChoosedList()
})
watch(
() => filterList,
() => {
clearChoosedList()
}
)
function handleChooseImage (val: CheckboxValueType, index: number) {
function handleChooseImage(val: CheckboxValueType, index: number) {
if (val === true) {
handleBarActive.value = true
if (lastChoosed.value !== -1 && isShiftKeyPress.value) {
@@ -650,11 +517,11 @@ function handleChooseImage (val: CheckboxValueType, index: number) {
}
}
function refreshPage () {
function refreshPage() {
sendRPC(IRPCActionType.REFRESH_SETTING_WINDOW)
}
function clearChoosedList () {
function clearChoosedList() {
isShiftKeyPress.value = false
Object.keys(choosedList).forEach(key => {
choosedList[key] = false
@@ -662,29 +529,29 @@ function clearChoosedList () {
lastChoosed.value = -1
}
function zoomImage (index: number) {
function zoomImage(index: number) {
gallerySliderControl.index = index
gallerySliderControl.visible = true
changeZIndexForGallery(true)
}
function changeZIndexForGallery (isOpen: boolean) {
function changeZIndexForGallery(isOpen: boolean) {
if (isOpen) {
// @ts-ignore
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
document.querySelector('.main-content.el-row').style.zIndex = 101
} else {
// @ts-ignore
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
document.querySelector('.main-content.el-row').style.zIndex = 10
}
}
function handleClose () {
function handleClose() {
gallerySliderControl.index = 0
gallerySliderControl.visible = false
changeZIndexForGallery(false)
}
async function copy (item: ImgInfo) {
async function copy(item: ImgInfo) {
item.config = JSON.parse(JSON.stringify(item.config) || '{}')
const copyLink = await triggerRPC<string>(IRPCActionType.GALLERY_PASTE_TEXT, item)
const obj = {
@@ -699,61 +566,66 @@ async function copy (item: ImgInfo) {
}
}
function remove (item: ImgInfo) {
function remove(item: ImgInfo) {
if (!item.id) return
$confirm($T('TIPS_REMOVE_LINK'), $T('TIPS_NOTICE'), {
confirmButtonText: $T('CONFIRM'),
cancelButtonText: $T('CANCEL'),
type: 'warning'
}).then(async () => {
const file = await $$db.getById(item.id!)
if (await getConfig(configPaths.settings.deleteCloudFile) && picBedsCanbeDeleted.includes(item?.type || 'placeholder')) {
const result = await ALLApi.delete(item)
if (result) {
ElNotification({
title: $T('GALLERY_SYNC_DELETE_NOTICE_TITLE'),
message: `${item.fileName} ${$T('GALLERY_SYNC_DELETE_NOTICE_SUCCEED')}`,
type: 'success'
})
} else {
ElNotification({
title: $T('GALLERY_SYNC_DELETE_NOTICE_TITLE'),
message: `${item.fileName} ${$T('GALLERY_SYNC_DELETE_NOTICE_FAILED')}`,
type: 'error'
})
})
.then(async () => {
const file = await $$db.getById(item.id!)
if (
(await getConfig(configPaths.settings.deleteCloudFile)) &&
picBedsCanbeDeleted.includes(item?.type || 'placeholder')
) {
const result = await ALLApi.delete(item)
if (result) {
ElNotification({
title: $T('GALLERY_SYNC_DELETE_NOTICE_TITLE'),
message: `${item.fileName} ${$T('GALLERY_SYNC_DELETE_NOTICE_SUCCEED')}`,
type: 'success'
})
} else {
ElNotification({
title: $T('GALLERY_SYNC_DELETE_NOTICE_TITLE'),
message: `${item.fileName} ${$T('GALLERY_SYNC_DELETE_NOTICE_FAILED')}`,
type: 'error'
})
return true
}
}
await $$db.removeById(item.id!)
sendRPC(IRPCActionType.GALLERY_REMOVE_FILES, [file])
const obj = {
title: $T('OPERATION_SUCCEED'),
body: ''
}
const myNotification = new Notification(obj.title, obj)
myNotification.onclick = () => {
return true
}
}
await $$db.removeById(item.id!)
sendRPC(IRPCActionType.GALLERY_REMOVE_FILES, [file])
const obj = {
title: $T('OPERATION_SUCCEED'),
body: ''
}
const myNotification = new Notification(obj.title, obj)
myNotification.onclick = () => {
updateGallery()
})
.catch(e => {
console.log(e)
return true
}
updateGallery()
}).catch((e) => {
console.log(e)
return true
})
})
}
function handleDeleteCloudFile (val: ICheckBoxValueType) {
function handleDeleteCloudFile(val: ICheckBoxValueType) {
saveConfig({
[configPaths.settings.deleteCloudFile]: val
})
}
function openDialog (item: ImgInfo) {
function openDialog(item: ImgInfo) {
imgInfo.id = item.id!
imgInfo.imgUrl = item.imgUrl as string
dialogVisible.value = true
}
async function confirmModify () {
async function confirmModify() {
await $$db.updateById(imgInfo.id, {
imgUrl: imgInfo.imgUrl
})
@@ -769,100 +641,106 @@ async function confirmModify () {
updateGallery()
}
function cleanSearch () {
function cleanSearch() {
searchText.value = ''
}
function cleanSearchUrl () {
function cleanSearchUrl() {
searchTextURL.value = ''
}
function isMultiple (obj: IObj) {
function isMultiple(obj: IObj) {
return Object.values(obj).some(item => item)
}
function toggleSelectAll () {
function toggleSelectAll() {
const result = !isAllSelected.value
filterList.value.forEach(item => {
choosedList[item.id!] = result
})
}
function multiRemove () {
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)
const isDeleteCloudFile = await getConfig(configPaths.settings.deleteCloudFile)
if (isDeleteCloudFile) {
for (let i = 0; i < imageIDList.length; i++) {
const key = imageIDList[i]
if (choosedList[key]) {
const file = await $$db.getById<ImgInfo>(key)
if (file) {
if (file.type !== undefined && picBedsCanbeDeleted.includes(file.type)) {
const result = await ALLApi.delete(file)
if (result) {
ElNotification({
title: $T('GALLERY_SYNC_DELETE'),
message: `${file.fileName} ${$T('GALLERY_SYNC_DELETE_NOTICE_SUCCEED')}`,
type: 'success',
duration: multiRemoveNumber > 5 ? 1000 : 2000
})
files.push(file)
await $$db.removeById(key)
} else {
ElNotification({
title: $T('GALLERY_SYNC_DELETE'),
message: `${file.fileName} ${$T('GALLERY_SYNC_DELETE_NOTICE_FAILED')}`,
type: 'error',
duration: multiRemoveNumber > 5 ? 1000 : 2000
})
$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)
const isDeleteCloudFile = await getConfig(configPaths.settings.deleteCloudFile)
if (isDeleteCloudFile) {
for (let i = 0; i < imageIDList.length; i++) {
const key = imageIDList[i]
if (choosedList[key]) {
const file = await $$db.getById<ImgInfo>(key)
if (file) {
if (file.type !== undefined && picBedsCanbeDeleted.includes(file.type)) {
const result = await ALLApi.delete(file)
if (result) {
ElNotification({
title: $T('GALLERY_SYNC_DELETE'),
message: `${file.fileName} ${$T('GALLERY_SYNC_DELETE_NOTICE_SUCCEED')}`,
type: 'success',
duration: multiRemoveNumber > 5 ? 1000 : 2000
})
files.push(file)
await $$db.removeById(key)
} else {
ElNotification({
title: $T('GALLERY_SYNC_DELETE'),
message: `${file.fileName} ${$T('GALLERY_SYNC_DELETE_NOTICE_FAILED')}`,
type: 'error',
duration: multiRemoveNumber > 5 ? 1000 : 2000
})
}
}
}
}
}
}
} else {
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)
} else {
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: ''
}
sendRPC(IRPCActionType.GALLERY_REMOVE_FILES, files)
const myNotification = new Notification(obj.title, obj)
myNotification.onclick = () => {
clearChoosedList()
// TODO: check this
// choosedList = {} // 只有删除才能将这个置空
const obj = {
title: $T('OPERATION_SUCCEED'),
body: ''
}
sendRPC(IRPCActionType.GALLERY_REMOVE_FILES, files)
const myNotification = new Notification(obj.title, obj)
myNotification.onclick = () => {
return true
}
updateGallery()
})
.catch(() => {
return true
}
updateGallery()
}).catch(() => {
return true
})
})
}
}
async function multiCopy () {
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.
@@ -890,21 +768,21 @@ async function multiCopy () {
}
}
function toggleHandleBar () {
function toggleHandleBar() {
handleBarActive.value = !handleBarActive.value
}
async function handlePasteStyleChange (val: string) {
async function handlePasteStyleChange(val: string) {
saveConfig(configPaths.settings.pasteStyle, val)
pasteStyle.value = val
}
function handleUseShortUrlChange (value: string) {
function handleUseShortUrlChange(value: string) {
saveConfig(configPaths.settings.useShortUrl, value === $T('UPLOAD_SHORT_URL'))
useShortUrl.value = value
}
function sortFile (type: 'name' | 'time' | 'ext' | 'check') {
function sortFile(type: 'name' | 'time' | 'ext' | 'check') {
switch (type) {
case 'name':
fileSortNameReverse.value = !fileSortNameReverse.value
@@ -950,7 +828,7 @@ function sortFile (type: 'name' | 'time' | 'ext' | 'check') {
}
}
function handleBatchRename () {
function handleBatchRename() {
isShowBatchRenameDialog.value = false
if (batchRenameMatch.value === '') {
ElMessage.warning($T('MANAGE_BUCKET_BATCH_RENAME_ERROR_MSG'))
@@ -976,7 +854,9 @@ function handleBatchRename () {
for (let i = 0; i < matchedFiles.length; i++) {
matchedFiles[i].newUrl = matchedFiles[i].newUrl.replaceAll('{auto}', (i + 1).toString())
}
const duplicateFilesNum = matchedFiles.filter((item: any) => matchedFiles.filter((item2: any) => item2.newUrl === item.newUrl).length > 1).length
const duplicateFilesNum = matchedFiles.filter(
(item: any) => matchedFiles.filter((item2: any) => item2.newUrl === item.newUrl).length > 1
).length
const renamefunc = async (item: any) => {
await $$db.updateById(item.id, {
imgUrl: item.newUrl
@@ -987,30 +867,38 @@ function handleBatchRename () {
for (let i = 0; i < matchedFiles.length; i++) {
promiseList.push(renamefunc(matchedFiles[i]))
}
Promise.all(promiseList).then(() => {
const obj = {
title: $T('OPERATION_SUCCEED'),
body: ''
}
const myNotification = new Notification(obj.title, obj)
myNotification.onclick = () => {
Promise.all(promiseList)
.then(() => {
const obj = {
title: $T('OPERATION_SUCCEED'),
body: ''
}
const myNotification = new Notification(obj.title, obj)
myNotification.onclick = () => {
return true
}
updateGallery()
})
.catch(() => {
return true
}
updateGallery()
}).catch(() => {
return true
})
})
}
if (duplicateFilesNum > 0) {
ElMessageBox.confirm(`${$T('MANAGE_BUCKET_BATCH_RENAME_REPEATED_MSG_A')} ${duplicateFilesNum} ${$T('MANAGE_BUCKET_BATCH_RENAME_REPEATED_MSG_B')}`, $T('MANAGE_BUCKET_BATCH_RENAME_REPEATED_MSG_C'), {
confirmButtonText: $T('MANAGE_BUCKET_BATCH_RENAME_REPEATED_CONFIRM'),
cancelButtonText: $T('MANAGE_BUCKET_BATCH_RENAME_REPEATED_CANCEL'),
type: 'warning'
}).then(() => {
rename()
}).catch(() => {
ElMessage.info($T('MANAGE_BUCKET_BATCH_RENAME_CANCEL'))
})
ElMessageBox.confirm(
`${$T('MANAGE_BUCKET_BATCH_RENAME_REPEATED_MSG_A')} ${duplicateFilesNum} ${$T('MANAGE_BUCKET_BATCH_RENAME_REPEATED_MSG_B')}`,
$T('MANAGE_BUCKET_BATCH_RENAME_REPEATED_MSG_C'),
{
confirmButtonText: $T('MANAGE_BUCKET_BATCH_RENAME_REPEATED_CONFIRM'),
cancelButtonText: $T('MANAGE_BUCKET_BATCH_RENAME_REPEATED_CANCEL'),
type: 'warning'
}
)
.then(() => {
rename()
})
.catch(() => {
ElMessage.info($T('MANAGE_BUCKET_BATCH_RENAME_CANCEL'))
})
} else {
rename()
}
@@ -1022,17 +910,18 @@ onBeforeUnmount(() => {
onActivated(async () => {
pasteStyle.value = (await getConfig(configPaths.settings.pasteStyle)) || IPasteStyle.MARKDOWN
useShortUrl.value = (await getConfig(configPaths.settings.useShortUrl) ? $T('UPLOAD_SHORT_URL') : $T('UPLOAD_NORMAL_URL'))
useShortUrl.value = (await getConfig(configPaths.settings.useShortUrl))
? $T('UPLOAD_SHORT_URL')
: $T('UPLOAD_NORMAL_URL')
initDeleteCloud()
})
</script>
<script lang="ts">
export default {
name: 'GalleryPage'
}
</script>
<style lang='stylus'>
<style lang="stylus">
.PhotoSlider
&__BannerIcon
&:nth-child(1)

View File

@@ -1,11 +1,13 @@
<template>
<div
id="mini-page"
>
<div id="mini-page">
<div
id="upload-area"
:class="{ 'is-dragover': dragover, uploading: isShowingProgress, linux: osGlobal === 'linux' }"
:style="{ backgroundPosition: '0 ' + progress + '%'}"
:class="{
'is-dragover': dragover,
uploading: isShowingProgress,
linux: osGlobal === 'linux'
}"
:style="{ backgroundPosition: '0 ' + progress + '%' }"
@drop.prevent="onDrop"
@dragover.prevent="dragover = true"
@dragleave.prevent="dragover = false"
@@ -13,18 +15,10 @@
<img
v-if="!dragover && !isShowingProgress"
:src="logoPath ? logoPath : require('../assets/squareLogo.png')"
style="width: 100%; height: 100%;border-radius: 50%;"
>
<div
id="upload-dragger"
@dblclick="openUploadWindow"
>
<input
id="file-uploader"
type="file"
multiple
@change="onChange"
>
style="width: 100%; height: 100%; border-radius: 50%"
/>
<div id="upload-dragger" @dblclick="openUploadWindow">
<input id="file-uploader" type="file" multiple @change="onChange" />
</div>
</div>
</div>
@@ -32,10 +26,7 @@
<script lang="ts" setup>
import { ElMessage as $message } from 'element-plus'
import {
ipcRenderer,
IpcRendererEvent
} from 'electron'
import { ipcRenderer, IpcRendererEvent } from 'electron'
import { IConfig } from 'piclist'
import { onBeforeUnmount, onBeforeMount, ref, watch } from 'vue'
@@ -57,11 +48,12 @@ const wY = ref(-1)
const screenX = ref(-1)
const screenY = ref(-1)
async function initLogoPath () {
async function initLogoPath() {
const config = await getConfig<IConfig>()
if (config) {
if (config.settings?.isCustomMiniIcon && config.settings?.customMiniIcon) {
logoPath.value = 'data:image/jpg;base64,' + await invokeToMain('convertPathToBase64', config.settings.customMiniIcon)
logoPath.value =
'data:image/jpg;base64,' + (await invokeToMain('convertPathToBase64', config.settings.customMiniIcon))
}
}
}
@@ -84,7 +76,7 @@ onBeforeMount(async () => {
window.addEventListener('mouseup', handleMouseUp, false)
})
watch(progress, (val) => {
watch(progress, val => {
if (val === 100) {
setTimeout(() => {
isShowingProgress.value = false
@@ -95,17 +87,16 @@ watch(progress, (val) => {
}
})
function onDrop (e: DragEvent) {
function onDrop(e: DragEvent) {
dragover.value = false
const items = e.dataTransfer?.items!
const files = e.dataTransfer?.files!
// send files first
if (files?.length) {
ipcSendFiles(e.dataTransfer?.files!)
} else {
if (e.dataTransfer?.files?.length) {
ipcSendFiles(e.dataTransfer.files)
} else if (e.dataTransfer?.items) {
const items = e.dataTransfer.items
if (items.length === 2 && items[0].type === 'text/uri-list') {
handleURLDrag(items, e.dataTransfer!)
handleURLDrag(items, e.dataTransfer)
} else if (items[0].type === 'text/plain') {
const str = e.dataTransfer!.getData(items[0].type)
if (isUrl(str)) {
@@ -117,7 +108,7 @@ function onDrop (e: DragEvent) {
}
}
function handleURLDrag (items: DataTransferItemList, dataTransfer: DataTransfer) {
function handleURLDrag(items: DataTransferItemList, dataTransfer: DataTransfer) {
// text/html
// Use this data to get a more precise URL
const urlString = dataTransfer.getData(items[1].type)
@@ -133,20 +124,20 @@ function handleURLDrag (items: DataTransferItemList, dataTransfer: DataTransfer)
}
}
function openUploadWindow () {
// @ts-ignore
function openUploadWindow() {
// @ts-expect-error file-uploader
document.getElementById('file-uploader').click()
}
function onChange (e: any) {
function onChange(e: any) {
ipcSendFiles(e.target.files)
// @ts-ignore
// @ts-expect-error file-uploader
document.getElementById('file-uploader').value = ''
}
function ipcSendFiles (files: FileList) {
function ipcSendFiles(files: FileList) {
const sendFiles: IFileWithPath[] = []
Array.from(files).forEach((item) => {
Array.from(files).forEach(item => {
const obj = {
name: item.name,
path: item.path
@@ -156,7 +147,7 @@ function ipcSendFiles (files: FileList) {
sendRPC(IRPCActionType.UPLOAD_CHOOSED_FILES, sendFiles)
}
function handleMouseDown (e: MouseEvent) {
function handleMouseDown(e: MouseEvent) {
draggingState.value = true
wX.value = e.pageX
wY.value = e.pageY
@@ -164,7 +155,7 @@ function handleMouseDown (e: MouseEvent) {
screenY.value = e.screenY
}
function handleMouseMove (e: MouseEvent) {
function handleMouseMove(e: MouseEvent) {
e.preventDefault()
e.stopPropagation()
if (draggingState.value) {
@@ -179,10 +170,11 @@ function handleMouseMove (e: MouseEvent) {
}
}
function handleMouseUp (e: MouseEvent) {
function handleMouseUp(e: MouseEvent) {
draggingState.value = false
if (screenX.value === e.screenX && screenY.value === e.screenY) {
if (e.button === 0) { // left mouse
if (e.button === 0) {
// left mouse
openUploadWindow()
} else {
openContextMenu()
@@ -190,7 +182,7 @@ function handleMouseUp (e: MouseEvent) {
}
}
function openContextMenu () {
function openContextMenu() {
sendRPC(IRPCActionType.SHOW_MINI_PAGE_MENU)
}
@@ -201,47 +193,46 @@ onBeforeUnmount(() => {
window.removeEventListener('mousemove', handleMouseMove, false)
window.removeEventListener('mouseup', handleMouseUp, false)
})
</script>
<script lang="ts">
export default {
name: 'MiniPage'
}
</script>
<style lang='stylus'>
#mini-page
background #409EFF
color #FFF
height 100vh
width 100vw
<style lang="stylus">
#mini-page
background #409EFF
color #FFF
height 100vh
width 100vw
border-radius 50%
text-align center
line-height 100vh
font-size 40px
background-size 90vh 90vw
background-position center center
background-repeat no-repeat
position relative
border 4px solid #fff
box-sizing border-box
cursor pointer
&.linux
border-radius 0
background-size 100vh 100vw
#upload-area
height 100%
width 100%
border-radius 50%
text-align center
line-height 100vh
font-size 40px
background-size 90vh 90vw
background-position center center
background-repeat no-repeat
position relative
border 4px solid #fff
box-sizing border-box
cursor pointer
transition all .2s ease-in-out
&.linux
border-radius 0
background-size 100vh 100vw
#upload-area
&.uploading
background: linear-gradient(to top, #409EFF 50%, #fff 51%)
background-size 200%
#upload-dragger
height 100%
width 100%
border-radius 50%
transition all .2s ease-in-out
&.linux
border-radius 0
&.uploading
background: linear-gradient(to top, #409EFF 50%, #fff 51%)
background-size 200%
#upload-dragger
height 100%
&.is-dragover
background rgba(0,0,0,0.3)
#file-uploader
display none
&.is-dragover
background rgba(0,0,0,0.3)
#file-uploader
display none
</style>

File diff suppressed because it is too large Load Diff

View File

@@ -2,72 +2,32 @@
<div id="plugin-view">
<div class="view-title">
{{ $T('PLUGIN_SETTINGS') }} -
<el-tooltip
:content="pluginListToolTip"
placement="right"
:persistent="false"
teleported
>
<el-icon
class="el-icon-goods"
@click="goAwesomeList"
>
<el-tooltip :content="pluginListToolTip" placement="right" :persistent="false" teleported>
<el-icon class="el-icon-goods" @click="goAwesomeList">
<Goods />
</el-icon>
</el-tooltip>
<el-tooltip
:content="updateAllToolTip"
placement="left"
:persistent="false"
teleported
>
<el-icon
class="el-icon-update"
@click="handleUpdateAllPlugin"
>
<el-tooltip :content="updateAllToolTip" placement="left" :persistent="false" teleported>
<el-icon class="el-icon-update" @click="handleUpdateAllPlugin">
<Refresh />
</el-icon>
</el-tooltip>
<el-tooltip
:content="importLocalPluginToolTip"
placement="left"
>
<el-icon
class="el-icon-download"
:persistent="false"
teleported
@click="handleImportLocalPlugin"
>
<el-tooltip :content="importLocalPluginToolTip" placement="left">
<el-icon class="el-icon-download" :persistent="false" teleported @click="handleImportLocalPlugin">
<Download />
</el-icon>
</el-tooltip>
</div>
<el-row
class="handle-bar"
:class="{ 'cut-width': pluginList.length > 6 }"
>
<el-input
v-model="searchText"
:placeholder="$T('PLUGIN_SEARCH_PLACEHOLDER')"
size="small"
>
<el-row class="handle-bar" :class="{ 'cut-width': pluginList.length > 6 }">
<el-input v-model="searchText" :placeholder="$T('PLUGIN_SEARCH_PLACEHOLDER')" size="small">
<template #suffix>
<el-icon
class="el-input__icon"
style="cursor: pointer;"
@click="cleanSearch"
>
<el-icon class="el-input__icon" style="cursor: pointer" @click="cleanSearch">
<close />
</el-icon>
</template>
</el-input>
</el-row>
<el-row
id="pluginList"
v-loading="loading"
:gutter="10"
class="plugin-list"
>
<el-row id="pluginList" v-loading="loading" :gutter="10" class="plugin-list">
<el-col
v-for="item in pluginList"
:key="item.fullName"
@@ -78,30 +38,11 @@
:lg="pluginList.length === 1 ? 24 : 12"
:xl="pluginList.length === 1 ? 24 : 12"
>
<div
class="plugin-item"
:class="{ 'darwin': osGlobal === '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" :class="{ darwin: osGlobal === '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)">
{{ item.name }} <small>{{ ' ' + item.version }}</small> &nbsp;
<!-- 升级提示 -->
<el-tag
@@ -114,10 +55,7 @@
new
</el-tag>
</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">
@@ -127,47 +65,26 @@
<span class="plugin-item__config">
<template v-if="searchText">
<template v-if="!item.hasInstall">
<span
v-if="!item.ing"
class="config-button install"
@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>
<el-icon
v-if="item.enabled"
class="el-icon-setting"
@click="buildContextMenu(item)"
>
<el-icon v-if="item.enabled" class="el-icon-setting" @click="buildContextMenu(item)">
<Tools />
</el-icon>
<el-icon
v-else
class="el-icon-remove-outline"
@click="buildContextMenu(item)"
>
<el-icon v-else class="el-icon-remove-outline" @click="buildContextMenu(item)">
<Remove />
</el-icon>
</template>
@@ -178,49 +95,28 @@
</div>
</el-col>
</el-row>
<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"
>
<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
v-model="dialogVisible"
:modal-append-to-body="false"
:title="$T('CONFIG_THING', {
c: configName
})"
:title="
$T('CONFIG_THING', {
c: configName
})
"
width="70%"
append-to-body
>
<config-form
:id="configName"
ref="$configForm"
:config="config"
:type="currentType"
color-mode="white"
/>
<config-form :id="configName" ref="$configForm" :config="config" :type="currentType" color-mode="white" />
<template #footer>
<el-button
round
@click="dialogVisible = false"
>
<el-button round @click="dialogVisible = false">
{{ $T('CANCEL') }}
</el-button>
<el-button
type="primary"
round
@click="handleConfirmConfig"
>
<el-button type="primary" round @click="handleConfirmConfig">
{{ $T('CONFIRM') }}
</el-button>
</template>
@@ -230,10 +126,7 @@
<script lang="ts" setup>
import axios from 'axios'
import {
ipcRenderer,
IpcRendererEvent
} from 'electron'
import { ipcRenderer, IpcRendererEvent } from 'electron'
import { ElMessageBox } from 'element-plus'
import { debounce, DebouncedFunc } from 'lodash'
import { Close, Download, Refresh, Goods, Remove, Tools } from '@element-plus/icons-vue'
@@ -293,15 +186,15 @@ watch(npmSearchText, (val: string) => {
watch(dialogVisible, (val: boolean) => {
if (val) {
// @ts-ignore
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
document.querySelector('.main-content.el-row').style.zIndex = 101
} else {
// @ts-ignore
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
document.querySelector('.main-content.el-row').style.zIndex = 10
}
})
async function getLatestVersionOfPlugIn (pluginName: string) {
async function getLatestVersionOfPlugIn(pluginName: string) {
try {
const res = await axios.get(`https://registry.npmjs.com/${pluginName}`)
latestVersionMap[pluginName] = res.data['dist-tags'].latest
@@ -316,7 +209,7 @@ onBeforeMount(async () => {
})
ipcRenderer.on(PICGO_HANDLE_PLUGIN_DONE, (_: IpcRendererEvent, fullName: string) => {
pluginList.value.forEach(item => {
if (item.fullName === fullName || (item.name === fullName)) {
if (item.fullName === fullName || item.name === fullName) {
item.ing = false
}
})
@@ -330,18 +223,27 @@ onBeforeMount(async () => {
}
loading.value = false
})
ipcRenderer.on('installPlugin', (_: 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(
'installPlugin',
(
_: 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', (_: IpcRendererEvent, plugin: string) => {
loading.value = false
pluginList.value.forEach(item => {
@@ -357,7 +259,8 @@ onBeforeMount(async () => {
ipcRenderer.on('uninstallSuccess', (_: IpcRendererEvent, plugin: string) => {
loading.value = false
pluginList.value = pluginList.value.filter(item => {
if (item.fullName === plugin) { // restore Uploader & Transformer after uninstalling
if (item.fullName === plugin) {
// restore Uploader & Transformer after uninstalling
if (item.config.transformer.name) {
handleRestoreState('transformer', item.config.transformer.name)
}
@@ -370,15 +273,18 @@ onBeforeMount(async () => {
})
pluginNameList.value = pluginNameList.value.filter(item => item !== plugin)
})
ipcRenderer.on(PICGO_CONFIG_PLUGIN, (_: IpcRendererEvent, _currentType: 'plugin' | 'transformer' | 'uploader', _configName: string, _config: any) => {
currentType.value = _currentType
configName.value = _configName
config.value = _config
dialogVisible.value = true
})
ipcRenderer.on(
PICGO_CONFIG_PLUGIN,
(_: IpcRendererEvent, _currentType: 'plugin' | 'transformer' | 'uploader', _configName: string, _config: any) => {
currentType.value = _currentType
configName.value = _configName
config.value = _config
dialogVisible.value = true
}
)
ipcRenderer.on(PICGO_HANDLE_PLUGIN_ING, (_: IpcRendererEvent, fullName: string) => {
pluginList.value.forEach(item => {
if (item.fullName === fullName || (item.name === fullName)) {
if (item.fullName === fullName || item.name === fullName) {
item.ing = true
}
})
@@ -394,14 +300,14 @@ onBeforeMount(async () => {
})
getPluginList()
getSearchResult = debounce(_getSearchResult, 50)
needReload.value = await getConfig<boolean>(configPaths.needReload) || false
needReload.value = (await getConfig<boolean>(configPaths.needReload)) || false
})
async function buildContextMenu (plugin: IPicGoPlugin) {
async function buildContextMenu(plugin: IPicGoPlugin) {
sendRPC(IRPCActionType.SHOW_PLUGIN_PAGE_MENU, plugin)
}
function handleResize () {
function handleResize() {
const myDiv = document.getElementById('pluginList') as HTMLElement
const windowHeight = window.innerHeight
const newHeight = windowHeight * 0.75
@@ -412,33 +318,35 @@ onMounted(() => {
window.addEventListener('resize', handleResize)
})
function getPluginList () {
function getPluginList() {
sendRPC(IRPCActionType.PLUGIN_GET_LIST)
}
function installPlugin (item: IPicGoPlugin) {
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
sendRPC(IRPCActionType.PLUGIN_INSTALL, item.fullName)
}).catch(() => {
console.log('Install canceled')
})
.then(() => {
item.ing = true
sendRPC(IRPCActionType.PLUGIN_INSTALL, item.fullName)
})
.catch(() => {
console.log('Install canceled')
})
} else {
item.ing = true
sendRPC(IRPCActionType.PLUGIN_INSTALL, item.fullName)
}
}
function reloadApp () {
function reloadApp() {
sendRPC(IRPCActionType.RELOAD_APP)
}
async function handleReload () {
async function handleReload() {
saveConfig({
needReload: true
})
@@ -451,12 +359,12 @@ async function handleReload () {
}
}
function cleanSearch () {
function cleanSearch() {
searchText.value = ''
}
async function handleConfirmConfig () {
const result = (await $configForm.value?.validate() || false)
async function handleConfirmConfig() {
const result = (await $configForm.value?.validate()) || false
if (result !== false) {
switch (currentType.value) {
case 'plugin':
@@ -486,11 +394,12 @@ async function handleConfirmConfig () {
}
}
function _getSearchResult (val: string) {
axios.get(`https://registry.npmjs.com/-/v1/search?text=${val}`)
function _getSearchResult(val: string) {
axios
.get(`https://registry.npmjs.com/-/v1/search?text=${val}`)
.then((res: INPMSearchResult) => {
pluginList.value = res.data.objects
.filter((item:INPMSearchResultObject) => {
.filter((item: INPMSearchResultObject) => {
return item.package.name.includes('picgo-plugin-')
})
.map((item: INPMSearchResultObject) => {
@@ -504,7 +413,7 @@ function _getSearchResult (val: string) {
})
}
function handleSearchResult (item: INPMSearchResultObject) {
function handleSearchResult(item: INPMSearchResultObject) {
const name = handleStreamlinePluginName(item.package.name)
let gui = false
if (item.package.keywords && item.package.keywords.length > 0) {
@@ -528,7 +437,7 @@ function handleSearchResult (item: INPMSearchResultObject) {
}
// restore Uploader & Transformer
async function handleRestoreState (item: string, name: string) {
async function handleRestoreState(item: string, name: string) {
if (item === 'uploader') {
const current = await getConfig(configPaths.picBed.current)
if (current === name) {
@@ -548,22 +457,22 @@ async function handleRestoreState (item: string, name: string) {
}
}
function openHomepage (url: string) {
function openHomepage(url: string) {
if (url) {
sendRPC(IRPCActionType.OPEN_URL, url)
}
}
function goAwesomeList () {
function goAwesomeList() {
sendRPC(IRPCActionType.OPEN_URL, 'https://github.com/PicGo/Awesome-PicGo')
}
function handleImportLocalPlugin () {
function handleImportLocalPlugin() {
sendRPC(IRPCActionType.PLUGIN_IMPORT_LOCAL)
loading.value = true
}
function handleUpdateAllPlugin () {
function handleUpdateAllPlugin() {
sendRPC(IRPCActionType.PLUGIN_UPDATE_ALL, toRaw(pluginNameList.value))
}
@@ -576,14 +485,13 @@ onBeforeUnmount(() => {
ipcRenderer.removeAllListeners('hideLoading')
ipcRenderer.removeAllListeners(PICGO_HANDLE_PLUGIN_DONE)
})
</script>
<script lang="ts">
export default {
name: 'PluginPage'
}
</script>
<style lang='stylus'>
<style lang="stylus">
$darwinBg = #172426
#plugin-view
position absolute

View File

@@ -1,29 +1,14 @@
<template>
<div id="rename-page">
<el-form
ref="formRef"
:model="form"
@submit.prevent
>
<el-form ref="formRef" :model="form" @submit.prevent>
<el-form-item
:label="$T('FILE_RENAME')"
prop="fileName"
:rules="[
{ required: true, message: 'file name is required', trigger: 'blur' }
]"
:rules="[{ required: true, message: 'file name is required', trigger: 'blur' }]"
>
<el-input
v-model="form.fileName"
size="small"
autofocus
@keyup.enter="confirmName"
>
<el-input v-model="form.fileName" size="small" autofocus @keyup.enter="confirmName">
<template #suffix>
<el-icon
class="el-input__icon"
style="cursor: pointer;"
@click="form.fileName = ''"
>
<el-icon class="el-input__icon" style="cursor: pointer" @click="form.fileName = ''">
<close />
</el-icon>
</template>
@@ -32,19 +17,10 @@
</el-form>
<el-row>
<div class="pull-right">
<el-button
round
size="small"
@click="cancel"
>
<el-button round size="small" @click="cancel">
{{ $T('CANCEL') }}
</el-button>
<el-button
type="primary"
round
size="small"
@click="confirmName"
>
<el-button type="primary" round size="small" @click="confirmName">
{{ $T('CONFIRM') }}
</el-button>
</div>
@@ -84,15 +60,15 @@ onBeforeMount(() => {
ipcRenderer.send(GET_RENAME_FILE_NAME)
})
function confirmName () {
formRef.value?.validate((valid) => {
function confirmName() {
formRef.value?.validate(valid => {
if (valid) {
sendToMain(`${RENAME_FILE_NAME}${id.value}`, form.fileName)
}
})
}
function cancel () {
function cancel() {
// if cancel, use origin file name
sendToMain(`${RENAME_FILE_NAME}${id.value}`, form.originName)
}
@@ -100,18 +76,17 @@ function cancel () {
onBeforeUnmount(() => {
ipcRenderer.removeAllListeners(RENAME_FILE_NAME)
})
</script>
<script lang="ts">
export default {
name: 'RenamePage'
}
</script>
<style lang='stylus'>
#rename-page
padding 0 20px
.pull-right
float right
.el-form-item__label
color #ddd
<style lang="stylus">
#rename-page
padding 0 20px
.pull-right
float right
.el-form-item__label
color #ddd
</style>

View File

@@ -4,10 +4,7 @@
{{ $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"
@@ -15,42 +12,25 @@
header-cell-class-name="shortcut-page-table-border"
cell-class-name="shortcut-page-table-border"
>
<el-table-column
:label="$T('SHORTCUT_NAME')"
>
<el-table-column :label="$T('SHORTCUT_NAME')">
<template #default="scope">
{{ scope.row.label ? scope.row.label : scope.row.name }}
</template>
</el-table-column>
<el-table-column
width="160px"
:label="$T('SHORTCUT_BIND')"
prop="key"
/>
<el-table-column
:label="$T('SHORTCUT_STATUS')"
>
<el-table-column width="160px" :label="$T('SHORTCUT_BIND')" prop="key" />
<el-table-column :label="$T('SHORTCUT_STATUS')">
<template #default="scope">
<el-tag
size="small"
:type="scope.row.enable ? 'success' : 'danger'"
>
<el-tag size="small" :type="scope.row.enable ? 'success' : 'danger'">
{{ scope.row.enable ? $T('SHORTCUT_ENABLED') : $T('SHORTCUT_DISABLED') }}
</el-tag>
</template>
</el-table-column>
<el-table-column
:label="$T('SHORTCUT_SOURCE')"
width="100px"
>
<el-table-column :label="$T('SHORTCUT_SOURCE')" width="100px">
<template #default="scope">
{{ calcOriginShowName(scope.row.from) }}
</template>
</el-table-column>
<el-table-column
:label="$T('SHORTCUT_HANDLE')"
width="100px"
>
<el-table-column :label="$T('SHORTCUT_HANDLE')" width="100px">
<template #default="scope">
<el-row>
<el-button
@@ -85,10 +65,7 @@
:modal-append-to-body="false"
append-to-body
>
<el-form
label-position="top"
label-width="80px"
>
<el-form label-position="top" label-width="80px">
<el-form-item>
<el-input
v-model="shortKey"
@@ -99,17 +76,10 @@
</el-form-item>
</el-form>
<template #footer>
<el-button
round
@click="cancelKeyBinding"
>
<el-button round @click="cancelKeyBinding">
{{ $T('CANCEL') }}
</el-button>
<el-button
type="primary"
round
@click="confirmKeyBinding"
>
<el-button type="primary" round @click="confirmKeyBinding">
{{ $T('CONFIRM') }}
</el-button>
</template>
@@ -148,38 +118,38 @@ watch(keyBindingVisible, (val: boolean) => {
sendRPC(IRPCActionType.SHORTKEY_TOGGLE_SHORTKEY_MODIFIED_MODE, val)
})
function calcOrigin (item: string) {
function calcOrigin(item: string) {
const [origin] = item.split(':')
return origin
}
function calcOriginShowName (item: string) {
function calcOriginShowName(item: string) {
return item.replace('picgo-plugin-', '')
}
function toggleEnable (item: IShortKeyConfig) {
function toggleEnable(item: IShortKeyConfig) {
const status = !item.enable
item.enable = status
sendRPC(IRPCActionType.SHORTKEY_BIND_OR_UNBIND, item, item.from)
}
function keyDetect (event: KeyboardEvent) {
function keyDetect(event: KeyboardEvent) {
shortKey.value = keyBinding(event).join('+')
}
async function openKeyBindingDialog (config: IShortKeyConfig, index: number) {
async function openKeyBindingDialog(config: IShortKeyConfig, index: number) {
command.value = `${config.from}:${config.name}`
shortKey.value = await getConfig(`settings.shortKey.${command.value}.key`) || ''
shortKey.value = (await getConfig(`settings.shortKey.${command.value}.key`)) || ''
currentIndex.value = index
keyBindingVisible.value = true
}
async function cancelKeyBinding () {
async function cancelKeyBinding() {
keyBindingVisible.value = false
shortKey.value = await getConfig<string>(`settings.shortKey.${command.value}.key`) || ''
shortKey.value = (await getConfig<string>(`settings.shortKey.${command.value}.key`)) || ''
}
async function confirmKeyBinding () {
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
@@ -201,7 +171,7 @@ export default {
}
</script>
<style lang='stylus'>
<style lang="stylus">
#shortcut-page
.shortcut-page-table-border
border-color darken(#eee, 50%)

View File

@@ -1,14 +1,9 @@
<template>
<div class="toolbox">
<el-row>
<el-row
class="toolbox-header"
>
<el-row class="toolbox-header">
<el-row>
<img
class="toolbox-header__logo"
:src="defaultLogo"
>
<img class="toolbox-header__logo" :src="defaultLogo" />
<el-row class="toolbox-header__text">
<el-row class="toolbox-header__title">
{{ $T('TOOLBOX_TITLE') }}
@@ -20,12 +15,7 @@
</el-row>
<el-row>
<template v-if="progress !== 100">
<el-button
type="primary"
round
:disabled="isLoading"
@click="handleCheck"
>
<el-button type="primary" round :disabled="isLoading" @click="handleCheck">
{{ $T('TOOLBOX_START_SCAN') }}
</el-button>
</template>
@@ -36,23 +26,14 @@
</template>
<template v-else-if="!isAllSuccess">
<template v-if="canFixLength !== 0">
<el-button
type="primary"
round
@click="handleFix"
>
<el-button type="primary" round @click="handleFix">
{{ $T('TOOLBOX_START_FIX') }}
</el-button>
</template>
<template v-else>
<div class="toolbox-cant-fix toolbox-tips">
{{ $T('TOOLBOX_CANT_AUTO_FIX') }}
<el-button
type="primary"
round
class="toolbox-cant-fix__btn"
@click="handleCheck"
>
<el-button type="primary" round class="toolbox-cant-fix__btn" @click="handleCheck">
{{ $T('TOOLBOX_RE_SCAN') }}
</el-button>
</div>
@@ -62,23 +43,11 @@
</el-row>
</el-row>
<el-row class="progress">
<el-progress
:percentage="progress"
:format="format"
/>
<el-progress :percentage="progress" :format="format" />
</el-row>
<el-collapse
v-model="activeTypes"
accordion
>
<el-collapse-item
v-for="(item, key) in fixList"
:key="key"
:name="key"
>
<template #title>
{{ item.title }} <toolbox-status-icon :status="item.status" />
</template>
<el-collapse v-model="activeTypes" accordion>
<el-collapse-item v-for="(item, key) in fixList" :key="key" :name="key">
<template #title> {{ item.title }} <toolbox-status-icon :status="item.status" /> </template>
<div class="toolbox-item-msg">
{{ item.msg || '' }}
<template v-if="item.handler && item.handlerText && item.value">
@@ -115,7 +84,7 @@ const fixList = reactive<IToolboxMap>({
title: $T('TOOLBOX_CHECK_CONFIG_FILE_BROKEN'),
status: IToolboxItemCheckStatus.INIT,
handlerText: $T('SETTINGS_OPEN_CONFIG_FILE'),
handler (value: string) {
handler(value: string) {
sendRPC(IRPCActionType.OPEN_FILE, value)
}
},
@@ -127,7 +96,7 @@ const fixList = reactive<IToolboxMap>({
title: $T('TOOLBOX_CHECK_PROBLEM_WITH_CLIPBOARD_PIC_UPLOAD'), // picgo-image-clipboard folder
status: IToolboxItemCheckStatus.INIT,
handlerText: $T('OPEN_FILE_PATH'),
handler (value: string) {
handler(value: string) {
sendRPC(IRPCActionType.OPEN_FILE, value)
}
},
@@ -144,7 +113,7 @@ const progress = computed(() => {
const status = fixList[key as IToolboxItemType].status
return status !== IToolboxItemCheckStatus.INIT && status !== IToolboxItemCheckStatus.LOADING
}).length
return done / total * 100
return (done / total) * 100
})
const isAllSuccess = computed(() => {
@@ -192,37 +161,44 @@ const handleCheck = () => {
}
const handleFix = async () => {
const fixRes = await Promise.all(Object.keys(fixList).filter(key => {
const status = fixList[key as IToolboxItemType].status
return status === IToolboxItemCheckStatus.ERROR && !fixList[key as IToolboxItemType].hasNoFixMethod
}).map(async key => {
return triggerRPC<IToolboxCheckRes>(IRPCActionType.TOOLBOX_CHECK_FIX, key as IToolboxItemType)
}))
const fixRes = await Promise.all(
Object.keys(fixList)
.filter(key => {
const status = fixList[key as IToolboxItemType].status
return status === IToolboxItemCheckStatus.ERROR && !fixList[key as IToolboxItemType].hasNoFixMethod
})
.map(async key => {
return triggerRPC<IToolboxCheckRes>(IRPCActionType.TOOLBOX_CHECK_FIX, key as IToolboxItemType)
})
)
fixRes.filter(item => item !== null).forEach(item => {
if (item) {
fixList[item.type].status = item.status
fixList[item.type].msg = item.msg
fixList[item.type].value = item.value
}
})
fixRes
.filter(item => item !== null)
.forEach(item => {
if (item) {
fixList[item.type].status = item.status
fixList[item.type].msg = item.msg
fixList[item.type].value = item.value
}
})
$confirm($T('TOOLBOX_FIX_DONE_NEED_RELOAD'), $T('TIPS_NOTICE'), {
confirmButtonText: $T('CONFIRM'),
cancelButtonText: $T('CANCEL'),
type: 'info'
}).then(() => {
sendRPC(IRPCActionType.RELOAD_APP)
}).catch(() => {})
})
.then(() => {
sendRPC(IRPCActionType.RELOAD_APP)
})
.catch(() => {})
}
</script>
<script lang="ts">
export default {
name: 'ToolBoxPage'
}
</script>
<style lang='stylus'>
<style lang="stylus">
.toolbox
padding 0 40px
&-header

View File

@@ -1,33 +1,16 @@
<template>
<div id="tray-page">
<div
class="open-main-window"
@click="openSettingWindow"
>
<div class="open-main-window" @click="openSettingWindow">
{{ $T('OPEN_MAIN_WINDOW') }}
</div>
<div class="content">
<div
v-if="clipboardFiles.length > 0"
class="wait-upload-img"
>
<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"
>
<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" />
</div>
</div>
</div>
@@ -35,23 +18,10 @@
<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"
>
<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>
@@ -85,11 +55,11 @@ const notification = reactive({
const clipboardFiles = ref<ImgInfo[]>([])
const uploadFlag = ref(false)
function openSettingWindow () {
function openSettingWindow() {
sendRPC(IRPCActionType.OPEN_WINDOW, IWindowList.SETTING_WINDOW)
}
async function getData () {
async function getData() {
files.value = (await $$db.get<ImgInfo>({ orderBy: 'desc', limit: 5 }))!.data
}
@@ -112,8 +82,8 @@ const formatCustomLink = (customLink: string, item: ImgInfo) => {
return customLink
}
async function copyTheLink (item: ImgInfo) {
const pasteStyle = await getConfig<IPasteStyle>(configPaths.settings.pasteStyle) || IPasteStyle.MARKDOWN
async function copyTheLink(item: ImgInfo) {
const pasteStyle = (await getConfig<IPasteStyle>(configPaths.settings.pasteStyle)) || IPasteStyle.MARKDOWN
const customLink = await getConfig<string>(configPaths.settings.customLink)
const txt = await pasteTemplate(pasteStyle, item, customLink)
clipboard.writeText(txt)
@@ -123,7 +93,7 @@ async function copyTheLink (item: ImgInfo) {
}
}
async function pasteTemplate (style: IPasteStyle, item: ImgInfo, customLink: string | undefined) {
async function pasteTemplate(style: IPasteStyle, item: ImgInfo, customLink: string | undefined) {
let url = item.url || item.imgUrl
if (item.type === 'aws-s3' || item.type === 'aws-s3-plist') {
url = item.imgUrl || item.url || ''
@@ -131,9 +101,9 @@ async function pasteTemplate (style: IPasteStyle, item: ImgInfo, customLink: str
if ((await getConfig(configPaths.settings.encodeOutputURL)) === true) {
url = handleUrlEncode(url)
}
const useShortUrl = await getConfig(configPaths.settings.useShortUrl) || false
const useShortUrl = (await getConfig(configPaths.settings.useShortUrl)) || false
if (useShortUrl) {
url = await triggerRPC<string>(IRPCActionType.TRAY_GET_SHORT_URL, url) || url
url = (await triggerRPC<string>(IRPCActionType.TRAY_GET_SHORT_URL, url)) || url
}
notification.body = url
const _customLink = customLink || '![$fileName]($url)'
@@ -150,18 +120,26 @@ async function pasteTemplate (style: IPasteStyle, item: ImgInfo, customLink: str
return tpl[style]
}
function disableDragFile () {
window.addEventListener('dragover', (e) => {
e = e || event
e.preventDefault()
}, false)
window.addEventListener('drop', (e) => {
e = e || event
e.preventDefault()
}, false)
function disableDragFile() {
window.addEventListener(
'dragover',
e => {
e = e || event
e.preventDefault()
},
false
)
window.addEventListener(
'drop',
e => {
e = e || event
e.preventDefault()
},
false
)
}
function uploadClipboardFiles () {
function uploadClipboardFiles() {
if (uploadFlag.value) {
return
}
@@ -177,13 +155,19 @@ onBeforeMount(() => {
const item = _files[i]
await $$db.insert(item)
}
files.value = (await $$db.get<ImgInfo>({ orderBy: 'desc', limit: 5 }))!.data
files.value = (await $$db.get<ImgInfo>({
orderBy: 'desc',
limit: 5
}))!.data
})
ipcRenderer.on('clipboardFiles', (_: Event, files: ImgInfo[]) => {
clipboardFiles.value = files
})
ipcRenderer.on('uploadFiles', async () => {
files.value = (await $$db.get<ImgInfo>({ orderBy: 'desc', limit: 5 }))!.data
files.value = (await $$db.get<ImgInfo>({
orderBy: 'desc',
limit: 5
}))!.data
uploadFlag.value = false
})
ipcRenderer.on('updateFiles', () => {

View File

@@ -1,31 +1,14 @@
<template>
<div id="upload-view">
<el-row
:gutter="16"
align="middle"
>
<el-col
:span="24"
>
<el-row :gutter="16" align="middle">
<el-col :span="24">
<div class="view-title">
<el-tooltip
placement="top"
effect="light"
:content="$T('UPLOAD_VIEW_HINT')"
:persistent="false"
teleported
>
<span
id="upload-view-title"
@click="handlePicBedNameClick(picBedName, picBedConfigName)"
>
<el-tooltip placement="top" effect="light" :content="$T('UPLOAD_VIEW_HINT')" :persistent="false" teleported>
<span id="upload-view-title" @click="handlePicBedNameClick(picBedName, picBedConfigName)">
{{ picBedName }} - {{ picBedConfigName || 'Default' }}
</span>
</el-tooltip>
<el-icon
style="cursor: pointer; margin-left: 4px;"
@click="handleChangePicBed"
>
<el-icon style="cursor: pointer; margin-left: 4px" @click="handleChangePicBed">
<CaretBottom />
</el-icon>
<el-button
@@ -46,29 +29,22 @@
@dragover.prevent="dragover = true"
@dragleave.prevent="dragover = false"
>
<div
id="upload-dragger"
@click="openUplodWindow"
>
<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>
{{ $T('DRAG_FILE_TO_HERE') }}
<span>{{ $T('CLICK_TO_UPLOAD') }}</span>
</div>
<input
id="file-uploader"
type="file"
multiple
@change="onChange"
>
<input id="file-uploader" type="file" multiple @change="onChange" />
</div>
</div>
<el-progress
:percentage="progress"
:show-text="false"
class="upload-progress"
:class="{ 'show': showProgress }"
:class="{ show: showProgress }"
:status="showError ? 'exception' : undefined"
/>
<div class="paste-style">
@@ -76,35 +52,16 @@
<div class="paste-style__text">
{{ $T('LINK_FORMAT') }}
</div>
<el-radio-group
v-model="pasteStyle"
size="small"
@change="handlePasteStyleChange"
>
<el-radio-button
v-for="(item, key) in pasteFormatList"
:key="key"
:value="key"
:title="item"
>
<el-radio-group v-model="pasteStyle" size="small" @change="handlePasteStyleChange">
<el-radio-button v-for="(item, key) in pasteFormatList" :key="key" :value="key" :title="item">
{{ key }}
</el-radio-button>
</el-radio-group>
<el-radio-group
v-model="useShortUrl"
size="small"
@change="handleUseShortUrlChange"
>
<el-radio-button
:value="true"
style="border-radius: 5px"
>
<el-radio-group v-model="useShortUrl" size="small" @change="handleUseShortUrlChange">
<el-radio-button :value="true" style="border-radius: 5px">
{{ $T('UPLOAD_SHORT_URL') }}
</el-radio-button>
<el-radio-button
:value="false"
style="border-radius: 5px"
>
<el-radio-button :value="false" style="border-radius: 5px">
{{ $T('UPLOAD_NORMAL_URL') }}
</el-radio-button>
</el-radio-group>
@@ -146,9 +103,7 @@
align-center
append-to-body
>
<ImageProcessSetting
v-model="imageProcessDialogVisible"
/>
<ImageProcessSetting v-model="imageProcessDialogVisible" />
</el-dialog>
</div>
</template>
@@ -168,14 +123,9 @@ import { sendRPC, triggerRPC } from '@/utils/common'
import { getConfig, saveConfig } from '@/utils/dataSender'
import { picBedGlobal, updatePicBedGlobal } from '@/utils/global'
import {
SHOW_INPUT_BOX,
SHOW_INPUT_BOX_RESPONSE
} from '#/events/constants'
import { SHOW_INPUT_BOX, SHOW_INPUT_BOX_RESPONSE } from '#/events/constants'
import { IPasteStyle, IRPCActionType } from '#/types/enum'
import {
isUrl
} from '#/utils/common'
import { isUrl } from '#/utils/common'
import { configPaths } from '#/utils/configPaths'
const $router = useRouter()
@@ -228,7 +178,7 @@ const handleImageProcess = () => {
watch(progress, onProgressChange)
function onProgressChange (val: number) {
function onProgressChange(val: number) {
if (val === 100) {
setTimeout(() => {
showProgress.value = false
@@ -240,10 +190,10 @@ function onProgressChange (val: number) {
}
}
async function handlePicBedNameClick (_picBedName: string, picBedConfigName: string | undefined) {
async function handlePicBedNameClick(_picBedName: string, picBedConfigName: string | undefined) {
const formatedpicBedConfigName = picBedConfigName || 'Default'
const currentPicBed = await getConfig<string>(configPaths.picBed.current)
const currentPicBedConfig = await getConfig<any[]>(`uploader.${currentPicBed}`) as any || {}
const currentPicBedConfig = ((await getConfig<any[]>(`uploader.${currentPicBed}`)) as any) || {}
const configList = await triggerRPC<IUploaderConfigItem>(IRPCActionType.PICBED_GET_CONFIG_LIST, currentPicBed)
const currentConfigList = configList?.configList ?? []
const config = currentConfigList.find((item: any) => item._configName === formatedpicBedConfigName)
@@ -265,19 +215,18 @@ onBeforeUnmount(() => {
ipcRenderer.removeAllListeners('syncPicBed')
})
function onDrop (e: DragEvent) {
function onDrop(e: DragEvent) {
dragover.value = false
const items = e.dataTransfer?.items!
const files = e.dataTransfer?.files!
// send files first
if (files?.length) {
ipcSendFiles(e.dataTransfer?.files!)
} else {
if (e.dataTransfer?.files?.length) {
ipcSendFiles(e.dataTransfer.files)
} else if (e.dataTransfer?.items) {
const items = e.dataTransfer.items
if (items.length === 2 && items[0].type === 'text/uri-list') {
handleURLDrag(items, e.dataTransfer!)
handleURLDrag(items, e.dataTransfer)
} else if (items[0].type === 'text/plain') {
const str = e.dataTransfer!.getData(items[0].type)
const str = e.dataTransfer.getData(items[0].type)
if (isUrl(str)) {
sendRPC(IRPCActionType.UPLOAD_CHOOSED_FILES, [{ path: str }])
} else {
@@ -287,7 +236,7 @@ function onDrop (e: DragEvent) {
}
}
function handleURLDrag (items: DataTransferItemList, dataTransfer: DataTransfer) {
function handleURLDrag(items: DataTransferItemList, dataTransfer: DataTransfer) {
// text/html
// Use this data to get a more precise URL
const urlString = dataTransfer.getData(items[1].type)
@@ -303,18 +252,18 @@ function handleURLDrag (items: DataTransferItemList, dataTransfer: DataTransfer)
}
}
function openUplodWindow () {
function openUplodWindow() {
document.getElementById('file-uploader')!.click()
}
function onChange (e: any) {
ipcSendFiles(e.target.files);
(document.getElementById('file-uploader') as HTMLInputElement).value = ''
function onChange(e: any) {
ipcSendFiles(e.target.files)
;(document.getElementById('file-uploader') as HTMLInputElement).value = ''
}
function ipcSendFiles (files: FileList) {
function ipcSendFiles(files: FileList) {
const sendFiles: IFileWithPath[] = []
Array.from(files).forEach((item) => {
Array.from(files).forEach(item => {
const obj = {
name: item.name,
path: item.path
@@ -324,32 +273,32 @@ function ipcSendFiles (files: FileList) {
sendRPC(IRPCActionType.UPLOAD_CHOOSED_FILES, sendFiles)
}
async function getPasteStyle () {
pasteStyle.value = await getConfig(configPaths.settings.pasteStyle) || IPasteStyle.MARKDOWN
pasteFormatList.value.Custom = await getConfig(configPaths.settings.customLink) || '![$fileName]($url)'
async function getPasteStyle() {
pasteStyle.value = (await getConfig(configPaths.settings.pasteStyle)) || IPasteStyle.MARKDOWN
pasteFormatList.value.Custom = (await getConfig(configPaths.settings.customLink)) || '![$fileName]($url)'
}
async function getUseShortUrl () {
useShortUrl.value = await getConfig(configPaths.settings.useShortUrl) || false
async function getUseShortUrl() {
useShortUrl.value = (await getConfig(configPaths.settings.useShortUrl)) || false
}
async function handleUseShortUrlChange () {
async function handleUseShortUrlChange() {
saveConfig({
[configPaths.settings.useShortUrl]: useShortUrl.value
})
}
function handlePasteStyleChange (val: string | number | boolean | undefined) {
function handlePasteStyleChange(val: string | number | boolean | undefined) {
saveConfig({
[configPaths.settings.pasteStyle]: val || IPasteStyle.MARKDOWN
})
}
function uploadClipboardFiles () {
function uploadClipboardFiles() {
sendRPC(IRPCActionType.UPLOAD_CLIPBOARD_FILES_FROM_UPLOAD_PAGE)
}
async function uploadURLFiles () {
async function uploadURLFiles() {
const str = await navigator.clipboard.readText()
$bus.emit(SHOW_INPUT_BOX, {
value: isUrl(str) ? str : '',
@@ -358,28 +307,30 @@ async function uploadURLFiles () {
})
}
function handleInputBoxValue (val: string) {
function handleInputBoxValue(val: string) {
if (val === '') return
if (isUrl(val)) {
sendRPC(IRPCActionType.UPLOAD_CHOOSED_FILES, [{
path: val
}])
sendRPC(IRPCActionType.UPLOAD_CHOOSED_FILES, [
{
path: val
}
])
} else {
$message.error($T('TIPS_INPUT_VALID_URL'))
}
}
async function getDefaultPicBed () {
async function getDefaultPicBed() {
const currentPicBed = await getConfig<string>(configPaths.picBed.current)
picBedGlobal.value.forEach(item => {
if (item.type === currentPicBed) {
picBedName.value = item.name
}
})
picBedConfigName.value = await getConfig<string>(`picBed.${currentPicBed}._configName`) || ''
picBedConfigName.value = (await getConfig<string>(`picBed.${currentPicBed}._configName`)) || ''
}
async function handleChangePicBed () {
async function handleChangePicBed() {
sendRPC(IRPCActionType.SHOW_UPLOAD_PAGE_MENU)
}
</script>
@@ -390,7 +341,7 @@ export default {
}
</script>
<style lang='stylus'>
<style lang="stylus">
.view-title
display flex
color #eee

View File

@@ -3,13 +3,7 @@
<div class="view-title">
{{ $T('SETTINGS') }}
</div>
<el-row
:gutter="15"
justify="space-between"
align="middle"
type="flex"
class="config-list"
>
<el-row :gutter="15" justify="space-between" align="middle" type="flex" class="config-list">
<el-col
v-for="item in curConfigList"
:key="item._id"
@@ -30,17 +24,11 @@
<div class="config-update-time">
{{ formatTime(item._updatedAt) }}
</div>
<div
v-if="defaultConfigId === item._id"
class="default-text"
>
<div v-if="defaultConfigId === item._id" class="default-text">
{{ $T('SELECTED_SETTING_HINT') }}
</div>
<div class="operation-container">
<el-icon
class="el-icon-edit"
@click="openEditPage(item._id)"
>
<el-icon class="el-icon-edit" @click="openEditPage(item._id)">
<Edit />
</el-icon>
<el-icon
@@ -61,24 +49,14 @@
:lg="curConfigList.length === 1 ? 12 : 6"
:xl="curConfigList.length === 1 ? 12 : 3"
>
<div
class="config-item config-item-add"
@click="addNewConfig"
>
<el-icon
class="el-icon-plus"
>
<div class="config-item config-item-add" @click="addNewConfig">
<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-row type="flex" justify="center" :span="24" class="set-default-container">
<el-button
class="set-default-btn"
type="success"
@@ -115,16 +93,19 @@ const curConfigList = ref<IStringKeyMap[]>([])
const defaultConfigId = ref('')
const store = useStore()
async function selectItem (id: string) {
async function selectItem(id: string) {
await triggerRPC<void>(IRPCActionType.UPLOADER_SELECT, type.value, id)
if (store?.state.defaultPicBed === type.value) {
sendRPC(IRPCActionType.TRAY_SET_TOOL_TIP, `${type.value} ${curConfigList.value.find(item => item._id === id)?._configName || ''}`)
sendRPC(
IRPCActionType.TRAY_SET_TOOL_TIP,
`${type.value} ${curConfigList.value.find(item => item._id === id)?._configName || ''}`
)
}
defaultConfigId.value = id
}
onBeforeRouteUpdate((to, _, next) => {
if (to.params.type && (to.name === UPLOADER_CONFIG_PAGE)) {
if (to.params.type && to.name === UPLOADER_CONFIG_PAGE) {
type.value = to.params.type as string
getCurrentConfigList()
}
@@ -136,13 +117,13 @@ onBeforeMount(() => {
getCurrentConfigList()
})
async function getCurrentConfigList () {
async function getCurrentConfigList() {
const configList = await triggerRPC<IUploaderConfigItem>(IRPCActionType.PICBED_GET_CONFIG_LIST, type.value)
curConfigList.value = configList?.configList ?? []
defaultConfigId.value = configList?.defaultId ?? ''
}
function openEditPage (configId: string) {
function openEditPage(configId: string) {
$router.push({
name: PICBEDS_PAGE,
params: {
@@ -155,18 +136,18 @@ function openEditPage (configId: string) {
})
}
function formatTime (time: number): string {
function formatTime(time: number): string {
return dayjs(time).format('YY/MM/DD HH:mm')
}
async function deleteConfig (id: string) {
async function deleteConfig(id: string) {
const res = await triggerRPC<IUploaderConfigItem>(IRPCActionType.PICBED_DELETE_CONFIG, type.value, id)
if (!res) return
curConfigList.value = res.configList
defaultConfigId.value = res.defaultId
}
function addNewConfig () {
function addNewConfig() {
$router.push({
name: PICBEDS_PAGE,
params: {
@@ -176,7 +157,7 @@ function addNewConfig () {
})
}
function setDefaultPicBed (type: string) {
function setDefaultPicBed(type: string) {
saveConfig({
[configPaths.picBed.current]: type,
[configPaths.picBed.uploader]: type
@@ -198,7 +179,7 @@ export default {
name: 'UploaderConfigPage'
}
</script>
<style lang='stylus'>
<style lang="stylus">
#config-list-view
position absolute
min-height 100%

View File

@@ -1,57 +1,23 @@
<template>
<div id="picbeds-page">
<el-row
:gutter="20"
class="setting-list"
>
<el-col
:span="22"
:offset="1"
>
<div
class="view-title"
>
<span
class="view-title-text"
@click="handleNameClick"
>
{{ picBedName }} {{ $T('SETTINGS') }}</span>
<el-row :gutter="20" class="setting-list">
<el-col :span="22" :offset="1">
<div class="view-title">
<span class="view-title-text" @click="handleNameClick"> {{ picBedName }} {{ $T('SETTINGS') }}</span>
<el-icon>
<Link />
</el-icon>
<el-button
type="primary"
round
size="small"
style="margin-left: 6px"
@click="handleCopyApi"
>
<el-button type="primary" round size="small" style="margin-left: 6px" @click="handleCopyApi">
{{ $T('UPLOAD_PAGE_COPY_UPLOAD_API') }}
</el-button>
</div>
<config-form
v-if="config.length > 0"
:id="type"
ref="$configForm"
:config="config"
type="uploader"
>
<config-form v-if="config.length > 0" :id="type" ref="$configForm" :config="config" type="uploader">
<el-form-item>
<el-button-group>
<el-button
class="confirm-btn"
type="info"
round
@click="handleReset"
>
<el-button class="confirm-btn" type="info" round @click="handleReset">
{{ $T('RESET_PICBED_CONFIG') }}
</el-button>
<el-button
class="confirm-btn"
type="success"
round
@click="handleConfirm"
>
<el-button class="confirm-btn" type="success" round @click="handleConfirm">
{{ $T('CONFIRM') }}
</el-button>
<el-button
@@ -64,17 +30,13 @@
<el-dropdown
ref="$dropdown"
placement="top"
style="color: #fff; font-size: 12px;width: 100%;"
style="color: #fff; font-size: 12px; width: 100%"
:disabled="picBedConfigList.length === 0"
teleported
>
{{ $T('MANAGE_LOGIN_PAGE_PANE_IMPORT') }}
<template #dropdown>
<el-dropdown-item
v-for="i in picBedConfigList"
:key="i._id"
@click="handleConfigImport(i)"
>
<el-dropdown-item v-for="i in picBedConfigList" :key="i._id" @click="handleConfigImport(i)">
{{ i._configName }}
</el-dropdown-item>
</template>
@@ -83,10 +45,7 @@
</el-button-group>
</el-form-item>
</config-form>
<div
v-else
class="single"
>
<div v-else class="single">
<div class="notice">
{{ $T('SETTINGS_NOT_CONFIG_OPTIONS') }}
</div>
@@ -98,9 +57,7 @@
<script lang="ts" setup>
import dayjs from 'dayjs'
import {
clipboard
} from 'electron'
import { clipboard } from 'electron'
import { ElDropdown, ElMessage } from 'element-plus'
import { Link } from '@element-plus/icons-vue'
import { ref, onBeforeMount } from 'vue'
@@ -144,27 +101,27 @@ const handleConfirm = async () => {
}
}
function handleMouseEnter () {
function handleMouseEnter() {
$dropdown.value?.handleOpen()
}
function handleMouseLeave () {
function handleMouseLeave() {
$dropdown.value?.handleClose()
}
async function getPicBeds () {
async function getPicBeds() {
const result = await triggerRPC<any>(IRPCActionType.PICBED_GET_PICBED_CONFIG, $route.params.type)
config.value = result.config
picBedName.value = result.name
}
async function getPicBedConfigList () {
const res = await triggerRPC<IUploaderConfigItem>(IRPCActionType.PICBED_GET_CONFIG_LIST, type.value) || undefined
async function getPicBedConfigList() {
const res = (await triggerRPC<IUploaderConfigItem>(IRPCActionType.PICBED_GET_CONFIG_LIST, type.value)) || undefined
const configList = res?.configList || []
picBedConfigList.value = configList.filter((item) => item._id !== $route.params.configId)
picBedConfigList.value = configList.filter(item => item._id !== $route.params.configId)
}
async function handleConfigImport (configItem: IUploaderConfigListItem) {
async function handleConfigImport(configItem: IUploaderConfigListItem) {
const { _id, _configName, _updatedAt, _createdAt, ...rest } = configItem
for (const key in rest) {
if (Object.prototype.hasOwnProperty.call(rest, key)) {
@@ -186,19 +143,19 @@ const handleReset = async () => {
$router.back()
}
async function handleNameClick () {
const lang = await getConfig(configPaths.settings.language) || II18nLanguage.ZH_CN
async function handleNameClick() {
const lang = (await getConfig(configPaths.settings.language)) || II18nLanguage.ZH_CN
const url = picBedManualUrlList[lang === II18nLanguage.EN ? 'en' : 'zh_cn'][$route.params.type as string]
if (url) {
sendRPC(IRPCActionType.OPEN_URL, url)
}
}
async function handleCopyApi () {
async function handleCopyApi() {
try {
const { port = 36677, host = '127.0.0.1' } = await getConfig<IStringKeyMap>(configPaths.settings.server) || {}
const serverKey = await getConfig(configPaths.settings.serverKey) || ''
const uploader = await getConfig(configPaths.uploader) as IStringKeyMap || {}
const { port = 36677, host = '127.0.0.1' } = (await getConfig<IStringKeyMap>(configPaths.settings.server)) || {}
const serverKey = (await getConfig(configPaths.settings.serverKey)) || ''
const uploader = ((await getConfig(configPaths.uploader)) as IStringKeyMap) || {}
const picBedConfigList = uploader[$route.params.type as string].configList || []
const picBedConfig = picBedConfigList.find((item: IUploaderConfigListItem) => item._id === $route.params.configId)
if (!picBedConfig) {
@@ -221,7 +178,7 @@ export default {
}
</script>
<style lang='stylus'>
<style lang="stylus">
#picbeds-page
height 100%
overflow-y auto