mirror of
https://github.com/Kuingsmile/PicList.git
synced 2025-01-22 22:28:14 -05:00
Merge branch 'dev' into release
This commit is contained in:
commit
7af7830f3c
28
CHANGELOG.md
28
CHANGELOG.md
@ -1,3 +1,31 @@
|
||||
## :tada: 2.6.4 (2023-10-14)
|
||||
|
||||
|
||||
### :sparkles: Features
|
||||
|
||||
* add piclist itself as a picbed ([9f49fc0](https://github.com/Kuingsmile/piclist/commit/9f49fc0))
|
||||
* **custom:** add tk analytic ([e8ea905](https://github.com/Kuingsmile/piclist/commit/e8ea905))
|
||||
|
||||
|
||||
### :bug: Bug Fixes
|
||||
|
||||
* **custom:** fix bump version error ([6f8e4e1](https://github.com/Kuingsmile/piclist/commit/6f8e4e1))
|
||||
* fix font file download logic ([32de515](https://github.com/Kuingsmile/piclist/commit/32de515))
|
||||
* fix macos right click menu file bug ([75601e7](https://github.com/Kuingsmile/piclist/commit/75601e7))
|
||||
* fix manage config file sync bug ([47b61e6](https://github.com/Kuingsmile/piclist/commit/47b61e6))
|
||||
|
||||
|
||||
### :pencil: Documentation
|
||||
|
||||
* **custom:** update docs ([d1780f2](https://github.com/Kuingsmile/piclist/commit/d1780f2))
|
||||
|
||||
|
||||
### :package: Chore
|
||||
|
||||
* **custom:** migrate to node-bump-version ([567af45](https://github.com/Kuingsmile/piclist/commit/567af45))
|
||||
|
||||
|
||||
|
||||
## :tada: 2.6.3 (2023-10-10)
|
||||
|
||||
|
||||
|
@ -100,6 +100,7 @@ In the community plugins, search for and install the Image auto upload Plugin. N
|
||||
| Local | ✔️ | ✔️ |
|
||||
| Built-in SFTP | ✔️ | ✔️ |
|
||||
| Doge Cloud | ✔️ | ✔️ |
|
||||
| PicList(Lasso-Doll) | ✔️ | ✔️ |
|
||||
|
||||
| Plugin | Album cloud deletion |
|
||||
| :----------------------------------------------------------------------------------------: | :------------------: |
|
||||
|
@ -100,6 +100,7 @@ MacOS:
|
||||
| 本地文件夹 | ✔️ | ✔️ |
|
||||
| 内置SFTP | ✔️ | ✔️ |
|
||||
| 多吉云 | ✔️ | ✔️ |
|
||||
| PicList(套娃) | ✔️ | ✔️ |
|
||||
|
||||
| 插件 | 相册云删除 |
|
||||
| :----------------------------------------------------------------------------------------: | :--------: |
|
||||
|
@ -1,11 +1,11 @@
|
||||
✨ Features
|
||||
|
||||
- 现在当已经设置了水印字体文件路径或使用图片水印时,不再检查内置字体文件是否存在
|
||||
- PicList和PicList-Core的内置服务器现在均支持通过`formData`的方式上传图片文件
|
||||
- 内置服务器现在默认监听`0.0.0.0`,而不是`127.0.0.1`,以配合多电脑间使用
|
||||
- 内置服务器现在支持设置鉴权密钥`key`参数,通过url参数形式传递`?key=xxx`,避免被恶意利用
|
||||
- PicList-Core现在支持通过`picgo-server`启动内置上传服务器,使用方式与PicList的内置服务器相同
|
||||
- 现在当设置了内置服务器鉴权密钥时,图床设置界面复制api接口会自动添加密钥
|
||||
- 添加了`PicList`自身作为套娃图床,实现A电脑添加B电脑的`PicList`进行上传的功能
|
||||
- 新增上传耗时等统计功能
|
||||
|
||||
🐛 Bug Fixes
|
||||
|
||||
- 修复了没有新建临时文件夹导致本地图床上传失败的问题
|
||||
- 修复了电脑间同步管理配置文件时,无法正常进入图床,需要重新保存一次配置的问题
|
||||
- 修复了arm mac平台缺失右键菜单的问题
|
||||
- 修复了跳过水印字体下载没有对文件上传情景生效的问题
|
||||
|
@ -1,11 +1,11 @@
|
||||
✨ Features
|
||||
|
||||
- Now that the watermark font file path has been set or the image watermark is used, the built-in font file is no longer checked
|
||||
- The built-in server of PicList and PicList-Core now support uploading image files through `formData`
|
||||
- PicList-Core now supports starting the built-in upload server through `picgo-server`, and the usage is the same as the built-in server of PicList
|
||||
- The built-in server now supports setting the authentication key `key` parameter, which is passed in the form of url parameters `?key=xxx` to avoid being maliciously used
|
||||
- PicList-Core now supports starting the built-in upload server through `picgo-server`, and the usage is the same as the built-in server of PicList
|
||||
- Now when the built-in server authentication key is set, the copy API interface in the image bed setting interface will automatically add the key
|
||||
- Added `PicList` itself as a nested image bed, which realizes the function of A computer adding B computer's `PicList` for uploading
|
||||
- Added upload time consumption and other statistics functions
|
||||
|
||||
🐛 Bug Fixes
|
||||
|
||||
- Fix the problem that the local image bed upload fails due to not creating a new temporary folder
|
||||
- Fixed the problem that when synchronizing and managing configuration files between computers, the image bed cannot be entered normally, and the configuration needs to be saved again
|
||||
- Fixed the problem that the right-click menu is missing on the arm mac platform
|
||||
- Fixed the problem that skipping the watermark font download does not take effect on file upload scenarios
|
||||
|
20
package.json
20
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "piclist",
|
||||
"version": "2.6.3",
|
||||
"version": "2.6.4",
|
||||
"author": {
|
||||
"name": "Kuingsmile",
|
||||
"email": "pkukuing@gmail.com"
|
||||
@ -52,7 +52,7 @@
|
||||
"cos-nodejs-sdk-v5": "^2.12.4",
|
||||
"dexie": "^3.2.4",
|
||||
"electron-updater": "^6.1.4",
|
||||
"element-plus": "2.3.14",
|
||||
"element-plus": "2.4.0",
|
||||
"epipebomb": "^1.0.0",
|
||||
"fast-xml-parser": "^4.3.2",
|
||||
"form-data": "^4.0.0",
|
||||
@ -68,8 +68,8 @@
|
||||
"multer": "^1.4.5-lts.1",
|
||||
"node-ssh-no-cpu-features": "^1.0.1",
|
||||
"nodejs-file-downloader": "^4.12.1",
|
||||
"piclist": "^1.3.4",
|
||||
"pinia": "^2.1.6",
|
||||
"piclist": "^1.6.0",
|
||||
"pinia": "^2.1.7",
|
||||
"pinia-plugin-persistedstate": "^3.2.0",
|
||||
"qiniu": "^7.9.0",
|
||||
"qrcode.vue": "^3.4.1",
|
||||
@ -89,7 +89,6 @@
|
||||
"devDependencies": {
|
||||
"@babel/plugin-proposal-optional-chaining": "^7.21.0",
|
||||
"@electron/notarize": "^2.1.0",
|
||||
"@picgo/bump-version": "^1.1.2",
|
||||
"@types/ali-oss": "^6.16.9",
|
||||
"@types/electron-devtools-installer": "^2.2.3",
|
||||
"@types/fs-extra": "^11.0.2",
|
||||
@ -105,8 +104,8 @@
|
||||
"@types/upyun": "^3.4.1",
|
||||
"@types/uuid": "^9.0.3",
|
||||
"@types/write-file-atomic": "^4.0.1",
|
||||
"@typescript-eslint/eslint-plugin": "^6.7.4",
|
||||
"@typescript-eslint/parser": "^6.7.4",
|
||||
"@typescript-eslint/eslint-plugin": "^6.7.5",
|
||||
"@typescript-eslint/parser": "^6.7.5",
|
||||
"@vue/cli-plugin-babel": "^5.0.8",
|
||||
"@vue/cli-plugin-eslint": "^5.0.8",
|
||||
"@vue/cli-plugin-router": "^5.0.8",
|
||||
@ -128,8 +127,9 @@
|
||||
"eslint-plugin-promise": "^6.1.1",
|
||||
"eslint-plugin-vue": "^9.17.0",
|
||||
"husky": "^3.1.0",
|
||||
"node-bump-version": "^1.0.2",
|
||||
"node-loader": "^2.0.0",
|
||||
"npm-check-updates": "^16.14.5",
|
||||
"npm-check-updates": "^16.14.6",
|
||||
"stylus": "^0.59.0",
|
||||
"stylus-loader": "^7.1.3",
|
||||
"typescript": "^4.9.5",
|
||||
@ -137,7 +137,7 @@
|
||||
},
|
||||
"commitlint": {
|
||||
"extends": [
|
||||
"./node_modules/@picgo/bump-version/commitlint-picgo"
|
||||
"./node_modules/node-bump-version/commitlint-node"
|
||||
]
|
||||
},
|
||||
"config": {
|
||||
@ -145,7 +145,7 @@
|
||||
"path": "./node_modules/cz-customizable"
|
||||
},
|
||||
"cz-customizable": {
|
||||
"config": "./node_modules/@picgo/bump-version/.cz-config.js"
|
||||
"config": "./node_modules/node-bump-version/.cz-config.js"
|
||||
}
|
||||
},
|
||||
"husky": {
|
||||
|
@ -6,6 +6,7 @@ import router from './renderer/router'
|
||||
import ElementUI from 'element-plus'
|
||||
import 'element-plus/dist/index.css'
|
||||
import VueLazyLoad from 'vue3-lazyload'
|
||||
import { initTalkingData } from './renderer/utils/analytic'
|
||||
import vue3PhotoPreview from 'vue3-photo-preview'
|
||||
import 'vue3-photo-preview/dist/index.css'
|
||||
import VueVideoPlayer from '@videojs-player/vue'
|
||||
@ -83,3 +84,5 @@ console.log(hljsCommon.highlightAuto('<h1>Highlight.js has been registered succe
|
||||
app.use(hljsVuePlugin)
|
||||
app.use(VueVideoPlayer)
|
||||
app.mount('#app')
|
||||
|
||||
initTalkingData()
|
||||
|
@ -18,7 +18,7 @@ import {
|
||||
import picgo from '@core/picgo'
|
||||
import db from '~/main/apis/core/datastore'
|
||||
import windowManager from 'apis/app/window/windowManager'
|
||||
import { showNotification, getClipboardFilePath } from '~/main/utils/common'
|
||||
import { showNotification, getClipboardFilePath, calcDurationRange } from '~/main/utils/common'
|
||||
import logger from '@core/picgo/logger'
|
||||
import { T } from '~/main/i18n'
|
||||
import { CLIPBOARD_IMAGE_FOLDER } from '~/universal/utils/static'
|
||||
@ -30,7 +30,8 @@ import { IWindowList } from '#/types/enum'
|
||||
import { IPicGo } from 'piclist'
|
||||
import {
|
||||
GET_RENAME_FILE_NAME,
|
||||
RENAME_FILE_NAME
|
||||
RENAME_FILE_NAME,
|
||||
TALKING_DATA_EVENT
|
||||
} from '~/universal/events/constants'
|
||||
|
||||
const waitForRename = (window: BrowserWindow, id: number): Promise<string|null> => {
|
||||
@ -48,6 +49,20 @@ const waitForRename = (window: BrowserWindow, id: number): Promise<string|null>
|
||||
})
|
||||
}
|
||||
|
||||
const handleTalkingData = (webContents: WebContents, options: IAnalyticsData) => {
|
||||
const data: ITalkingDataOptions = {
|
||||
EventId: 'upload',
|
||||
Label: options.type,
|
||||
MapKv: {
|
||||
by: options.fromClipboard ? 'clipboard' : 'files',
|
||||
count: options.count,
|
||||
duration: calcDurationRange(options.duration || 0),
|
||||
type: options.type
|
||||
}
|
||||
}
|
||||
webContents.send(TALKING_DATA_EVENT, data)
|
||||
}
|
||||
|
||||
class Uploader {
|
||||
private webContents: WebContents | null = null
|
||||
// private uploading: boolean = false
|
||||
@ -142,8 +157,17 @@ class Uploader {
|
||||
|
||||
async upload (img?: IUploadOption): Promise<ImgInfo[]|false> {
|
||||
try {
|
||||
const startTime = Date.now()
|
||||
const output = await picgo.upload(img)
|
||||
if (Array.isArray(output) && output.some((item: ImgInfo) => item.imgUrl)) {
|
||||
if (this.webContents) {
|
||||
handleTalkingData(this.webContents, {
|
||||
fromClipboard: !img,
|
||||
type: db.get('picBed.uploader') || db.get('picBed.current') || 'smms',
|
||||
count: img ? img.length : 1,
|
||||
duration: Date.now() - startTime
|
||||
} as IAnalyticsData)
|
||||
}
|
||||
output.forEach((item: ImgInfo) => {
|
||||
item.config = JSON.parse(JSON.stringify(db.get(`picBed.${item.type}`)))
|
||||
})
|
||||
|
@ -16,6 +16,30 @@ function beforeOpen () {
|
||||
resolveOtherI18nFiles()
|
||||
}
|
||||
|
||||
function copyFileOutsideOfElectronAsar (
|
||||
sourceInAsarArchive: string,
|
||||
destOutsideAsarArchive: string
|
||||
) {
|
||||
if (fs.existsSync(sourceInAsarArchive)) {
|
||||
// file will be copied
|
||||
if (fs.statSync(sourceInAsarArchive).isFile()) {
|
||||
const file = destOutsideAsarArchive
|
||||
const dir = path.dirname(file)
|
||||
if (!fs.existsSync(dir)) {
|
||||
fs.mkdirSync(dir, { recursive: true })
|
||||
}
|
||||
fs.writeFileSync(file, fs.readFileSync(sourceInAsarArchive))
|
||||
} else if (fs.statSync(sourceInAsarArchive).isDirectory()) {
|
||||
fs.readdirSync(sourceInAsarArchive).forEach(function (fileOrFolderName) {
|
||||
copyFileOutsideOfElectronAsar(
|
||||
`${sourceInAsarArchive}/${fileOrFolderName}`,
|
||||
`${destOutsideAsarArchive}/${fileOrFolderName}`
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* macOS 右键菜单
|
||||
*/
|
||||
@ -23,7 +47,7 @@ function resolveMacWorkFlow () {
|
||||
const dest = `${os.homedir()}/Library/Services/Upload pictures with PicList.workflow`
|
||||
if (fs.existsSync(dest)) return true
|
||||
try {
|
||||
fs.copySync(path.join(__static, 'Upload pictures with PicList.workflow'), dest)
|
||||
copyFileOutsideOfElectronAsar(path.join(__static, 'Upload pictures with PicList.workflow'), dest)
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
|
@ -57,6 +57,30 @@ export const showMessageBox = (options: any) => {
|
||||
})
|
||||
}
|
||||
|
||||
export const calcDurationRange = (duration: number) => {
|
||||
if (duration < 1000) {
|
||||
return 500
|
||||
} else if (duration < 1500) {
|
||||
return 1000
|
||||
} else if (duration < 3000) {
|
||||
return 2000
|
||||
} else if (duration < 5000) {
|
||||
return 3000
|
||||
} else if (duration < 7000) {
|
||||
return 5000
|
||||
} else if (duration < 10000) {
|
||||
return 8000
|
||||
} else if (duration < 12000) {
|
||||
return 10000
|
||||
} else if (duration < 20000) {
|
||||
return 15000
|
||||
} else if (duration < 30000) {
|
||||
return 20000
|
||||
}
|
||||
// max range
|
||||
return 100000
|
||||
}
|
||||
|
||||
/**
|
||||
* macOS public.file-url will get encoded file path,
|
||||
* so we need to decode it
|
||||
|
@ -12,6 +12,7 @@ import WebdavApi from './webdav'
|
||||
import DogeCloudApi from './dogecloud'
|
||||
import HuaweicloudApi from './huaweiyun'
|
||||
import AlistApi from './alist'
|
||||
import PiclistApi from './piclist'
|
||||
|
||||
const apiMap: IStringKeyMap = {
|
||||
aliyun: AliyunApi,
|
||||
@ -27,7 +28,8 @@ const apiMap: IStringKeyMap = {
|
||||
webdavplist: WebdavApi,
|
||||
dogecloud: DogeCloudApi,
|
||||
'huaweicloud-uploader': HuaweicloudApi,
|
||||
alist: AlistApi
|
||||
alist: AlistApi,
|
||||
piclist: PiclistApi
|
||||
}
|
||||
|
||||
export default class ALLApi {
|
||||
|
27
src/renderer/apis/piclist.ts
Normal file
27
src/renderer/apis/piclist.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import axios, { AxiosResponse } from 'axios'
|
||||
|
||||
export default class PiclistApi {
|
||||
static async delete (configMap: IStringKeyMap): Promise<boolean> {
|
||||
const { config, fullResult } = configMap
|
||||
const { host, port } = config
|
||||
if (!host) {
|
||||
console.error('PiclistApi.delete: invalid params')
|
||||
return false
|
||||
}
|
||||
|
||||
const url = `http://${host || '127.0.0.1'}:${port || 36677}/delete`
|
||||
|
||||
try {
|
||||
const response: AxiosResponse = await axios.post(
|
||||
url,
|
||||
{
|
||||
list: [fullResult]
|
||||
}
|
||||
)
|
||||
return response.status === 200 && response.data?.success
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
@ -569,6 +569,7 @@ function handleConfigImport (alias: string) {
|
||||
}
|
||||
|
||||
async function getCurrentConfigList () {
|
||||
await manageStore.refreshConfig()
|
||||
const configList = await getPicBedsConfig<any>('uploader') ?? {}
|
||||
const pbList = ['aliyun', 'aws-s3', 'github', 'imgur', 'local', 'qiniu', 'sftpplist', 'smms', 'tcyun', 'upyun', 'webdavplist']
|
||||
|
||||
|
@ -242,6 +242,7 @@ async function handleCopyApi () {
|
||||
if (host === '0.0.0.0') {
|
||||
host = '127.0.0.1'
|
||||
}
|
||||
const serverKey = await getConfig('settings.serverKey') || ''
|
||||
const uploader = await getConfig('uploader') as IStringKeyMap || {}
|
||||
const picBedConfigList = uploader[$route.params.type as string].configList || []
|
||||
const picBedConfig = picBedConfigList.find((item: IUploaderConfigListItem) => item._id === $route.params.configId)
|
||||
@ -249,7 +250,10 @@ async function handleCopyApi () {
|
||||
ElMessage.error('No config found')
|
||||
return
|
||||
}
|
||||
const apiUrl = `http://${host}:${port}/upload?picbed=${$route.params.type}&configName=${picBedConfig?._configName}`
|
||||
let apiUrl = `http://${host}:${port}/upload?picbed=${$route.params.type}&configName=${picBedConfig?._configName}`
|
||||
if (serverKey) {
|
||||
apiUrl += `&key=${serverKey}`
|
||||
}
|
||||
clipboard.writeText(apiUrl)
|
||||
ElMessage.success($T('MANAGE_BUCKET_COPY_SUCCESS') + ' ' + apiUrl)
|
||||
} catch (error) {
|
||||
|
23
src/renderer/utils/analytic.ts
Normal file
23
src/renderer/utils/analytic.ts
Normal file
@ -0,0 +1,23 @@
|
||||
/* eslint-disable camelcase */
|
||||
import {
|
||||
TALKING_DATA_APPID, TALKING_DATA_EVENT
|
||||
} from '~/universal/events/constants'
|
||||
import pkg from 'root/package.json'
|
||||
import { ipcRenderer } from 'electron'
|
||||
import { handleTalkingDataEvent } from './common'
|
||||
const { version } = pkg
|
||||
|
||||
export const initTalkingData = () => {
|
||||
setTimeout(() => {
|
||||
const talkingDataScript = document.createElement('script')
|
||||
|
||||
talkingDataScript.src = `http://sdk.talkingdata.com/app/h5/v1?appid=${TALKING_DATA_APPID}&vn=${version}&vc=${version}`
|
||||
|
||||
const head = document.getElementsByTagName('head')[0]
|
||||
head.appendChild(talkingDataScript)
|
||||
}, 0)
|
||||
}
|
||||
|
||||
ipcRenderer.on(TALKING_DATA_EVENT, (_, data: ITalkingDataOptions) => {
|
||||
handleTalkingDataEvent(data)
|
||||
})
|
@ -2,6 +2,16 @@ import { isReactive, isRef, toRaw, unref } from 'vue'
|
||||
import { ipcRenderer } from 'electron'
|
||||
import { OPEN_URL } from '~/universal/events/constants'
|
||||
|
||||
const isDevelopment = process.env.NODE_ENV !== 'production'
|
||||
export const handleTalkingDataEvent = (data: ITalkingDataOptions) => {
|
||||
const { EventId, Label = '', MapKv = {} } = data
|
||||
MapKv.from = window.location.href
|
||||
window.TDAPP.onEvent(EventId, Label, MapKv)
|
||||
if (isDevelopment) {
|
||||
console.log('talkingData', data)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get raw data from reactive or ref
|
||||
*/
|
||||
|
@ -1,6 +1,8 @@
|
||||
export const SHOW_INPUT_BOX = 'SHOW_INPUT_BOX'
|
||||
export const SHOW_INPUT_BOX_RESPONSE = 'SHOW_INPUT_BOX_RESPONSE'
|
||||
export const TOGGLE_SHORTKEY_MODIFIED_MODE = 'TOGGLE_SHORTKEY_MODIFIED_MODE'
|
||||
export const TALKING_DATA_APPID = 'B743C16E2989419A9B02EDE9D1E6A530'
|
||||
export const TALKING_DATA_EVENT = 'TALKING_DATA_EVENT'
|
||||
export const C1N = 'WjJoeFdWWklhVTlXYVRKTU5EUmFOVkEwUlVRPQ=='
|
||||
export const PICGO_SAVE_CONFIG = 'PICGO_SAVE_CONFIG'
|
||||
export const PICGO_GET_CONFIG = 'PICGO_GET_CONFIG'
|
||||
|
6
src/universal/types/types.d.ts
vendored
6
src/universal/types/types.d.ts
vendored
@ -128,6 +128,12 @@ interface IBounds {
|
||||
y: number
|
||||
}
|
||||
|
||||
interface ITalkingDataOptions {
|
||||
EventId: string
|
||||
Label?: string
|
||||
MapKv?: IStringKeyMap
|
||||
}
|
||||
|
||||
// PicGo Types
|
||||
type ICtx = import('piclist').PicGo
|
||||
interface IPicGoPlugin {
|
||||
|
@ -6,4 +6,4 @@ export const RELEASE_URL_BACKUP = 'https://release.piclist.cn'
|
||||
export const STABLE_RELEASE_URL = 'https://github.com/Kuingsmile/PicList/releases/latest'
|
||||
export const C1 = Buffer.from(C1N, 'base64').toString()
|
||||
|
||||
export const picBedsCanbeDeleted = ['aliyun', 'aws-s3', 'github', 'imgur', 'local', 'sftpplist', 'smms', 'qiniu', 'tcyun', 'upyun', 'webdavplist', 'dogecloud', 'huaweicloud-uploader', 'alist']
|
||||
export const picBedsCanbeDeleted = ['aliyun', 'aws-s3', 'github', 'imgur', 'local', 'sftpplist', 'smms', 'qiniu', 'tcyun', 'upyun', 'webdavplist', 'dogecloud', 'huaweicloud-uploader', 'alist', 'piclist']
|
||||
|
Loading…
Reference in New Issue
Block a user