mirror of
https://github.com/Kuingsmile/PicList.git
synced 2025-02-02 02:58:13 -05:00
Merge branch 'dev' into release
This commit is contained in:
commit
606ecd15d6
22
CHANGELOG.md
22
CHANGELOG.md
@ -1,3 +1,25 @@
|
||||
## :tada: 2.9.4 (2024-10-22)
|
||||
|
||||
|
||||
### :sparkles: Features
|
||||
|
||||
* **custom:** change default short key ([64fba8a](https://github.com/Kuingsmile/piclist/commit/64fba8a))
|
||||
* **custom:** optimize second uploader ([0565ce3](https://github.com/Kuingsmile/piclist/commit/0565ce3)), closes [#241](https://github.com/Kuingsmile/piclist/issues/241) [#238](https://github.com/Kuingsmile/piclist/issues/238)
|
||||
* **custom:** remove telegra.ph ([59ed79a](https://github.com/Kuingsmile/piclist/commit/59ed79a))
|
||||
|
||||
|
||||
### :bug: Bug Fixes
|
||||
|
||||
* **custom:** fix gallery image delete bug ([d6f48e5](https://github.com/Kuingsmile/piclist/commit/d6f48e5)), closes [#239](https://github.com/Kuingsmile/piclist/issues/239)
|
||||
* **custom:** fix webdav url bug ([07cf63a](https://github.com/Kuingsmile/piclist/commit/07cf63a)), closes [#243](https://github.com/Kuingsmile/piclist/issues/243)
|
||||
|
||||
|
||||
### :pencil: Documentation
|
||||
|
||||
* **custom:** prepare for 2.9.4 ([4b12e42](https://github.com/Kuingsmile/piclist/commit/4b12e42))
|
||||
|
||||
|
||||
|
||||
## :tada: 2.9.3 (2024-08-22)
|
||||
|
||||
|
||||
|
1
FAQ.md
1
FAQ.md
@ -55,7 +55,6 @@ PicList本体支持了如下图床:
|
||||
- `Webdav`
|
||||
- `本地图床`
|
||||
- `SFTP`
|
||||
- `Telegra.ph`
|
||||
- `兰空图床`
|
||||
- `PicList(套娃)`
|
||||
|
||||
|
@ -55,7 +55,6 @@ PicList itself supports the following image hosting platforms:
|
||||
- Webdav
|
||||
- Local path
|
||||
- SFTP
|
||||
- Telegra.ph
|
||||
- Lsky Pro
|
||||
- PicList (nested)
|
||||
|
||||
|
@ -34,7 +34,7 @@ if you want to use PicList-core, please go to [https://github.com/Kuingsmile/Pic
|
||||
## Features
|
||||
|
||||
- Retains all the features of PicGo and is compatible with the vast majority of existing PicGo plugins, including integrations with software like Typora and Obsidian.
|
||||
- Added multiple built-in image hosting platforms, such as WebDav, Lsky Pro, local image hosting, SFTP and Telegra.ph. The original built-in imgur image host now also supports account login for uploading.
|
||||
- Added multiple built-in image hosting platforms, such as WebDav, Lsky Pro, local image hosting, SFTP. The original built-in imgur image host now also supports account login for uploading.
|
||||
- Within the album, you can synchronize the deletion of cloud images. This is supported across all built-in image hosts and multiple plugins.
|
||||
- The album now offers advanced search and sorting features, as well as batch URL modification.
|
||||
- Built-in tools for adding watermarks, compressing images, scaling images, rotating images, and converting image formats are now available. Advanced renaming is also supported.
|
||||
@ -139,7 +139,6 @@ docker-compose up -d
|
||||
| Built-in SFTP | ✔️ | ✔️ |
|
||||
| Doge Cloud | ✔️ | ✔️ |
|
||||
| PicList(Lasso-Doll) | ✔️ | ✔️ |
|
||||
| Telegra.ph | ✔️ | × |
|
||||
| Lsky Pro | ✔️ | ✔️ |
|
||||
| Custom API platform | × | × |
|
||||
|
||||
|
@ -34,7 +34,7 @@ PicList的内核使用的是原版PicGo-Core基础上修改的[PicList-core](htt
|
||||
## 特色功能
|
||||
|
||||
- 保留了PicGo的所有功能,兼容绝大部分已有的PicGo插件,包括和Typora、Obsidian等软件的搭配
|
||||
- 新增了多个内置图床,如WebDav、兰空图床、本地图床、SFTP和Telegra.ph等,原内置imgur图床额外支持登录账号上传
|
||||
- 新增了多个内置图床,如WebDav、兰空图床、本地图床、SFTP等,原内置imgur图床额外支持登录账号上传
|
||||
- 相册中可同步删除云端图片,支持所有内置图床和多个插件
|
||||
- 相册新增了高级搜索和排序,批量修改URL等功能
|
||||
- 内置水印添加、图片压缩、图片缩放、图片旋转和图片格式转换等功能,同时支持高级重命名
|
||||
@ -141,7 +141,6 @@ docker-compose up -d
|
||||
| 内置SFTP | ✔️ | ✔️ |
|
||||
| 多吉云 | ✔️ | ✔️ |
|
||||
| PicList(套娃) | ✔️ | ✔️ |
|
||||
| Telegra.ph | ✔️ | x |
|
||||
| 兰空图床 | ✔️ | ✔️ |
|
||||
| 自定义图床 | x | x |
|
||||
|
||||
|
@ -1,9 +1,10 @@
|
||||
### ✨ Features
|
||||
|
||||
- 新增第二图床上传支持
|
||||
- 现在管理页面支持预览avif图片
|
||||
- 调整了图床配置页面的日期显示格式
|
||||
- 优化了第二图床的上传逻辑,现在会使用相同文件名和压缩方式
|
||||
- 移除了telegra.ph图床(官方现已关闭匿名上传功能)
|
||||
- 默认上传快捷键修改为`Ctrl+Alt+U`,避免与vscode命令面板冲突
|
||||
|
||||
### 🐛 Bug Fixes
|
||||
|
||||
- 修复了PicList图床对core版的兼容性问题
|
||||
- 修复了webdav图床链接拼接错误的问题
|
||||
- 修复了开启云删除时部分第三方图床图片无法批量删除的问题
|
||||
|
@ -1,9 +1,10 @@
|
||||
### ✨ Features
|
||||
|
||||
- Added support for the second image bed upload
|
||||
- Now the management page supports previewing avif images
|
||||
- Adjusted the date display format on the image bed configuration page
|
||||
- Optimize the upload logic of the second image bed, now it will use the same file name and compression method
|
||||
- Removed telegra.ph image bed (officially closed anonymous upload function)
|
||||
- The default upload shortcut key is changed to `Ctrl+Alt+U` to avoid conflicts with the vscode command panel
|
||||
|
||||
### 🐛 Bug Fixes
|
||||
|
||||
- Fixed the compatibility issue of PicList image bed with the core version
|
||||
- Fixed the problem of incorrect splicing of webdav image bed links
|
||||
- Fixed the problem that some third-party image bed pictures cannot be deleted in batches when cloud deletion is enabled
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "piclist",
|
||||
"version": "2.9.3",
|
||||
"version": "2.9.4",
|
||||
"author": {
|
||||
"name": "Kuingsmile",
|
||||
"email": "pkukuing@gmail.com"
|
||||
@ -67,7 +67,7 @@
|
||||
"multer": "^1.4.5-lts.1",
|
||||
"node-ssh-no-cpu-features": "^2.0.0",
|
||||
"nodejs-file-downloader": "^4.12.1",
|
||||
"piclist": "^1.9.3",
|
||||
"piclist": "^1.9.6",
|
||||
"pinia": "^2.1.7",
|
||||
"pinia-plugin-persistedstate": "^3.2.1",
|
||||
"proxy-agent": "^5.0.0",
|
||||
|
@ -309,8 +309,16 @@ export function createTray(tooltip: string) {
|
||||
const pasteStyle = db.get(configPaths.settings.pasteStyle) || IPasteStyle.MARKDOWN
|
||||
const rawInput = cloneDeep(files)
|
||||
const trayWindow = windowManager.get(IWindowList.TRAY_WINDOW)!
|
||||
await handleSecondaryUpload(trayWindow.webContents, files, 'tray')
|
||||
const imgs = await uploader.setWebContents(trayWindow.webContents).upload(files)
|
||||
const { needRestore, ctx } = await handleSecondaryUpload(trayWindow.webContents, files, 'tray')
|
||||
let imgs: ImgInfo[] | false = false
|
||||
if (needRestore) {
|
||||
const res = await uploader
|
||||
.setWebContents(trayWindow.webContents)
|
||||
.uploadReturnCtx(ctx ? ctx.processedInput : files, true)
|
||||
imgs = res ? res.output : false
|
||||
} else {
|
||||
imgs = await uploader.setWebContents(trayWindow.webContents).upload(files)
|
||||
}
|
||||
const deleteLocalFile = db.get(configPaths.settings.deleteLocalFile) || false
|
||||
if (imgs !== false) {
|
||||
const pasteText: string[] = []
|
||||
|
@ -15,6 +15,7 @@ import pasteTemplate from '~/utils/pasteTemplate'
|
||||
import { IPasteStyle, IWindowList } from '#/types/enum'
|
||||
import { configPaths } from '#/utils/configPaths'
|
||||
import { changeCurrentUploader } from '~/utils/handleUploaderConfig'
|
||||
import { IPicGo } from 'piclist'
|
||||
|
||||
const handleClipboardUploading = async (): Promise<false | ImgInfo[]> => {
|
||||
const useBuiltinClipboard =
|
||||
@ -28,9 +29,27 @@ const handleClipboardUploading = async (): Promise<false | ImgInfo[]> => {
|
||||
return await uploader.setWebContents(win!.webContents).upload()
|
||||
}
|
||||
|
||||
const handleClipboardUploadingReturnCtx = async (img?: IUploadOption, skipProcess = false): Promise<false | IPicGo> => {
|
||||
const useBuiltinClipboard =
|
||||
db.get(configPaths.settings.useBuiltinClipboard) === undefined
|
||||
? true
|
||||
: !!db.get(configPaths.settings.useBuiltinClipboard)
|
||||
const win = windowManager.getAvailableWindow()
|
||||
if (useBuiltinClipboard) {
|
||||
return await uploader.setWebContents(win!.webContents).uploadWithBuildInClipboardReturnCtx(img, skipProcess)
|
||||
}
|
||||
return await uploader.setWebContents(win!.webContents).uploadReturnCtx(img, skipProcess)
|
||||
}
|
||||
|
||||
export const uploadClipboardFiles = async (): Promise<IStringKeyMap> => {
|
||||
await handleSecondaryUpload(undefined, undefined, 'clipboard')
|
||||
const img = await handleClipboardUploading()
|
||||
const { needRestore, ctx } = await handleSecondaryUpload(undefined, undefined, 'clipboard')
|
||||
let img: ImgInfo[] | false = false
|
||||
if (needRestore) {
|
||||
const res = await handleClipboardUploadingReturnCtx(ctx ? ctx.processedInput : undefined, true)
|
||||
img = res ? res.output : false
|
||||
} else {
|
||||
img = await handleClipboardUploading()
|
||||
}
|
||||
if (img !== false) {
|
||||
if (img.length > 0) {
|
||||
const trayWindow = windowManager.get(IWindowList.TRAY_WINDOW)
|
||||
@ -86,8 +105,14 @@ export const uploadChoosedFiles = async (
|
||||
): Promise<IStringKeyMap[]> => {
|
||||
const input = files.map(item => item.path)
|
||||
const rawInput = cloneDeep(input)
|
||||
await handleSecondaryUpload(webContents, input)
|
||||
const imgs = await uploader.setWebContents(webContents).upload(input)
|
||||
const { needRestore, ctx } = await handleSecondaryUpload(webContents, input)
|
||||
let imgs: ImgInfo[] | false = false
|
||||
if (needRestore) {
|
||||
const res = await uploader.setWebContents(webContents).uploadReturnCtx(ctx ? ctx.processedInput : input, true)
|
||||
imgs = res ? res.output : false
|
||||
} else {
|
||||
imgs = await uploader.setWebContents(webContents).upload(input)
|
||||
}
|
||||
const result = []
|
||||
if (imgs !== false) {
|
||||
const pasteStyle = db.get(configPaths.settings.pasteStyle) || IPasteStyle.MARKDOWN
|
||||
@ -140,12 +165,13 @@ export const handleSecondaryUpload = async (
|
||||
webContents?: WebContents,
|
||||
input?: string[],
|
||||
uploadType: 'clipboard' | 'file' | 'tray' = 'file'
|
||||
): Promise<void> => {
|
||||
): Promise<{ needRestore: boolean; ctx: IPicGo | false }> => {
|
||||
const enableSecondUploader = db.get(configPaths.settings.enableSecondUploader) || false
|
||||
let currentPicBedType = ''
|
||||
let currentPicBedConfig = {} as IStringKeyMap
|
||||
let currentPicBedConfigId = ''
|
||||
let needRestore = false
|
||||
let ctx: IPicGo | false = false
|
||||
if (enableSecondUploader) {
|
||||
const secondUploader = db.get(configPaths.picBed.secondUploader)
|
||||
const secondUploaderConfig = db.get(configPaths.picBed.secondUploaderConfig)
|
||||
@ -165,10 +191,11 @@ export const handleSecondaryUpload = async (
|
||||
let secondImgs: ImgInfo[] | false = false
|
||||
changeCurrentUploader(secondUploader, secondUploaderConfig, secondUploaderId)
|
||||
if (uploadType === 'clipboard') {
|
||||
secondImgs = await handleClipboardUploading()
|
||||
ctx = await handleClipboardUploadingReturnCtx(undefined)
|
||||
} else {
|
||||
secondImgs = await uploader.setWebContents(webContents!).upload(input)
|
||||
ctx = await uploader.setWebContents(webContents!).uploadReturnCtx(input)
|
||||
}
|
||||
secondImgs = ctx ? ctx.output : false
|
||||
if (secondImgs !== false) {
|
||||
const trayWindow = windowManager.get(IWindowList.TRAY_WINDOW)
|
||||
if (uploadType === 'clipboard') {
|
||||
@ -196,4 +223,8 @@ export const handleSecondaryUpload = async (
|
||||
if (needRestore) {
|
||||
changeCurrentUploader(currentPicBedType, currentPicBedConfig, currentPicBedConfigId)
|
||||
}
|
||||
return {
|
||||
needRestore,
|
||||
ctx
|
||||
}
|
||||
}
|
||||
|
@ -149,6 +149,69 @@ class Uploader {
|
||||
}
|
||||
}
|
||||
|
||||
async uploadWithBuildInClipboardReturnCtx(img?: IUploadOption, skipProcess = false): Promise<IPicGo | false> {
|
||||
let filePath = ''
|
||||
try {
|
||||
const imgPath = getClipboardFilePath()
|
||||
if (!imgPath) {
|
||||
const nativeImage = clipboard.readImage()
|
||||
if (nativeImage.isEmpty()) {
|
||||
return false
|
||||
}
|
||||
const buffer = nativeImage.toPNG()
|
||||
const baseDir = picgo.baseDir
|
||||
const fileName = `${dayjs().format('YYYYMMDDHHmmSSS')}.png`
|
||||
filePath = path.join(baseDir, CLIPBOARD_IMAGE_FOLDER, fileName)
|
||||
await writeFile(filePath, buffer)
|
||||
return await this.uploadReturnCtx(img ?? [filePath], skipProcess)
|
||||
} else {
|
||||
return await this.uploadReturnCtx(img ?? [imgPath], skipProcess)
|
||||
}
|
||||
} catch (e: any) {
|
||||
logger.error(e)
|
||||
return false
|
||||
} finally {
|
||||
if (filePath) {
|
||||
fs.remove(filePath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async uploadReturnCtx(img?: IUploadOption, skipProcess = false): Promise<IPicGo | false> {
|
||||
try {
|
||||
const startTime = Date.now()
|
||||
const ctx = await picgo.uploadReturnCtx(img, skipProcess)
|
||||
if (Array.isArray(ctx.output) && ctx.output.some((item: ImgInfo) => item.imgUrl)) {
|
||||
if (this.webContents) {
|
||||
handleTalkingData(this.webContents, {
|
||||
fromClipboard: !img,
|
||||
type: db.get(configPaths.picBed.uploader) || db.get(configPaths.picBed.current) || 'smms',
|
||||
count: img ? img.length : 1,
|
||||
duration: Date.now() - startTime
|
||||
} as IAnalyticsData)
|
||||
}
|
||||
ctx.output.forEach((item: ImgInfo) => {
|
||||
item.config = JSON.parse(JSON.stringify(db.get(`picBed.${item.type}`)))
|
||||
})
|
||||
return ctx
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
} catch (e: any) {
|
||||
logger.error(e)
|
||||
setTimeout(() => {
|
||||
showNotification({
|
||||
title: T('UPLOAD_FAILED'),
|
||||
body: util.format(e.stack),
|
||||
clickToCopy: true
|
||||
})
|
||||
}, 500)
|
||||
return false
|
||||
} finally {
|
||||
ipcMain.removeAllListeners(GET_RENAME_FILE_NAME)
|
||||
}
|
||||
}
|
||||
|
||||
async upload(img?: IUploadOption): Promise<ImgInfo[] | false> {
|
||||
try {
|
||||
const startTime = Date.now()
|
||||
|
@ -35,7 +35,7 @@ class ConfigStore {
|
||||
if (!this.#db.has(configPaths.settings.shortKey._path)) {
|
||||
this.#db.set(configPaths.settings.shortKey['picgo:upload'], {
|
||||
enable: true,
|
||||
key: 'CommandOrControl+Shift+P',
|
||||
key: 'CommandOrControl+Alt+P',
|
||||
name: 'upload',
|
||||
label: T('QUICK_UPLOAD')
|
||||
})
|
||||
|
@ -79,8 +79,14 @@ class GuiApi implements IGuiApi {
|
||||
this.windowId = await getWindowId()
|
||||
const webContents = this.getWebcontentsByWindowId(this.windowId)
|
||||
const rawInput = cloneDeep(input)
|
||||
await handleSecondaryUpload(webContents!, input)
|
||||
const imgs = await uploader.setWebContents(webContents!).upload(input)
|
||||
const { needRestore, ctx } = await handleSecondaryUpload(webContents!, input)
|
||||
let imgs: ImgInfo[] | false = false
|
||||
if (needRestore) {
|
||||
const res = await uploader.setWebContents(webContents!).uploadReturnCtx(ctx ? ctx.processedInput : input, true)
|
||||
imgs = res ? res.output : false
|
||||
} else {
|
||||
imgs = await uploader.setWebContents(webContents!).upload(input)
|
||||
}
|
||||
if (imgs !== false) {
|
||||
const pasteStyle = db.get(configPaths.settings.pasteStyle) || IPasteStyle.MARKDOWN
|
||||
const deleteLocalFile = db.get(configPaths.settings.deleteLocalFile) || false
|
||||
|
@ -428,9 +428,7 @@ function handleDetectShiftKey(event: KeyboardEvent) {
|
||||
}
|
||||
|
||||
const filterList = computed(() => {
|
||||
const start = new Date().getTime()
|
||||
const res = getGallery()
|
||||
console.log(`filterList: ${new Date().getTime() - start}ms`)
|
||||
return res
|
||||
})
|
||||
|
||||
@ -487,9 +485,7 @@ function getGallery(): IGalleryItem[] {
|
||||
}
|
||||
|
||||
async function updateGallery() {
|
||||
const start = new Date().getTime()
|
||||
images.value = (await $$db.get({ orderBy: 'desc' }))!.data
|
||||
console.log(`updateGallery: ${new Date().getTime() - start}ms`)
|
||||
}
|
||||
|
||||
watch(
|
||||
@ -698,6 +694,9 @@ function multiRemove() {
|
||||
duration: multiRemoveNumber > 5 ? 1000 : 2000
|
||||
})
|
||||
}
|
||||
} else {
|
||||
files.push(file)
|
||||
await $$db.removeById(key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
5
src/universal/types/types.d.ts
vendored
5
src/universal/types/types.d.ts
vendored
@ -296,11 +296,6 @@ interface shortKeyHandlerMap {
|
||||
handle: IShortKeyHandler
|
||||
}
|
||||
|
||||
// PicBeds
|
||||
interface ITelegraphConfig {
|
||||
proxy?: string
|
||||
}
|
||||
|
||||
interface ILocalConfig {
|
||||
path: string
|
||||
customUrl?: string
|
||||
|
@ -25,7 +25,6 @@ export interface IConfigStruct {
|
||||
webdavplist?: IWebdavPlistConfig
|
||||
local?: ILocalConfig
|
||||
sftpplist?: ISftpPlistConfig
|
||||
telegraphplist?: ITelegraphConfig
|
||||
lskyplist?: ILskyConfig
|
||||
'aws-s3-plist': IAwsS3PListUserConfig
|
||||
proxy?: string
|
||||
|
@ -47,7 +47,6 @@ export const picBedManualUrlList: IStringKeyMap = {
|
||||
qiniu: 'https://piclist.cn/configure.html#%E4%B8%83%E7%89%9B%E4%BA%91',
|
||||
sftpplist: 'https://piclist.cn/configure.html#%E5%86%85%E7%BD%AEsftp',
|
||||
smms: 'https://piclist.cn/configure.html#sm-ms',
|
||||
telegraphplist: 'https://piclist.cn/configure.html#telegra-ph',
|
||||
upyun: 'https://piclist.cn/configure.html#%E5%8F%88%E6%8B%8D%E4%BA%91',
|
||||
webdavplist: 'https://piclist.cn/configure.html#webdav'
|
||||
},
|
||||
@ -68,7 +67,6 @@ export const picBedManualUrlList: IStringKeyMap = {
|
||||
qiniu: 'https://piclist.cn/en/configure.html#qiniu-cloud',
|
||||
sftpplist: 'https://piclist.cn/en/configure.html#built-in-sftp',
|
||||
smms: 'https://piclist.cn/en/configure.html#sm-ms',
|
||||
telegraphplist: 'https://piclist.cn/en/configure.html#telegra-ph',
|
||||
upyun: 'https://piclist.cn/en/configure.html#upyun',
|
||||
webdavplist: 'https://piclist.cn/en/configure.html#webdav'
|
||||
}
|
||||
|
@ -11956,10 +11956,10 @@ performance-now@^2.1.0:
|
||||
resolved "https://registry.npmmirror.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
|
||||
integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==
|
||||
|
||||
piclist@^1.9.3:
|
||||
version "1.9.3"
|
||||
resolved "https://registry.yarnpkg.com/piclist/-/piclist-1.9.3.tgz#3aa769237935a70fdb786a46f5ed46b762e38dd9"
|
||||
integrity sha512-nWorUUyBmDJ6ZtHXHVa1dn4PHiKjION9izdj+xcgGkwgQj4xegKWLsivEgdMEV8e+iuulO6e+n1+pQcqOqqasg==
|
||||
piclist@^1.9.6:
|
||||
version "1.9.6"
|
||||
resolved "https://registry.yarnpkg.com/piclist/-/piclist-1.9.6.tgz#010753f7b7cedc076251bd1639f7859e48508386"
|
||||
integrity sha512-CAUbU43/eibk/Jq+SXPL96TXog1vNjpE1pwbsof+D8A8SEpXRg+K5cLAsRjGXubi/SmLonU+imtbldUNuCoHjA==
|
||||
dependencies:
|
||||
"@aws-sdk/client-s3" "3.421.0"
|
||||
"@aws-sdk/lib-storage" "3.421.0"
|
||||
|
Loading…
Reference in New Issue
Block a user