Feature: add remote file delete , picBed management

First version of PicList.
In album, you can delete remote file now.
Add picBed management
function.
This commit is contained in:
萌萌哒赫萝
2023-02-15 23:36:47 +08:00
parent 7421322475
commit efeadb8fb8
355 changed files with 12428 additions and 883 deletions

View File

@@ -10,6 +10,15 @@
<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;"
>同步删除云端
<el-switch
v-model="deleteCloud"
:active-text="$T('SETTINGS_OPEN')"
:inactive-text="$T('SETTINGS_CLOSE')"
@change="handleDeleteCloudFile"
/></span>
</div>
<transition name="el-zoom-in-top">
<el-row v-show="handleBarActive">
@@ -79,7 +88,7 @@
<el-col :span="4">
<div
class="item-base copy round"
:class="{ active: isMultiple(choosedList)}"
:class="{ active: isMultiple(choosedList) }"
@click="multiCopy"
>
{{ $T('COPY') }}
@@ -88,7 +97,7 @@
<el-col :span="4">
<div
class="item-base delete round"
:class="{ active: isMultiple(choosedList)}"
:class="{ active: isMultiple(choosedList) }"
@click="multiRemove"
>
{{ $T('DELETE') }}
@@ -97,10 +106,10 @@
<el-col :span="4">
<div
class="item-base all-pick round"
:class="{ active: filterList.length > 0}"
:class="{ active: filterList.length > 0 }"
@click="toggleSelectAll"
>
{{ isAllSelected ? $T('CANCEL') : $T('SELECT_ALL') }}
{{ isAllSelected? $T('CANCEL'): $T('SELECT_ALL') }}
</div>
</el-col>
</el-row>
@@ -128,7 +137,11 @@
<el-col
v-for="(item, index) in filterList"
:key="item.id"
:span="6"
:xs="24"
:sm="8"
:md="6"
:lg="4"
:xl="3"
class="gallery-list__img"
>
<div
@@ -166,7 +179,7 @@
</el-icon>
<el-icon
class="cursor-pointer delete"
@click="remove(item.id)"
@click="remove(item)"
>
<Delete />
</el-icon>
@@ -187,9 +200,7 @@
:modal-append-to-body="false"
>
<el-input v-model="imgInfo.imgUrl" />
<template
#footer
>
<template #footer>
<el-button @click="dialogVisible = false">
{{ $T('CANCEL') }}
</el-button>
@@ -206,7 +217,7 @@
<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 { CheckboxValueType, ElMessageBox, ElNotification } from 'element-plus'
import { Close, CaretBottom, Document, Edit, Delete, CaretTop } from '@element-plus/icons-vue'
import {
ipcRenderer,
@@ -218,6 +229,7 @@ import { getConfig, saveConfig, sendToMain } from '@/utils/dataSender'
import { onBeforeRouteUpdate } from 'vue-router'
import { T as $T } from '@/i18n/index'
import $$db from '@/utils/db'
import ALLApi from '@/apis/allApi'
const images = ref<ImgInfo[]>([])
const dialogVisible = ref(false)
const imgInfo = reactive({
@@ -230,6 +242,7 @@ const gallerySliderControl = reactive({
visible: false,
index: 0
})
const deleteCloud = ref<boolean>(false)
const choosedPicBed = ref<string[]>([])
const lastChoosed = ref<number>(-1)
const isShiftKeyPress = ref<boolean>(false)
@@ -253,6 +266,12 @@ onBeforeRouteUpdate((to, from) => {
}
})
// init deleteCloud
async function initDeleteCloud () {
const config = await getConfig() as any
deleteCloud.value = config.settings.deleteCloudFile || false
}
onBeforeMount(async () => {
ipcRenderer.on('updateGallery', () => {
nextTick(async () => {
@@ -396,15 +415,37 @@ async function copy (item: ImgInfo) {
}
}
function remove (id?: string) {
if (id) {
function remove (item: ImgInfo) {
if (item.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)
const file = await $$db.getById(item.id!)
await $$db.removeById(item.id!)
const picBedsCanbeDeleted = ['smms', 'github', 'imgur', 'tcyun', 'aliyun', 'qiniu', 'upyun']
if (await getConfig('settings.deleteCloudFile')) {
if (item.type !== undefined && picBedsCanbeDeleted.includes(item.type)) {
setTimeout(() => {
ALLApi.delete(item).then((value: boolean) => {
if (value) {
ElNotification({
title: '通知',
message: `${item.fileName} 云端删除成功`,
type: 'success'
})
} else {
ElNotification({
title: '通知',
message: `${item.fileName} 云端删除失败`,
type: 'error'
})
}
})
}, 0)
}
}
sendToMain('removeFiles', [file])
const obj = {
title: $T('OPERATION_SUCCEED'),
@@ -422,6 +463,12 @@ function remove (id?: string) {
}
}
function handleDeleteCloudFile (val: ICheckBoxValueType) {
saveConfig({
'settings.deleteCloudFile': val
})
}
function openDialog (item: ImgInfo) {
imgInfo.id = item.id!
imgInfo.imgUrl = item.imgUrl as string
@@ -435,7 +482,6 @@ async function confirmModify () {
const obj = {
title: $T('CHANGE_IMAGE_URL_SUCCEED'),
body: imgInfo.imgUrl
// icon: this.imgInfo.imgUrl
}
const myNotification = new Notification(obj.title, obj)
myNotification.onclick = () => {
@@ -445,15 +491,6 @@ async function confirmModify () {
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 = ''
}
@@ -482,13 +519,49 @@ function multiRemove () {
}).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)
const isDeleteCloudFile = await getConfig('settings.deleteCloudFile')
const picBedsCanbeDeleted = ['smms', 'github', 'imgur', 'tcyun', 'aliyun', 'qiniu', 'upyun']
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)) {
setTimeout(() => {
ALLApi.delete(file).then((value: boolean) => {
if (value) {
ElNotification({
title: '通知',
message: `${file.fileName} 云端删除成功`,
type: 'success',
duration: multiRemoveNumber > 5 ? 1000 : 2000
})
} else {
ElNotification({
title: '通知',
message: `${file.fileName} 云端删除失败`,
type: 'error',
duration: multiRemoveNumber > 5 ? 1000 : 2000
})
}
})
}, 0)
}
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)
}
}
}
}
@@ -555,6 +628,7 @@ onBeforeUnmount(() => {
onActivated(async () => {
pasteStyle.value = (await getConfig('settings.pasteStyle')) || 'markdown'
initDeleteCloud()
})
</script>
@@ -623,7 +697,7 @@ export default {
.pull-right
float right
.gallery-list
height 360px
height 100%
box-sizing border-box
padding 8px 0
overflow-y auto
@@ -633,7 +707,7 @@ export default {
transition all .2s ease-in-out .1s
width 100%
&.small
height: 287px
height: 100%
top: 113px
&__img
// height 150px

View File

@@ -4,7 +4,6 @@
: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' }"
@@ -28,8 +27,7 @@
</div>
</template>
<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 {
@@ -163,12 +161,6 @@ function handleMouseMove (e: MouseEvent) {
width: 64,
height: 64
})
// remote.BrowserWindow.getFocusedWindow()!.setBounds({
// x: xLoc,
// y: yLoc,
// width: 64,
// height: 64
// })
}
}

View File

@@ -27,11 +27,10 @@
<el-form-item
:label="$T('SETTINGS_CHOOSE_LANGUAGE')"
>
<!-- <el-button type="primary" round size="small" @click="openFile('data.json')">{{ $T('SETTINGS_CLICK_TO_OPEN') }}</el-button> -->
<el-select
v-model="currentLanguage"
size="small"
style="width: 100%"
style="width: 50%"
:placeholder="$T('SETTINGS_CHOOSE_LANGUAGE')"
@change="handleLanguageChange"
>
@@ -137,17 +136,6 @@
@change="updateHelperChange"
/>
</el-form-item>
<el-form-item
v-show="form.updateHelper"
:label="$T('SETTINGS_ACCEPT_BETA_UPDATE')"
>
<el-switch
v-model="form.checkBetaUpdate"
:active-text="$T('SETTINGS_OPEN')"
:inactive-text="$T('SETTINGS_CLOSE')"
@change="checkBetaUpdateChange"
/>
</el-form-item>
<el-form-item
:label="$T('SETTINGS_LAUNCH_ON_BOOT')"
>
@@ -158,6 +146,16 @@
@change="handleAutoStartChange"
/>
</el-form-item>
<el-form-item
label="相册内删除时同步删除云端文件"
>
<el-switch
v-model="form.deleteCloudFile"
:active-text="$T('SETTINGS_OPEN')"
:inactive-text="$T('SETTINGS_CLOSE')"
@change="handleDeleteCloudFile"
/>
</el-form-item>
<el-form-item
:label="$T('SETTINGS_RENAME_BEFORE_UPLOAD')"
>
@@ -247,6 +245,10 @@
/>
</el-checkbox-group>
</el-form-item>
<el-divider
border-style="none"
/>
<el-form-item />
</el-form>
</el-row>
</el-col>
@@ -403,7 +405,7 @@
type="primary"
round
size="small"
@click="openFile('picgo.log')"
@click="openFile('piclist.log')"
>
{{ $T('SETTINGS_CLICK_TO_OPEN') }}
</el-button>
@@ -520,7 +522,7 @@
import { ElForm, ElMessage as $message, FormRules } from 'element-plus'
import { Reading, QuestionFilled } from '@element-plus/icons-vue'
import pkg from 'root/package.json'
import { IConfig } from 'picgo'
import { IConfig } from 'piclist'
import { PICGO_OPEN_FILE, OPEN_URL, GET_PICBEDS } from '#/events/constants'
import {
ipcRenderer
@@ -529,7 +531,7 @@ import { i18nManager, T as $T } from '@/i18n/index'
import { enforceNumber } from '~/universal/utils/common'
import { getLatestVersion } from '#/utils/getLatestVersion'
import { compare } from 'compare-versions'
import { STABLE_RELEASE_URL, BETA_RELEASE_URL } from '#/utils/static'
import { STABLE_RELEASE_URL } from '#/utils/static'
import { computed, onBeforeMount, onBeforeUnmount, reactive, ref } from 'vue'
import { getConfig, saveConfig, sendToMain } from '@/utils/dataSender'
import { useRouter } from 'vue-router'
@@ -558,7 +560,8 @@ const form = reactive<ISettingForm>({
checkBetaUpdate: true,
useBuiltinClipboard: false,
language: 'zh-CN',
logFileSizeLimit: 10
logFileSizeLimit: 10,
deleteCloudFile: false
})
const languageList = i18nManager.languageList.map(item => ({
@@ -643,6 +646,7 @@ async function initData () {
form.checkBetaUpdate = settings.checkBetaUpdate === undefined ? true : settings.checkBetaUpdate
form.useBuiltinClipboard = settings.useBuiltinClipboard === undefined ? false : settings.useBuiltinClipboard
form.language = settings.language ?? 'zh-CN'
form.deleteCloudFile = settings.deleteCloudFile || false
currentLanguage.value = settings.language ?? 'zh-CN'
customLink.value = settings.customLink || '$url'
shortKey.upload = settings.shortKey.upload
@@ -728,10 +732,6 @@ function updateHelperChange (val: ICheckBoxValueType) {
saveConfig('settings.showUpdateTip', val)
}
function checkBetaUpdateChange (val: ICheckBoxValueType) {
saveConfig('settings.checkBetaUpdate', val)
}
function useBuiltinClipboardChange (val: ICheckBoxValueType) {
saveConfig('settings.useBuiltinClipboard', val)
}
@@ -756,6 +756,12 @@ function handleAutoStartChange (val: ICheckBoxValueType) {
sendToMain('autoStart', val)
}
function handleDeleteCloudFile (val: ICheckBoxValueType) {
saveConfig({
'settings.deleteCloudFile': val
})
}
function handleRename (val: ICheckBoxValueType) {
saveConfig({
'settings.rename': val
@@ -774,7 +780,7 @@ function compareVersion2Update (current: string, latest: string): boolean {
async function checkUpdate () {
checkUpdateVisible.value = true
const version = await getLatestVersion(form.checkBetaUpdate)
const version = await getLatestVersion()
if (version) {
latestVersion.value = version
} else {
@@ -784,7 +790,7 @@ async function checkUpdate () {
function confirmCheckVersion () {
if (needUpdate.value) {
sendToMain(OPEN_URL, form.checkBetaUpdate ? BETA_RELEASE_URL : STABLE_RELEASE_URL)
sendToMain(OPEN_URL, STABLE_RELEASE_URL)
}
checkUpdateVisible.value = false
}

View File

@@ -1,9 +1,11 @@
<template>
<div id="upload-view">
<el-row :gutter="16">
<el-row
:gutter="16"
align="middle"
>
<el-col
:span="20"
:offset="2"
:span="24"
>
<div class="view-title">
{{ $T('PICTURE_UPLOAD') }} - {{ picBedName }}
@@ -47,7 +49,7 @@
:status="showError ? 'exception' : undefined"
/>
<div class="paste-style">
<div class="el-col-16">
<div class="el-col-12">
<div class="paste-style__text">
{{ $T('LINK_FORMAT') }}
</div>
@@ -56,14 +58,27 @@
size="small"
@change="handlePasteStyleChange"
>
<el-radio-button label="markdown">
<el-radio-button
label="markdown"
title="![alt](url)"
>
Markdown
</el-radio-button>
<el-radio-button label="HTML" />
<el-radio-button label="URL" />
<el-radio-button label="UBB" />
<el-radio-button
label="Custom"
label="HTML"
title="<img src='url'/>"
/>
<el-radio-button
label="URL"
title="http://test.com/test.png"
/>
<el-radio-button
label="UBB"
title="[img]url[/img]"
/>
<!--TODO 修改title为用户具体设置的格式-->
<el-radio-button
:label="$T('CUSTOM')"
:title="$T('CUSTOM')"
/>
</el-radio-group>
@@ -99,7 +114,6 @@
</div>
</template>
<script lang="ts" setup>
// import { Component, Vue, Watch } from 'vue-property-decorator'
import { UploadFilled, CaretBottom } from '@element-plus/icons-vue'
import {
ipcRenderer,
@@ -127,7 +141,7 @@ const pasteStyle = ref('')
const picBed = ref<IPicBedType[]>([])
const picBedName = ref('')
onBeforeMount(() => {
ipcRenderer.on('uploadProgress', (event: IpcRendererEvent, _progress: number) => {
ipcRenderer.on('uploadProgress', (_event: IpcRendererEvent, _progress: number) => {
if (_progress !== -1) {
showProgress.value = true
progress.value = _progress
@@ -269,7 +283,7 @@ async function getDefaultPicBed () {
})
}
function getPicBeds (event: Event, picBeds: IPicBedType[]) {
function getPicBeds (_event: Event, picBeds: IPicBedType[]) {
picBed.value = picBeds
getDefaultPicBed()
}
@@ -295,13 +309,13 @@ export default {
#upload-view
height 100%
.view-title
margin 20px auto
margin 10vh auto 10px
#upload-area
height 400px
height 50vh
border 2px dashed #dddddd
border-radius 8px
text-align center
width 800px
width 60vw
margin 0 auto
color #dddddd
cursor pointer
@@ -309,15 +323,16 @@ export default {
align-items center
#upload-dragger
height 100%
item-align center
&.is-dragover,
&:hover
border 2px dashed #A4D8FA
background-color rgba(164, 216, 250, 0.3)
color #fff
i
font-size 66px
margin 50px 0 16px
line-height 66px
height 80%
font-size 10vh
margin 0
span
color #409EFF
#file-uploader

View File

@@ -98,7 +98,7 @@ export default {
<style lang='stylus'>
#picbeds-page
.setting-list
height 425px
height 100%
overflow-y auto
overflow-x hidden
.confirm-btn