mirror of
https://github.com/Kuingsmile/PicList.git
synced 2026-09-05 07:28:42 +08:00
🐛 Fix: gallery db bug
This commit is contained in:
@@ -212,7 +212,7 @@ export function createTray () {
|
||||
if (imgs !== false) {
|
||||
const pasteText: string[] = []
|
||||
for (let i = 0; i < imgs.length; i++) {
|
||||
pasteText.push(pasteTemplate(pasteStyle, imgs[i]))
|
||||
pasteText.push(pasteTemplate(pasteStyle, imgs[i], db.get('settings.customLink')))
|
||||
const notification = new Notification({
|
||||
title: '上传成功',
|
||||
body: imgs[i].imgUrl!,
|
||||
|
||||
@@ -16,7 +16,7 @@ export const uploadClipboardFiles = async (): Promise<string> => {
|
||||
if (img.length > 0) {
|
||||
const trayWindow = windowManager.get(IWindowList.TRAY_WINDOW)
|
||||
const pasteStyle = db.get('settings.pasteStyle') || 'markdown'
|
||||
handleCopyUrl(pasteTemplate(pasteStyle, img[0]))
|
||||
handleCopyUrl(pasteTemplate(pasteStyle, img[0], db.get('settings.customLink')))
|
||||
const notification = new Notification({
|
||||
title: '上传成功',
|
||||
body: img[0].imgUrl!,
|
||||
@@ -52,7 +52,7 @@ export const uploadChoosedFiles = async (webContents: WebContents, files: IFileW
|
||||
const pasteStyle = db.get('settings.pasteStyle') || 'markdown'
|
||||
const pasteText: string[] = []
|
||||
for (let i = 0; i < imgs.length; i++) {
|
||||
pasteText.push(pasteTemplate(pasteStyle, imgs[i]))
|
||||
pasteText.push(pasteTemplate(pasteStyle, imgs[i], db.get('settings.customLink')))
|
||||
const notification = new Notification({
|
||||
title: '上传成功',
|
||||
body: imgs[i].imgUrl!,
|
||||
|
||||
@@ -81,6 +81,8 @@ function dbPathChecker (): string {
|
||||
return defaultConfigPath
|
||||
}
|
||||
|
||||
export const defaultConfigPath = configFilePath
|
||||
|
||||
export {
|
||||
dbChecker,
|
||||
dbPathChecker
|
||||
|
||||
@@ -4,7 +4,9 @@ import {
|
||||
Notification,
|
||||
ipcMain
|
||||
} from 'electron'
|
||||
import db, { GalleryDB } from '~/main/apis/core/datastore'
|
||||
import path from 'path'
|
||||
import db, { GalleryDB } from 'apis/core/datastore'
|
||||
import { dbPathChecker, defaultConfigPath } from 'apis/core/datastore/dbChecker'
|
||||
import uploader from 'apis/app/uploader'
|
||||
import pasteTemplate from '#/utils/pasteTemplate'
|
||||
import { handleCopyUrl } from '~/main/utils/common'
|
||||
@@ -15,6 +17,8 @@ import {
|
||||
import {
|
||||
SHOW_INPUT_BOX
|
||||
} from '~/universal/events/constants'
|
||||
import { DBStore } from '@picgo/store'
|
||||
type PromiseResType<T> = T extends Promise<infer R> ? R : T
|
||||
|
||||
// Cross-process support may be required in the future
|
||||
class GuiApi implements IGuiApi {
|
||||
@@ -79,7 +83,7 @@ class GuiApi implements IGuiApi {
|
||||
const pasteStyle = db.get('settings.pasteStyle') || 'markdown'
|
||||
const pasteText: string[] = []
|
||||
for (let i = 0; i < imgs.length; i++) {
|
||||
pasteText.push(pasteTemplate(pasteStyle, imgs[i]))
|
||||
pasteText.push(pasteTemplate(pasteStyle, imgs[i], db.get('settings.customLink')))
|
||||
const notification = new Notification({
|
||||
title: '上传成功',
|
||||
body: imgs[i].imgUrl as string,
|
||||
@@ -128,6 +132,44 @@ class GuiApi implements IGuiApi {
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* get picgo config/data path
|
||||
*/
|
||||
async getConfigPath () {
|
||||
const currentConfigPath = dbPathChecker()
|
||||
const galleryDBPath = path.join(path.dirname(currentConfigPath), 'picgo.db')
|
||||
return {
|
||||
defaultConfigPath,
|
||||
currentConfigPath,
|
||||
galleryDBPath
|
||||
}
|
||||
}
|
||||
|
||||
get galleryDB (): DBStore {
|
||||
return new Proxy<DBStore>(GalleryDB.getInstance(), {
|
||||
get (target, prop: keyof DBStore) {
|
||||
if (prop === 'removeById') {
|
||||
return new Promise((resolve) => {
|
||||
const guiApi = GuiApi.getInstance()
|
||||
guiApi.showMessageBox({
|
||||
title: '警告',
|
||||
message: '有插件正在试图删除一些相册文件,是否继续',
|
||||
type: 'info',
|
||||
buttons: ['Yes', 'No']
|
||||
}).then(res => {
|
||||
if (res.result === 0) {
|
||||
resolve(Reflect.get(target, prop))
|
||||
} else {
|
||||
resolve(() => {})
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
return Reflect.get(target, prop)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default GuiApi
|
||||
|
||||
@@ -32,7 +32,7 @@ export default {
|
||||
const img = await uploader.setWebContents(trayWindow.webContents).upload()
|
||||
if (img !== false) {
|
||||
const pasteStyle = db.get('settings.pasteStyle') || 'markdown'
|
||||
handleCopyUrl(pasteTemplate(pasteStyle, img[0]))
|
||||
handleCopyUrl(pasteTemplate(pasteStyle, img[0], db.get('settings.customLink')))
|
||||
const notification = new Notification({
|
||||
title: '上传成功',
|
||||
body: img[0].imgUrl!,
|
||||
|
||||
@@ -28,7 +28,7 @@ import {
|
||||
} from '#/events/constants'
|
||||
|
||||
import { GalleryDB } from 'apis/core/datastore'
|
||||
import { IObject } from '@picgo/store/dist/types'
|
||||
import { IObject, IFilter } from '@picgo/store/dist/types'
|
||||
|
||||
// eslint-disable-next-line
|
||||
const requireFunc = typeof __webpack_require__ === 'function' ? __non_webpack_require__ : require
|
||||
@@ -283,10 +283,10 @@ const handleImportLocalPlugin = () => {
|
||||
}
|
||||
|
||||
const handlePicGoGalleryDB = () => {
|
||||
ipcMain.on(PICGO_GET_DB, async (event: IpcMainEvent, callbackId: string) => {
|
||||
ipcMain.on(PICGO_GET_DB, async (event: IpcMainEvent, filter: IFilter, callbackId: string) => {
|
||||
const dbStore = GalleryDB.getInstance()
|
||||
const res = await dbStore.get()
|
||||
event.sender.send(PICGO_GET_CONFIG, res, callbackId)
|
||||
const res = await dbStore.get(filter)
|
||||
event.sender.send(PICGO_GET_DB, res, callbackId)
|
||||
})
|
||||
|
||||
ipcMain.on(PICGO_INSERT_DB, async (event: IpcMainEvent, value: IObject, callbackId: string) => {
|
||||
|
||||
@@ -55,7 +55,7 @@ const handleStartUpFiles = (argv: string[], cwd: string) => {
|
||||
}
|
||||
|
||||
class LifeCycle {
|
||||
private async beforeReady () {
|
||||
private beforeReady () {
|
||||
protocol.registerSchemesAsPrivileged([{ scheme: 'picgo', privileges: { secure: true, standard: true } }])
|
||||
// fix the $PATH in macOS
|
||||
fixPath()
|
||||
@@ -63,10 +63,11 @@ class LifeCycle {
|
||||
ipcList.listen()
|
||||
busEventList.listen()
|
||||
updateShortKeyFromVersion212(db, db.get('settings.shortKey'))
|
||||
await migrateGalleryFromVersion230(db, GalleryDB.getInstance())
|
||||
}
|
||||
private onReady () {
|
||||
app.on('ready', async () => {
|
||||
console.log('on ready')
|
||||
await migrateGalleryFromVersion230(db, GalleryDB.getInstance())
|
||||
createProtocol('picgo')
|
||||
if (isDevelopment && !process.env.IS_TEST) {
|
||||
// Install Vue Devtools
|
||||
@@ -169,7 +170,7 @@ class LifeCycle {
|
||||
if (!gotTheLock) {
|
||||
app.quit()
|
||||
} else {
|
||||
await this.beforeReady()
|
||||
this.beforeReady()
|
||||
this.onReady()
|
||||
this.onRunning()
|
||||
this.onQuit()
|
||||
|
||||
@@ -38,10 +38,11 @@ const migrateGalleryFromVersion230 = async (configDB: typeof ConfigStore, galler
|
||||
if (fse.existsSync(configBakPath)) {
|
||||
return
|
||||
}
|
||||
fse.copyFileSync(configPath, configBakPath)
|
||||
// migrate gallery from config to gallery db
|
||||
if (originGallery && originGallery.length > 0) {
|
||||
if (originGallery && originGallery?.length > 0) {
|
||||
fse.copyFileSync(configPath, configBakPath)
|
||||
await galleryDB.insertMany(originGallery)
|
||||
configDB.set('uploaded', [])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -103,6 +103,7 @@ class Server {
|
||||
})
|
||||
}
|
||||
startup () {
|
||||
console.log('startup', this.config.enable)
|
||||
if (this.config.enable) {
|
||||
this.listen(this.config.port)
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import fs from 'fs-extra'
|
||||
import path from 'path'
|
||||
import os from 'os'
|
||||
import { remote, app } from 'electron'
|
||||
import pkg from 'root/package.json'
|
||||
import { dbPathChecker } from 'apis/core/datastore/dbChecker'
|
||||
|
||||
const APP = process.type === 'renderer' ? remote.app : app
|
||||
const STORE_PATH = APP.getPath('userData')
|
||||
const configPath = dbPathChecker()
|
||||
const CONFIG_DIR = path.dirname(configPath)
|
||||
|
||||
function injectPicGoVersion () {
|
||||
global.PICGO_GUI_VERSION = pkg.version
|
||||
@@ -41,7 +41,7 @@ function resolveMacWorkFlow () {
|
||||
*/
|
||||
function resolveClipboardImageGenerator () {
|
||||
let clipboardFiles = getClipboardFiles()
|
||||
if (!fs.pathExistsSync(path.join(STORE_PATH, 'windows10.ps1'))) {
|
||||
if (!fs.pathExistsSync(path.join(CONFIG_DIR, 'windows10.ps1'))) {
|
||||
clipboardFiles.forEach(item => {
|
||||
fs.copyFileSync(item.origin, item.dest)
|
||||
})
|
||||
@@ -52,10 +52,15 @@ function resolveClipboardImageGenerator () {
|
||||
}
|
||||
|
||||
function diffFilesAndUpdate (filePath1: string, filePath2: string) {
|
||||
let file1 = fs.readFileSync(filePath1)
|
||||
let file2 = fs.readFileSync(filePath2)
|
||||
try {
|
||||
let file1 = fs.existsSync(filePath1) && fs.readFileSync(filePath1)
|
||||
let file2 = fs.existsSync(filePath1) && fs.readFileSync(filePath2)
|
||||
|
||||
if (!file1.equals(file2)) {
|
||||
if (!file1 || !file2 || !file1.equals(file2)) {
|
||||
fs.copyFileSync(filePath1, filePath2)
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
fs.copyFileSync(filePath1, filePath2)
|
||||
}
|
||||
}
|
||||
@@ -65,13 +70,14 @@ function resolveClipboardImageGenerator () {
|
||||
'/linux.sh',
|
||||
'/mac.applescript',
|
||||
'/windows.ps1',
|
||||
'/windows10.ps1'
|
||||
'/windows10.ps1',
|
||||
'/wsl.sh'
|
||||
]
|
||||
|
||||
return files.map(item => {
|
||||
return {
|
||||
origin: path.join(__static, item),
|
||||
dest: path.join(STORE_PATH, item)
|
||||
dest: path.join(CONFIG_DIR, item)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -71,12 +71,12 @@
|
||||
<el-col :span="20" :offset="2">
|
||||
<el-row :gutter="16">
|
||||
<gallerys
|
||||
:images="images"
|
||||
:images="filterList"
|
||||
:index="idx"
|
||||
@close="handleClose"
|
||||
:options="options"
|
||||
></gallerys>
|
||||
<el-col :span="6" v-for="(item, index) in images" :key="item.id" class="gallery-list__img">
|
||||
<el-col :span="6" v-for="(item, index) in filterList" :key="item.id" class="gallery-list__img">
|
||||
<div
|
||||
class="gallery-list__item"
|
||||
@click="zoomImage(index)"
|
||||
@@ -162,12 +162,12 @@ export default class extends Vue {
|
||||
async created () {
|
||||
ipcRenderer.on('updateGallery', (event: IpcRendererEvent) => {
|
||||
this.$nextTick(async () => {
|
||||
this.images = await this.$$db.get()
|
||||
this.updateGallery()
|
||||
})
|
||||
})
|
||||
ipcRenderer.send('getPicBeds')
|
||||
ipcRenderer.on('getPicBeds', this.getPicBeds)
|
||||
this.images = await this.$$db.get()
|
||||
this.updateGallery()
|
||||
}
|
||||
mounted () {
|
||||
document.addEventListener('keydown', this.handleDetectShiftKey)
|
||||
@@ -212,6 +212,9 @@ export default class extends Vue {
|
||||
return this.images
|
||||
}
|
||||
}
|
||||
async updateGallery () {
|
||||
this.images = (await this.$$db.get({ orderBy: 'desc' })).data
|
||||
}
|
||||
|
||||
@Watch('filterList')
|
||||
handleFilterListChange () {
|
||||
@@ -257,7 +260,8 @@ export default class extends Vue {
|
||||
}
|
||||
async copy (item: ImgInfo) {
|
||||
const style = await this.getConfig<IPasteStyle>('settings.pasteStyle') || IPasteStyle.MARKDOWN
|
||||
const copyLink = pasteStyle(style, item)
|
||||
const customLink = await this.getConfig<string>('settings.customLink')
|
||||
const copyLink = pasteStyle(style, item, customLink)
|
||||
const obj = {
|
||||
title: '复制链接成功',
|
||||
body: copyLink,
|
||||
@@ -286,7 +290,7 @@ export default class extends Vue {
|
||||
myNotification.onclick = () => {
|
||||
return true
|
||||
}
|
||||
this.getGallery()
|
||||
this.updateGallery()
|
||||
}).catch((e) => {
|
||||
console.log(e)
|
||||
return true
|
||||
@@ -311,7 +315,7 @@ export default class extends Vue {
|
||||
return true
|
||||
}
|
||||
this.dialogVisible = false
|
||||
this.getGallery()
|
||||
this.updateGallery()
|
||||
}
|
||||
choosePicBed (type: string) {
|
||||
let idx = this.choosedPicBed.indexOf(type)
|
||||
@@ -356,7 +360,6 @@ export default class extends Vue {
|
||||
}
|
||||
this.clearChoosedList()
|
||||
this.choosedList = {} // 只有删除才能将这个置空
|
||||
this.getGallery()
|
||||
const obj = {
|
||||
title: '操作结果',
|
||||
body: '删除成功'
|
||||
@@ -366,6 +369,7 @@ export default class extends Vue {
|
||||
myNotification.onclick = () => {
|
||||
return true
|
||||
}
|
||||
this.updateGallery()
|
||||
}).catch(() => {
|
||||
return true
|
||||
})
|
||||
@@ -375,6 +379,7 @@ export default class extends Vue {
|
||||
if (Object.values(this.choosedList).some(item => item)) {
|
||||
const copyString: string[] = []
|
||||
const style = await this.getConfig<IPasteStyle>('settings.pasteStyle') || IPasteStyle.MARKDOWN
|
||||
const customLink = await this.getConfig<string>('settings.customLink')
|
||||
// choosedList -> { [id]: true or false }; true means choosed. false means not choosed.
|
||||
const imageIDList = Object.keys(this.choosedList)
|
||||
for (let i = 0; i < imageIDList.length; i++) {
|
||||
@@ -382,7 +387,7 @@ export default class extends Vue {
|
||||
if (this.choosedList[key]) {
|
||||
const item = await this.$$db.getById<ImgInfo>(key)
|
||||
if (item) {
|
||||
copyString.push(pasteStyle(style, item))
|
||||
copyString.push(pasteStyle(style, item, customLink))
|
||||
this.choosedList[key] = false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,14 +50,15 @@ export default class extends Vue {
|
||||
return this.files.slice().reverse()
|
||||
}
|
||||
async getData () {
|
||||
this.files = (await this.$$db.get<ImgInfo>()).slice().reverse().slice(0, 5)
|
||||
this.files = (await this.$$db.get<ImgInfo>({ orderBy: 'desc', limit: 5 })).data
|
||||
}
|
||||
async copyTheLink (item: ImgInfo) {
|
||||
this.notification.body = item.imgUrl!
|
||||
this.notification.icon = item.imgUrl!
|
||||
const myNotification = new Notification(this.notification.title, this.notification)
|
||||
const pasteStyle = await this.getConfig<IPasteStyle>('settings.pasteStyle') || IPasteStyle.MARKDOWN
|
||||
clipboard.writeText(pasteTemplate(pasteStyle, item))
|
||||
const customLink = await this.getConfig<string>('settings.customLink')
|
||||
clipboard.writeText(pasteTemplate(pasteStyle, item, customLink))
|
||||
myNotification.onclick = () => {
|
||||
return true
|
||||
}
|
||||
@@ -90,13 +91,13 @@ export default class extends Vue {
|
||||
const item = files[i]
|
||||
await this.$$db.insert(item)
|
||||
}
|
||||
this.files = (await this.$$db.get<ImgInfo>()).slice().reverse().slice(0, 5)
|
||||
this.files = (await this.$$db.get<ImgInfo>({ orderBy: 'desc', limit: 5 })).data
|
||||
})
|
||||
ipcRenderer.on('clipboardFiles', (event: Event, files: ImgInfo[]) => {
|
||||
this.clipboardFiles = files
|
||||
})
|
||||
ipcRenderer.on('uploadFiles', async (event: Event) => {
|
||||
this.files = (await this.$$db.get()).slice().reverse().slice(0, 5)
|
||||
this.files = (await this.$$db.get<ImgInfo>({ orderBy: 'desc', limit: 5 })).data
|
||||
console.log(this.files)
|
||||
this.uploadFlag = false
|
||||
})
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { IObject, IResult } from '@picgo/store/dist/types'
|
||||
import { IObject, IResult, IGetResult, IFilter } from '@picgo/store/dist/types'
|
||||
import { ipcRenderer, IpcRendererEvent } from 'electron'
|
||||
import { uuid } from 'uuidv4'
|
||||
import {
|
||||
@@ -11,8 +11,8 @@ import {
|
||||
} from '#/events/constants'
|
||||
import { IGalleryDB } from '#/types/extra-vue'
|
||||
export class GalleryDB implements IGalleryDB {
|
||||
async get<T> (): Promise<IResult<T>[]> {
|
||||
const res = await this.msgHandler<IResult<T>[]>(PICGO_GET_DB)
|
||||
async get<T> (filter?: IFilter): Promise<IGetResult<T>> {
|
||||
const res = await this.msgHandler<IGetResult<T>>(PICGO_GET_DB, filter)
|
||||
return res
|
||||
}
|
||||
async insert<T> (value: T): Promise<IResult<T>> {
|
||||
|
||||
Vendored
+2
-2
@@ -1,9 +1,9 @@
|
||||
import VueRouter, { Route } from 'vue-router'
|
||||
import axios from 'axios'
|
||||
import { IObject, IResult } from '@picgo/store/dist/types'
|
||||
import { IObject, IResult, IGetResult, IFilter } from '@picgo/store/dist/types'
|
||||
|
||||
interface IGalleryDB {
|
||||
get<T>(): Promise<IResult<T>[]>
|
||||
get<T>(filter?: IFilter): Promise<IGetResult<T>>
|
||||
insert<T> (value: T): Promise<IResult<T>>
|
||||
insertMany<T> (value: T[]): Promise<IResult<T>[]>
|
||||
updateById (id: string, value: IObject): Promise<boolean>
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import db from '~/main/apis/core/datastore'
|
||||
import { IPasteStyle } from '#/types/enum'
|
||||
import { handleUrlEncode } from './common'
|
||||
|
||||
@@ -19,15 +18,15 @@ const formatCustomLink = (customLink: string, item: ImgInfo) => {
|
||||
return customLink
|
||||
}
|
||||
|
||||
export default (style: IPasteStyle, item: ImgInfo) => {
|
||||
export default (style: IPasteStyle, item: ImgInfo, customLink: string | undefined) => {
|
||||
const url = handleUrlEncode(item.url || item.imgUrl)
|
||||
const customLink = db.get('settings.customLink') || '$url'
|
||||
const _customLink = customLink || '$url'
|
||||
const tpl = {
|
||||
'markdown': ``,
|
||||
'HTML': `<img src="${url}"/>`,
|
||||
'URL': url,
|
||||
'UBB': `[IMG]${url}[/IMG]`,
|
||||
'Custom': formatCustomLink(customLink, item)
|
||||
'Custom': formatCustomLink(_customLink, item)
|
||||
}
|
||||
return tpl[style]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user