mirror of
https://github.com/Kuingsmile/PicList.git
synced 2026-06-09 01:30:15 +08:00
🎨 Style(custom): lint code
This commit is contained in:
@@ -23,12 +23,12 @@ class RemoteNoticeHandler {
|
||||
private remoteNotice: IRemoteNotice | null = null
|
||||
private remoteNoticeLocalCountStorage: IRemoteNoticeLocalCountStorage | null = null
|
||||
|
||||
async init () {
|
||||
async init() {
|
||||
this.remoteNotice = await this.getRemoteNoticeInfo()
|
||||
this.initLocalCountStorage()
|
||||
}
|
||||
|
||||
private initLocalCountStorage () {
|
||||
private initLocalCountStorage() {
|
||||
const localCountStorage = {}
|
||||
if (!fs.existsSync(REMOTE_NOTICE_LOCAL_STORAGE_PATH)) {
|
||||
fs.writeFileSync(REMOTE_NOTICE_LOCAL_STORAGE_PATH, JSON.stringify({}))
|
||||
@@ -44,14 +44,14 @@ class RemoteNoticeHandler {
|
||||
}
|
||||
}
|
||||
|
||||
private saveLocalCountStorage (newData?: IRemoteNoticeLocalCountStorage) {
|
||||
private saveLocalCountStorage(newData?: IRemoteNoticeLocalCountStorage) {
|
||||
if (newData) {
|
||||
this.remoteNoticeLocalCountStorage = newData
|
||||
}
|
||||
fs.writeFileSync(REMOTE_NOTICE_LOCAL_STORAGE_PATH, JSON.stringify(this.remoteNoticeLocalCountStorage))
|
||||
}
|
||||
|
||||
private async getRemoteNoticeInfo (): Promise<IRemoteNotice | null> {
|
||||
private async getRemoteNoticeInfo(): Promise<IRemoteNotice | null> {
|
||||
try {
|
||||
const noticeInfo = (await axios({
|
||||
method: 'get',
|
||||
@@ -68,7 +68,7 @@ class RemoteNoticeHandler {
|
||||
* if the notice is not shown or is always shown, then show the notice
|
||||
* @param action
|
||||
*/
|
||||
private checkActionCount (action: IRemoteNoticeAction) {
|
||||
private checkActionCount(action: IRemoteNoticeAction) {
|
||||
try {
|
||||
if (!this.remoteNoticeLocalCountStorage) {
|
||||
return true
|
||||
@@ -102,7 +102,7 @@ class RemoteNoticeHandler {
|
||||
}
|
||||
}
|
||||
|
||||
private async doActions (actions: IRemoteNoticeAction[]) {
|
||||
private async doActions(actions: IRemoteNoticeAction[]) {
|
||||
for (const action of actions) {
|
||||
if (this.checkActionCount(action)) {
|
||||
switch (action.type) {
|
||||
@@ -117,7 +117,7 @@ class RemoteNoticeHandler {
|
||||
body: action.data?.content || '',
|
||||
clickToCopy: !!action.data?.copyToClipboard,
|
||||
copyContent: action.data?.copyToClipboard || '',
|
||||
clickFn () {
|
||||
clickFn() {
|
||||
if (action.data?.url) {
|
||||
shell.openExternal(action.data.url)
|
||||
}
|
||||
@@ -163,7 +163,7 @@ class RemoteNoticeHandler {
|
||||
}
|
||||
}
|
||||
|
||||
triggerHook (hook: string) {
|
||||
triggerHook(hook: string) {
|
||||
if (!this.remoteNotice || !this.remoteNotice.list) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -6,24 +6,30 @@ import shortKeyService from 'apis/app/shortKey/shortKeyService'
|
||||
import GuiApi from 'apis/gui'
|
||||
import { globalShortcut } from 'electron'
|
||||
|
||||
import type { IKeyCommandType, IPluginShortKeyConfig, IShortKeyConfig, IShortKeyConfigs, IShortKeyHandler } from '#/types/types'
|
||||
import type {
|
||||
IKeyCommandType,
|
||||
IPluginShortKeyConfig,
|
||||
IShortKeyConfig,
|
||||
IShortKeyConfigs,
|
||||
IShortKeyHandler
|
||||
} from '#/types/types'
|
||||
import { TOGGLE_SHORTKEY_MODIFIED_MODE } from '~/events/constant'
|
||||
import { configPaths } from '~/utils/configPaths'
|
||||
|
||||
class ShortKeyHandler {
|
||||
private isInModifiedMode: boolean = false
|
||||
constructor () {
|
||||
constructor() {
|
||||
bus.on(TOGGLE_SHORTKEY_MODIFIED_MODE, flag => {
|
||||
this.isInModifiedMode = flag
|
||||
})
|
||||
}
|
||||
|
||||
async init () {
|
||||
async init() {
|
||||
this.initBuiltInShortKey()
|
||||
await this.initPluginsShortKey()
|
||||
}
|
||||
|
||||
private initBuiltInShortKey () {
|
||||
private initBuiltInShortKey() {
|
||||
const commands = db.get(configPaths.settings.shortKey._path) as IShortKeyConfigs
|
||||
Object.keys(commands)
|
||||
.filter(item => item.includes('picgo:'))
|
||||
@@ -38,7 +44,7 @@ class ShortKeyHandler {
|
||||
})
|
||||
}
|
||||
|
||||
private async initPluginsShortKey () {
|
||||
private async initPluginsShortKey() {
|
||||
// get enabled plugin
|
||||
const pluginList = picgo.pluginLoader.getList()
|
||||
for (const item of pluginList) {
|
||||
@@ -68,7 +74,7 @@ class ShortKeyHandler {
|
||||
}
|
||||
}
|
||||
|
||||
private registerShortKey (
|
||||
private registerShortKey(
|
||||
config: IShortKeyConfig | IPluginShortKeyConfig,
|
||||
command: string,
|
||||
handler: IShortKeyHandler,
|
||||
@@ -97,7 +103,7 @@ class ShortKeyHandler {
|
||||
}
|
||||
|
||||
// enable or disable shortKey
|
||||
bindOrUnbindShortKey (item: IShortKeyConfig, from: string): boolean {
|
||||
bindOrUnbindShortKey(item: IShortKeyConfig, from: string): boolean {
|
||||
const command = `${from}:${item.name}`
|
||||
if (item.enable === false) {
|
||||
globalShortcut.unregister(item.key)
|
||||
@@ -121,7 +127,7 @@ class ShortKeyHandler {
|
||||
}
|
||||
|
||||
// update shortKey bindings
|
||||
updateShortKey (item: IShortKeyConfig, oldKey: string, from: string): boolean {
|
||||
updateShortKey(item: IShortKeyConfig, oldKey: string, from: string): boolean {
|
||||
const command = `${from}:${item.name}`
|
||||
if (globalShortcut.isRegistered(item.key)) return false
|
||||
globalShortcut.unregister(oldKey)
|
||||
@@ -134,7 +140,7 @@ class ShortKeyHandler {
|
||||
return true
|
||||
}
|
||||
|
||||
private async handler (command: string) {
|
||||
private async handler(command: string) {
|
||||
if (this.isInModifiedMode) {
|
||||
return
|
||||
}
|
||||
@@ -150,7 +156,7 @@ class ShortKeyHandler {
|
||||
}
|
||||
}
|
||||
|
||||
async registerPluginShortKey (pluginName: string) {
|
||||
async registerPluginShortKey(pluginName: string) {
|
||||
const plugin = await picgo.pluginLoader.getPlugin(pluginName)
|
||||
if (plugin && plugin.commands) {
|
||||
if (typeof plugin.commands !== 'function') {
|
||||
@@ -170,7 +176,7 @@ class ShortKeyHandler {
|
||||
}
|
||||
}
|
||||
|
||||
unregisterPluginShortKey (pluginName: string) {
|
||||
unregisterPluginShortKey(pluginName: string) {
|
||||
const commands = db.get(configPaths.settings.shortKey._path) as IShortKeyConfigs
|
||||
const keyList = Object.keys(commands)
|
||||
.filter(command => command.includes(pluginName))
|
||||
|
||||
@@ -4,22 +4,22 @@ import type { IShortKeyHandler } from '#/types/types'
|
||||
|
||||
class ShortKeyService {
|
||||
private commandList: Map<string, IShortKeyHandler> = new Map()
|
||||
registerCommand (command: string, handler: IShortKeyHandler) {
|
||||
registerCommand(command: string, handler: IShortKeyHandler) {
|
||||
this.commandList.set(command, handler)
|
||||
}
|
||||
|
||||
unregisterCommand (command: string) {
|
||||
unregisterCommand(command: string) {
|
||||
this.commandList.delete(command)
|
||||
}
|
||||
|
||||
getShortKeyHandler (command: string): IShortKeyHandler | null {
|
||||
getShortKeyHandler(command: string): IShortKeyHandler | null {
|
||||
const handler = this.commandList.get(command)
|
||||
if (handler) return handler
|
||||
logger.warn(`cannot find command: ${command}`)
|
||||
return null
|
||||
}
|
||||
|
||||
getCommandList () {
|
||||
getCommandList() {
|
||||
return [...this.commandList.keys()]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ import uploadPng from '../../../../../resources/upload.png?asset&asarUnpack'
|
||||
import uploadDarkPng from '../../../../../resources/upload-dark.png?asset&asarUnpack'
|
||||
let contextMenu: Menu | null
|
||||
|
||||
export function setDockMenu () {
|
||||
export function setDockMenu() {
|
||||
const isListeningClipboard = db.get(configPaths.settings.isListeningClipboard) || false
|
||||
const dockMenu = Menu.buildFromTemplate([
|
||||
{
|
||||
@@ -45,7 +45,7 @@ export function setDockMenu () {
|
||||
},
|
||||
{
|
||||
label: $t('START_WATCH_CLIPBOARD'),
|
||||
click () {
|
||||
click() {
|
||||
db.set(configPaths.settings.isListeningClipboard, true)
|
||||
clipboardPoll.startListening()
|
||||
clipboardPoll.on('change', () => {
|
||||
@@ -58,7 +58,7 @@ export function setDockMenu () {
|
||||
},
|
||||
{
|
||||
label: $t('STOP_WATCH_CLIPBOARD'),
|
||||
click () {
|
||||
click() {
|
||||
db.set(configPaths.settings.isListeningClipboard, false)
|
||||
clipboardPoll.stopListening()
|
||||
clipboardPoll.removeAllListeners()
|
||||
@@ -70,7 +70,7 @@ export function setDockMenu () {
|
||||
app.dock?.setMenu(dockMenu)
|
||||
}
|
||||
|
||||
export function createMenu () {
|
||||
export function createMenu() {
|
||||
const submenu = buildPicBedListMenu()
|
||||
const appMenu = Menu.buildFromTemplate([
|
||||
{
|
||||
@@ -79,7 +79,7 @@ export function createMenu () {
|
||||
{ label: $t('OPEN_MAIN_WINDOW'), click: openMainWindow },
|
||||
{
|
||||
label: $t('RELOAD_APP'),
|
||||
click () {
|
||||
click() {
|
||||
app.relaunch()
|
||||
app.exit(0)
|
||||
}
|
||||
@@ -107,7 +107,7 @@ export function createMenu () {
|
||||
Menu.setApplicationMenu(appMenu)
|
||||
}
|
||||
|
||||
export function createContextMenu () {
|
||||
export function createContextMenu() {
|
||||
const ClipboardWatcher = clipboardPoll
|
||||
const isListeningClipboard = db.get(configPaths.settings.isListeningClipboard) || false
|
||||
const isMiniWindowVisible =
|
||||
@@ -147,7 +147,7 @@ export function createContextMenu () {
|
||||
},
|
||||
{
|
||||
label: $t('RELOAD_APP'),
|
||||
click () {
|
||||
click() {
|
||||
app.relaunch()
|
||||
app.exit(0)
|
||||
}
|
||||
@@ -160,7 +160,7 @@ export function createContextMenu () {
|
||||
0,
|
||||
{
|
||||
label: $t('OPEN_MINI_WINDOW'),
|
||||
click () {
|
||||
click() {
|
||||
openMiniWindow(false)
|
||||
},
|
||||
visible: !isMiniWindowVisible
|
||||
@@ -185,7 +185,7 @@ export function createContextMenu () {
|
||||
{ label: $t('OPEN_MAIN_WINDOW'), click: openMainWindow },
|
||||
{
|
||||
label: $t('OPEN_MINI_WINDOW'),
|
||||
click () {
|
||||
click() {
|
||||
openMiniWindow(false)
|
||||
},
|
||||
visible: !isMiniWindowVisible
|
||||
@@ -207,7 +207,7 @@ export function createContextMenu () {
|
||||
},
|
||||
{
|
||||
label: $t('ABOUT'),
|
||||
click () {
|
||||
click() {
|
||||
dialog.showMessageBox({
|
||||
title: 'PicList',
|
||||
message: 'PicList',
|
||||
@@ -230,7 +230,7 @@ const getTrayIcon = () => {
|
||||
}
|
||||
}
|
||||
|
||||
export function createTray (tooltip: string) {
|
||||
export function createTray(tooltip: string) {
|
||||
const menubarPic = getTrayIcon()
|
||||
setTray(new Tray(menubarPic))
|
||||
tray.setToolTip(tooltip)
|
||||
@@ -309,7 +309,7 @@ export function createTray (tooltip: string) {
|
||||
// drop-files only be supported in macOS
|
||||
// so the tray window must be available
|
||||
if (process.platform === 'darwin') {
|
||||
(tray as any).on('drop-files', async (_: Event, files: string[]) => {
|
||||
;(tray as any).on('drop-files', async (_: Event, files: string[]) => {
|
||||
const pasteStyle = db.get(configPaths.settings.pasteStyle) || IPasteStyle.MARKDOWN
|
||||
const rawInput = cloneDeep(files)
|
||||
const trayWindow = windowManager.get(IWindowList.TRAY_WINDOW)!
|
||||
@@ -338,14 +338,14 @@ export function createTray (tooltip: string) {
|
||||
imgs[i].shortUrl = shortUrl
|
||||
pasteText.push(pasteTextItem)
|
||||
const isShowResultNotification =
|
||||
db.get(configPaths.settings.uploadResultNotification) === undefined
|
||||
? true
|
||||
: !!db.get(configPaths.settings.uploadResultNotification)
|
||||
db.get(configPaths.settings.uploadResultNotification) === undefined
|
||||
? true
|
||||
: !!db.get(configPaths.settings.uploadResultNotification)
|
||||
if (isShowResultNotification) {
|
||||
const notification = new Notification({
|
||||
title: $t('UPLOAD_SUCCEED'),
|
||||
body: shortUrl || imgs[i].imgUrl!
|
||||
// icon: files[i]
|
||||
// icon: files[i]
|
||||
})
|
||||
setTimeout(() => {
|
||||
notification.show()
|
||||
|
||||
@@ -1,236 +1,236 @@
|
||||
import db, { GalleryDB } from '@core/datastore'
|
||||
import picgo from '@core/picgo'
|
||||
import uploader from 'apis/app/uploader'
|
||||
import windowManager from 'apis/app/window/windowManager'
|
||||
import { Notification, WebContents } from 'electron'
|
||||
import fs from 'fs-extra'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import type { IPicGo } from 'piclist'
|
||||
|
||||
import type { IFileWithPath, ImgInfo, IStringKeyMap, IUploadOption } from '#/types/types'
|
||||
import { T as $t } from '~/i18n/index'
|
||||
import { handleCopyUrl, handleUrlEncodeWithSetting } from '~/utils/common'
|
||||
import { configPaths } from '~/utils/configPaths'
|
||||
import { IPasteStyle, IWindowList } from '~/utils/enum'
|
||||
import { changeCurrentUploader } from '~/utils/handleUploaderConfig'
|
||||
import pasteTemplate from '~/utils/pasteTemplate'
|
||||
|
||||
const handleClipboardUploading = async (): Promise<false | ImgInfo[]> => {
|
||||
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).uploadWithBuildInClipboard()
|
||||
}
|
||||
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> => {
|
||||
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)
|
||||
const pasteStyle = db.get(configPaths.settings.pasteStyle) || IPasteStyle.MARKDOWN
|
||||
const [pastedText, shortUrl] = await pasteTemplate(pasteStyle, img[0], db.get(configPaths.settings.customLink))
|
||||
img[0].shortUrl = shortUrl
|
||||
handleCopyUrl(pastedText)
|
||||
const isShowResultNotification =
|
||||
db.get(configPaths.settings.uploadResultNotification) === undefined
|
||||
? true
|
||||
: !!db.get(configPaths.settings.uploadResultNotification)
|
||||
if (isShowResultNotification) {
|
||||
const notification = new Notification({
|
||||
title: $t('UPLOAD_SUCCEED'),
|
||||
body: shortUrl || img[0].imgUrl!
|
||||
// icon: img[0].imgUrl
|
||||
})
|
||||
setTimeout(() => {
|
||||
notification.show()
|
||||
}, 100)
|
||||
}
|
||||
const inserted = await GalleryDB.getInstance().insert(img[0])
|
||||
// trayWindow just be created in mac/windows, not in linux
|
||||
trayWindow?.webContents?.send('clipboardFiles', [])
|
||||
trayWindow?.webContents?.send('uploadFiles', img)
|
||||
if (windowManager.has(IWindowList.SETTING_WINDOW)) {
|
||||
windowManager.get(IWindowList.SETTING_WINDOW)!.webContents?.send('updateGallery')
|
||||
}
|
||||
return {
|
||||
url: handleUrlEncodeWithSetting(inserted.imgUrl as string),
|
||||
fullResult: inserted
|
||||
}
|
||||
} else {
|
||||
const notification = new Notification({
|
||||
title: $t('UPLOAD_FAILED'),
|
||||
body: $t('TIPS_UPLOAD_NOT_PICTURES')
|
||||
})
|
||||
notification.show()
|
||||
return {
|
||||
url: '',
|
||||
fullResult: {}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
url: '',
|
||||
fullResult: {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const uploadChoosedFiles = async (
|
||||
webContents: WebContents,
|
||||
files: IFileWithPath[]
|
||||
): Promise<IStringKeyMap[]> => {
|
||||
const input = files.map(item => item.path)
|
||||
const rawInput = cloneDeep(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
|
||||
const deleteLocalFile = db.get(configPaths.settings.deleteLocalFile) || false
|
||||
const pasteText: string[] = []
|
||||
for (let i = 0; i < imgs.length; i++) {
|
||||
if (deleteLocalFile) {
|
||||
fs.remove(rawInput[i])
|
||||
.then(() => {
|
||||
picgo.log.info(`delete local file: ${rawInput[i]}`)
|
||||
})
|
||||
.catch((err: Error) => {
|
||||
picgo.log.error(err)
|
||||
})
|
||||
}
|
||||
const [pasteTextItem, shortUrl] = await pasteTemplate(
|
||||
pasteStyle,
|
||||
imgs[i],
|
||||
db.get(configPaths.settings.customLink)
|
||||
)
|
||||
imgs[i].shortUrl = shortUrl
|
||||
pasteText.push(pasteTextItem)
|
||||
const isShowResultNotification =
|
||||
db.get(configPaths.settings.uploadResultNotification) === undefined
|
||||
? true
|
||||
: !!db.get(configPaths.settings.uploadResultNotification)
|
||||
if (isShowResultNotification) {
|
||||
const notification = new Notification({
|
||||
title: $t('UPLOAD_SUCCEED'),
|
||||
body: shortUrl || imgs[i].imgUrl!
|
||||
// icon: files[i].path
|
||||
})
|
||||
setTimeout(() => {
|
||||
notification.show()
|
||||
}, i * 100)
|
||||
}
|
||||
const inserted = await GalleryDB.getInstance().insert(imgs[i])
|
||||
result.push({
|
||||
url: handleUrlEncodeWithSetting(inserted.imgUrl!),
|
||||
fullResult: inserted
|
||||
})
|
||||
}
|
||||
handleCopyUrl(pasteText.join('\n'))
|
||||
// trayWindow just be created in mac/windows, not in linux
|
||||
windowManager.get(IWindowList.TRAY_WINDOW)?.webContents?.send('uploadFiles', imgs)
|
||||
if (windowManager.has(IWindowList.SETTING_WINDOW)) {
|
||||
windowManager.get(IWindowList.SETTING_WINDOW)!.webContents?.send('updateGallery')
|
||||
}
|
||||
return result
|
||||
} else {
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
export const handleSecondaryUpload = async (
|
||||
webContents?: WebContents,
|
||||
input?: string[],
|
||||
uploadType: 'clipboard' | 'file' | 'tray' = 'file'
|
||||
): 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)
|
||||
const secondUploaderId = db.get(configPaths.picBed.secondUploaderId)
|
||||
const currentPicBed = db.get('picBed') || ({} as IStringKeyMap)
|
||||
currentPicBedType = currentPicBed.uploader || currentPicBed.current || 'smms'
|
||||
currentPicBedConfig = currentPicBed[currentPicBedType] || ({} as IStringKeyMap)
|
||||
currentPicBedConfigId = currentPicBedConfig._id
|
||||
if (
|
||||
secondUploader === currentPicBedType &&
|
||||
secondUploaderConfig._configName === currentPicBedConfig._configName &&
|
||||
secondUploaderId === currentPicBedConfigId
|
||||
) {
|
||||
picgo.log.info('second uploader is the same as current uploader')
|
||||
} else {
|
||||
needRestore = true
|
||||
let secondImgs: ImgInfo[] | false = false
|
||||
changeCurrentUploader(secondUploader, secondUploaderConfig, secondUploaderId)
|
||||
if (uploadType === 'clipboard') {
|
||||
ctx = await handleClipboardUploadingReturnCtx(undefined)
|
||||
} else {
|
||||
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') {
|
||||
if (secondImgs.length > 0) {
|
||||
await GalleryDB.getInstance().insert(secondImgs[0])
|
||||
trayWindow?.webContents?.send('clipboardFiles', [])
|
||||
trayWindow?.webContents?.send('uploadFiles', secondImgs)
|
||||
}
|
||||
} else {
|
||||
for (const secondImgsItem of secondImgs) {
|
||||
await GalleryDB.getInstance().insert(secondImgsItem)
|
||||
}
|
||||
if (uploadType === 'tray') {
|
||||
trayWindow?.webContents?.send('dragFiles', secondImgs)
|
||||
} else {
|
||||
trayWindow?.webContents?.send('uploadFiles', secondImgs)
|
||||
}
|
||||
}
|
||||
if (windowManager.has(IWindowList.SETTING_WINDOW) && uploadType !== 'tray') {
|
||||
windowManager.get(IWindowList.SETTING_WINDOW)!.webContents?.send('updateGallery')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (needRestore) {
|
||||
changeCurrentUploader(currentPicBedType, currentPicBedConfig, currentPicBedConfigId)
|
||||
}
|
||||
return {
|
||||
needRestore,
|
||||
ctx
|
||||
}
|
||||
}
|
||||
import db, { GalleryDB } from '@core/datastore'
|
||||
import picgo from '@core/picgo'
|
||||
import uploader from 'apis/app/uploader'
|
||||
import windowManager from 'apis/app/window/windowManager'
|
||||
import { Notification, WebContents } from 'electron'
|
||||
import fs from 'fs-extra'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import type { IPicGo } from 'piclist'
|
||||
|
||||
import type { IFileWithPath, ImgInfo, IStringKeyMap, IUploadOption } from '#/types/types'
|
||||
import { T as $t } from '~/i18n/index'
|
||||
import { handleCopyUrl, handleUrlEncodeWithSetting } from '~/utils/common'
|
||||
import { configPaths } from '~/utils/configPaths'
|
||||
import { IPasteStyle, IWindowList } from '~/utils/enum'
|
||||
import { changeCurrentUploader } from '~/utils/handleUploaderConfig'
|
||||
import pasteTemplate from '~/utils/pasteTemplate'
|
||||
|
||||
const handleClipboardUploading = async (): Promise<false | ImgInfo[]> => {
|
||||
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).uploadWithBuildInClipboard()
|
||||
}
|
||||
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> => {
|
||||
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)
|
||||
const pasteStyle = db.get(configPaths.settings.pasteStyle) || IPasteStyle.MARKDOWN
|
||||
const [pastedText, shortUrl] = await pasteTemplate(pasteStyle, img[0], db.get(configPaths.settings.customLink))
|
||||
img[0].shortUrl = shortUrl
|
||||
handleCopyUrl(pastedText)
|
||||
const isShowResultNotification =
|
||||
db.get(configPaths.settings.uploadResultNotification) === undefined
|
||||
? true
|
||||
: !!db.get(configPaths.settings.uploadResultNotification)
|
||||
if (isShowResultNotification) {
|
||||
const notification = new Notification({
|
||||
title: $t('UPLOAD_SUCCEED'),
|
||||
body: shortUrl || img[0].imgUrl!
|
||||
// icon: img[0].imgUrl
|
||||
})
|
||||
setTimeout(() => {
|
||||
notification.show()
|
||||
}, 100)
|
||||
}
|
||||
const inserted = await GalleryDB.getInstance().insert(img[0])
|
||||
// trayWindow just be created in mac/windows, not in linux
|
||||
trayWindow?.webContents?.send('clipboardFiles', [])
|
||||
trayWindow?.webContents?.send('uploadFiles', img)
|
||||
if (windowManager.has(IWindowList.SETTING_WINDOW)) {
|
||||
windowManager.get(IWindowList.SETTING_WINDOW)!.webContents?.send('updateGallery')
|
||||
}
|
||||
return {
|
||||
url: handleUrlEncodeWithSetting(inserted.imgUrl as string),
|
||||
fullResult: inserted
|
||||
}
|
||||
} else {
|
||||
const notification = new Notification({
|
||||
title: $t('UPLOAD_FAILED'),
|
||||
body: $t('TIPS_UPLOAD_NOT_PICTURES')
|
||||
})
|
||||
notification.show()
|
||||
return {
|
||||
url: '',
|
||||
fullResult: {}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
url: '',
|
||||
fullResult: {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const uploadChoosedFiles = async (
|
||||
webContents: WebContents,
|
||||
files: IFileWithPath[]
|
||||
): Promise<IStringKeyMap[]> => {
|
||||
const input = files.map(item => item.path)
|
||||
const rawInput = cloneDeep(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
|
||||
const deleteLocalFile = db.get(configPaths.settings.deleteLocalFile) || false
|
||||
const pasteText: string[] = []
|
||||
for (let i = 0; i < imgs.length; i++) {
|
||||
if (deleteLocalFile) {
|
||||
fs.remove(rawInput[i])
|
||||
.then(() => {
|
||||
picgo.log.info(`delete local file: ${rawInput[i]}`)
|
||||
})
|
||||
.catch((err: Error) => {
|
||||
picgo.log.error(err)
|
||||
})
|
||||
}
|
||||
const [pasteTextItem, shortUrl] = await pasteTemplate(
|
||||
pasteStyle,
|
||||
imgs[i],
|
||||
db.get(configPaths.settings.customLink)
|
||||
)
|
||||
imgs[i].shortUrl = shortUrl
|
||||
pasteText.push(pasteTextItem)
|
||||
const isShowResultNotification =
|
||||
db.get(configPaths.settings.uploadResultNotification) === undefined
|
||||
? true
|
||||
: !!db.get(configPaths.settings.uploadResultNotification)
|
||||
if (isShowResultNotification) {
|
||||
const notification = new Notification({
|
||||
title: $t('UPLOAD_SUCCEED'),
|
||||
body: shortUrl || imgs[i].imgUrl!
|
||||
// icon: files[i].path
|
||||
})
|
||||
setTimeout(() => {
|
||||
notification.show()
|
||||
}, i * 100)
|
||||
}
|
||||
const inserted = await GalleryDB.getInstance().insert(imgs[i])
|
||||
result.push({
|
||||
url: handleUrlEncodeWithSetting(inserted.imgUrl!),
|
||||
fullResult: inserted
|
||||
})
|
||||
}
|
||||
handleCopyUrl(pasteText.join('\n'))
|
||||
// trayWindow just be created in mac/windows, not in linux
|
||||
windowManager.get(IWindowList.TRAY_WINDOW)?.webContents?.send('uploadFiles', imgs)
|
||||
if (windowManager.has(IWindowList.SETTING_WINDOW)) {
|
||||
windowManager.get(IWindowList.SETTING_WINDOW)!.webContents?.send('updateGallery')
|
||||
}
|
||||
return result
|
||||
} else {
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
export const handleSecondaryUpload = async (
|
||||
webContents?: WebContents,
|
||||
input?: string[],
|
||||
uploadType: 'clipboard' | 'file' | 'tray' = 'file'
|
||||
): 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)
|
||||
const secondUploaderId = db.get(configPaths.picBed.secondUploaderId)
|
||||
const currentPicBed = db.get('picBed') || ({} as IStringKeyMap)
|
||||
currentPicBedType = currentPicBed.uploader || currentPicBed.current || 'smms'
|
||||
currentPicBedConfig = currentPicBed[currentPicBedType] || ({} as IStringKeyMap)
|
||||
currentPicBedConfigId = currentPicBedConfig._id
|
||||
if (
|
||||
secondUploader === currentPicBedType &&
|
||||
secondUploaderConfig._configName === currentPicBedConfig._configName &&
|
||||
secondUploaderId === currentPicBedConfigId
|
||||
) {
|
||||
picgo.log.info('second uploader is the same as current uploader')
|
||||
} else {
|
||||
needRestore = true
|
||||
let secondImgs: ImgInfo[] | false = false
|
||||
changeCurrentUploader(secondUploader, secondUploaderConfig, secondUploaderId)
|
||||
if (uploadType === 'clipboard') {
|
||||
ctx = await handleClipboardUploadingReturnCtx(undefined)
|
||||
} else {
|
||||
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') {
|
||||
if (secondImgs.length > 0) {
|
||||
await GalleryDB.getInstance().insert(secondImgs[0])
|
||||
trayWindow?.webContents?.send('clipboardFiles', [])
|
||||
trayWindow?.webContents?.send('uploadFiles', secondImgs)
|
||||
}
|
||||
} else {
|
||||
for (const secondImgsItem of secondImgs) {
|
||||
await GalleryDB.getInstance().insert(secondImgsItem)
|
||||
}
|
||||
if (uploadType === 'tray') {
|
||||
trayWindow?.webContents?.send('dragFiles', secondImgs)
|
||||
} else {
|
||||
trayWindow?.webContents?.send('uploadFiles', secondImgs)
|
||||
}
|
||||
}
|
||||
if (windowManager.has(IWindowList.SETTING_WINDOW) && uploadType !== 'tray') {
|
||||
windowManager.get(IWindowList.SETTING_WINDOW)!.webContents?.send('updateGallery')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (needRestore) {
|
||||
changeCurrentUploader(currentPicBedType, currentPicBedConfig, currentPicBedConfigId)
|
||||
}
|
||||
return {
|
||||
needRestore,
|
||||
ctx
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,11 +36,11 @@ const waitForRename = (window: BrowserWindow, id: number): Promise<string | null
|
||||
class Uploader {
|
||||
private webContents: WebContents | null = null
|
||||
|
||||
constructor () {
|
||||
constructor() {
|
||||
this.init()
|
||||
}
|
||||
|
||||
init () {
|
||||
init() {
|
||||
picgo.on(ICOREBuildInEvent.NOTIFICATION, (message: any) => {
|
||||
new Notification(message).show()
|
||||
})
|
||||
@@ -92,12 +92,12 @@ class Uploader {
|
||||
})
|
||||
}
|
||||
|
||||
setWebContents (webContents: WebContents) {
|
||||
setWebContents(webContents: WebContents) {
|
||||
this.webContents = webContents
|
||||
return this
|
||||
}
|
||||
|
||||
private async getClipboardImagePath (): Promise<string | false> {
|
||||
private async getClipboardImagePath(): Promise<string | false> {
|
||||
const imgPath = getClipboardFilePath()
|
||||
if (imgPath) return imgPath
|
||||
|
||||
@@ -115,7 +115,7 @@ class Uploader {
|
||||
/**
|
||||
* use electron's clipboard image to upload
|
||||
*/
|
||||
async uploadWithBuildInClipboard (): Promise<ImgInfo[] | false> {
|
||||
async uploadWithBuildInClipboard(): Promise<ImgInfo[] | false> {
|
||||
let imgPath: string | false = false
|
||||
try {
|
||||
imgPath = await this.getClipboardImagePath()
|
||||
@@ -131,7 +131,7 @@ class Uploader {
|
||||
}
|
||||
}
|
||||
|
||||
async uploadWithBuildInClipboardReturnCtx (img?: IUploadOption, skipProcess = false): Promise<IPicGo | false> {
|
||||
async uploadWithBuildInClipboardReturnCtx(img?: IUploadOption, skipProcess = false): Promise<IPicGo | false> {
|
||||
let imgPath: string | false = false
|
||||
try {
|
||||
imgPath = await this.getClipboardImagePath()
|
||||
@@ -147,7 +147,7 @@ class Uploader {
|
||||
}
|
||||
}
|
||||
|
||||
async uploadReturnCtx (img?: IUploadOption, skipProcess = false): Promise<IPicGo | false> {
|
||||
async uploadReturnCtx(img?: IUploadOption, skipProcess = false): Promise<IPicGo | false> {
|
||||
try {
|
||||
const ctx = await picgo.uploadReturnCtx(img, skipProcess)
|
||||
if (!Array.isArray(ctx.output) || !ctx.output.some((item: ImgInfo) => item.imgUrl)) return false
|
||||
@@ -172,7 +172,7 @@ class Uploader {
|
||||
}
|
||||
}
|
||||
|
||||
async upload (img?: IUploadOption): Promise<ImgInfo[] | false> {
|
||||
async upload(img?: IUploadOption): Promise<ImgInfo[] | false> {
|
||||
try {
|
||||
const output = await picgo.upload(img)
|
||||
if (!Array.isArray(output) || !output.some((item: ImgInfo) => item.imgUrl)) return false
|
||||
|
||||
@@ -1,277 +1,277 @@
|
||||
import path from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
import bus from '@core/bus'
|
||||
import { CREATE_APP_MENU } from '@core/bus/constants'
|
||||
import db from '@core/datastore'
|
||||
import { app, BrowserWindow, Rectangle } from 'electron'
|
||||
|
||||
import type { IWindowListItem } from '#/types/electron'
|
||||
import type { IBrowserWindowOptions } from '#/types/types'
|
||||
import { TOGGLE_SHORTKEY_MODIFIED_MODE } from '~/events/constant'
|
||||
import { T as $t } from '~/i18n'
|
||||
import { configPaths } from '~/utils/configPaths'
|
||||
import { IWindowList } from '~/utils/enum'
|
||||
|
||||
import logo from '../../../../../resources/logo.png?asset&asarUnpack'
|
||||
|
||||
const windowList = new Map<string, IWindowListItem>()
|
||||
|
||||
const getDefaultWindowSizes = (): { width: number; height: number } => {
|
||||
const [mainWindowWidth, mainWindowHeight] = db.get([
|
||||
configPaths.settings.mainWindowWidth,
|
||||
configPaths.settings.mainWindowHeight
|
||||
])
|
||||
return {
|
||||
width: mainWindowWidth || 1200,
|
||||
height: mainWindowHeight || 800
|
||||
}
|
||||
}
|
||||
|
||||
function setMiniWindowShape (win: BrowserWindow) {
|
||||
const radius = 32
|
||||
const shape: Rectangle[] = []
|
||||
|
||||
for (let y = -radius; y <= radius; y++) {
|
||||
for (let x = -radius; x <= radius; x++) {
|
||||
if (x * x + y * y <= radius * radius) {
|
||||
shape.push({ x: radius + x, y: radius + y, width: 1, height: 1 })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
win.setShape(shape)
|
||||
}
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
||||
const preloadPath = fileURLToPath(new URL('../preload/index.mjs', import.meta.url))
|
||||
|
||||
const { width: defaultWindowWidth, height: defaultWindowHeight } = getDefaultWindowSizes()
|
||||
|
||||
const trayWindowOptions = {
|
||||
height: 350,
|
||||
width: 196,
|
||||
show: false,
|
||||
frame: false,
|
||||
fullscreenable: false,
|
||||
resizable: false,
|
||||
transparent: true,
|
||||
vibrancy: 'ultra-dark',
|
||||
webPreferences: {
|
||||
sandbox: false,
|
||||
preload: preloadPath,
|
||||
nodeIntegration: false,
|
||||
contextIsolation: true,
|
||||
nodeIntegrationInWorker: false,
|
||||
backgroundThrottling: true,
|
||||
webSecurity: false
|
||||
}
|
||||
}
|
||||
|
||||
const settingWindowOptions = {
|
||||
height: defaultWindowHeight,
|
||||
width: defaultWindowWidth,
|
||||
show: false,
|
||||
frame: true,
|
||||
center: true,
|
||||
fullscreenable: true,
|
||||
resizable: true,
|
||||
title: 'PicList',
|
||||
transparent: false,
|
||||
backgroundColor: '#ebeef5',
|
||||
titleBarStyle: 'hidden',
|
||||
webPreferences: {
|
||||
sandbox: false,
|
||||
webviewTag: true,
|
||||
backgroundThrottling: true,
|
||||
preload: preloadPath,
|
||||
nodeIntegration: false,
|
||||
contextIsolation: true,
|
||||
nodeIntegrationInWorker: false,
|
||||
webSecurity: false
|
||||
}
|
||||
} as IBrowserWindowOptions
|
||||
|
||||
if (process.platform !== 'darwin') {
|
||||
settingWindowOptions.frame = false
|
||||
settingWindowOptions.icon = logo
|
||||
}
|
||||
|
||||
const miniWindowOptions = {
|
||||
height: 64,
|
||||
width: 64,
|
||||
show: process.platform === 'linux',
|
||||
frame: false,
|
||||
fullscreenable: false,
|
||||
skipTaskbar: true,
|
||||
resizable: false,
|
||||
transparent: process.platform !== 'linux',
|
||||
icon: logo,
|
||||
webPreferences: {
|
||||
sandbox: false,
|
||||
preload: preloadPath,
|
||||
nodeIntegration: false,
|
||||
contextIsolation: true,
|
||||
backgroundThrottling: true,
|
||||
nodeIntegrationInWorker: false
|
||||
}
|
||||
} as IBrowserWindowOptions
|
||||
|
||||
if (db.get(configPaths.settings.miniWindowOntop)) {
|
||||
miniWindowOptions.alwaysOnTop = true
|
||||
}
|
||||
|
||||
const renameWindowOptions = {
|
||||
height: 270,
|
||||
width: 350,
|
||||
show: true,
|
||||
fullscreenable: false,
|
||||
icon: logo,
|
||||
resizable: true,
|
||||
webPreferences: {
|
||||
sandbox: false,
|
||||
preload: preloadPath,
|
||||
nodeIntegration: false,
|
||||
contextIsolation: true,
|
||||
nodeIntegrationInWorker: false,
|
||||
backgroundThrottling: false
|
||||
}
|
||||
} as IBrowserWindowOptions
|
||||
|
||||
if (process.platform !== 'darwin') {
|
||||
renameWindowOptions.show = true
|
||||
renameWindowOptions.backgroundColor = '#3f3c37'
|
||||
renameWindowOptions.autoHideMenuBar = true
|
||||
renameWindowOptions.transparent = false
|
||||
}
|
||||
|
||||
const toolboxWindowOptions = {
|
||||
height: 450,
|
||||
width: 800,
|
||||
show: false,
|
||||
frame: true,
|
||||
center: true,
|
||||
fullscreenable: false,
|
||||
resizable: false,
|
||||
title: `PicList ${$t('TOOLBOX')}`,
|
||||
backgroundColor: '#ebeef5',
|
||||
icon: logo,
|
||||
webPreferences: {
|
||||
sandbox: false,
|
||||
backgroundThrottling: true,
|
||||
preload: preloadPath,
|
||||
nodeIntegration: false,
|
||||
contextIsolation: true,
|
||||
nodeIntegrationInWorker: false,
|
||||
webSecurity: false
|
||||
}
|
||||
} as IBrowserWindowOptions
|
||||
|
||||
if (process.platform !== 'darwin') {
|
||||
toolboxWindowOptions.backgroundColor = '#3f3c37'
|
||||
toolboxWindowOptions.autoHideMenuBar = true
|
||||
toolboxWindowOptions.transparent = false
|
||||
}
|
||||
|
||||
windowList.set(IWindowList.TRAY_WINDOW, {
|
||||
isValid: process.platform !== 'linux',
|
||||
multiple: false,
|
||||
options: () => trayWindowOptions,
|
||||
callback (window) {
|
||||
if (!app.isPackaged && process.env.ELECTRON_RENDERER_URL) {
|
||||
window.loadURL(process.env.ELECTRON_RENDERER_URL)
|
||||
} else {
|
||||
window.loadFile(path.join(__dirname, '../renderer/index.html'))
|
||||
}
|
||||
window.on('blur', () => {
|
||||
window.hide()
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
windowList.set(IWindowList.SETTING_WINDOW, {
|
||||
isValid: true,
|
||||
multiple: false,
|
||||
options: () => settingWindowOptions,
|
||||
callback (window, windowManager) {
|
||||
if (!app.isPackaged && process.env.ELECTRON_RENDERER_URL) {
|
||||
window.loadURL(`${process.env.ELECTRON_RENDERER_URL}#main-page/upload`)
|
||||
} else {
|
||||
window.loadFile(path.join(__dirname, '../renderer/index.html'), {
|
||||
hash: 'main-page/upload'
|
||||
})
|
||||
}
|
||||
window.on('closed', () => {
|
||||
bus.emit(TOGGLE_SHORTKEY_MODIFIED_MODE, false)
|
||||
if (process.platform === 'linux') {
|
||||
process.nextTick(() => {
|
||||
app.quit()
|
||||
})
|
||||
}
|
||||
})
|
||||
bus.emit(CREATE_APP_MENU)
|
||||
windowManager.create(IWindowList.MINI_WINDOW)
|
||||
}
|
||||
})
|
||||
|
||||
windowList.set(IWindowList.MINI_WINDOW, {
|
||||
isValid: process.platform !== 'darwin',
|
||||
multiple: false,
|
||||
options: () => miniWindowOptions,
|
||||
callback (window) {
|
||||
if (!app.isPackaged && process.env.ELECTRON_RENDERER_URL) {
|
||||
window.loadURL(`${process.env.ELECTRON_RENDERER_URL}#mini-page`)
|
||||
} else {
|
||||
window.loadFile(path.join(__dirname, '../renderer/index.html'), {
|
||||
hash: 'mini-page'
|
||||
})
|
||||
}
|
||||
setMiniWindowShape(window)
|
||||
}
|
||||
})
|
||||
|
||||
windowList.set(IWindowList.RENAME_WINDOW, {
|
||||
isValid: true,
|
||||
multiple: true,
|
||||
options: () => renameWindowOptions,
|
||||
async callback (window, windowManager) {
|
||||
if (!app.isPackaged && process.env.ELECTRON_RENDERER_URL) {
|
||||
window.loadURL(`${process.env.ELECTRON_RENDERER_URL}#rename-page`)
|
||||
} else {
|
||||
window.loadFile(path.join(__dirname, '../renderer/index.html'), {
|
||||
hash: 'rename-page'
|
||||
})
|
||||
}
|
||||
const currentWindow = windowManager.getAvailableWindow(true)
|
||||
if (currentWindow && currentWindow.isVisible()) {
|
||||
const { x, y, width, height } = currentWindow.getBounds()
|
||||
const positionX = Math.floor(x + width / 2 - 150)
|
||||
const positionY = Math.floor(y + height / 2 - (height > 400 ? 88 : 0))
|
||||
window.setPosition(positionX, positionY, false)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
windowList.set(IWindowList.TOOLBOX_WINDOW, {
|
||||
isValid: true,
|
||||
multiple: false,
|
||||
options: () => toolboxWindowOptions,
|
||||
async callback (window, windowManager) {
|
||||
if (!app.isPackaged && process.env.ELECTRON_RENDERER_URL) {
|
||||
window.loadURL(`${process.env.ELECTRON_RENDERER_URL}#toolbox-page`)
|
||||
} else {
|
||||
window.loadFile(path.join(__dirname, '../renderer/index.html'), {
|
||||
hash: 'toolbox-page'
|
||||
})
|
||||
}
|
||||
const currentWindow = windowManager.getAvailableWindow(true)
|
||||
if (currentWindow && currentWindow.isVisible()) {
|
||||
const { x, y, width, height } = currentWindow.getBounds()
|
||||
const positionX = Math.floor(x + width / 2 - 400)
|
||||
const positionY = Math.floor(y + height / 2 - (height > 400 ? 225 : 0))
|
||||
window.setPosition(positionX, positionY, false)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
export default windowList
|
||||
import path from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
import bus from '@core/bus'
|
||||
import { CREATE_APP_MENU } from '@core/bus/constants'
|
||||
import db from '@core/datastore'
|
||||
import { app, BrowserWindow, Rectangle } from 'electron'
|
||||
|
||||
import type { IWindowListItem } from '#/types/electron'
|
||||
import type { IBrowserWindowOptions } from '#/types/types'
|
||||
import { TOGGLE_SHORTKEY_MODIFIED_MODE } from '~/events/constant'
|
||||
import { T as $t } from '~/i18n'
|
||||
import { configPaths } from '~/utils/configPaths'
|
||||
import { IWindowList } from '~/utils/enum'
|
||||
|
||||
import logo from '../../../../../resources/logo.png?asset&asarUnpack'
|
||||
|
||||
const windowList = new Map<string, IWindowListItem>()
|
||||
|
||||
const getDefaultWindowSizes = (): { width: number; height: number } => {
|
||||
const [mainWindowWidth, mainWindowHeight] = db.get([
|
||||
configPaths.settings.mainWindowWidth,
|
||||
configPaths.settings.mainWindowHeight
|
||||
])
|
||||
return {
|
||||
width: mainWindowWidth || 1200,
|
||||
height: mainWindowHeight || 800
|
||||
}
|
||||
}
|
||||
|
||||
function setMiniWindowShape(win: BrowserWindow) {
|
||||
const radius = 32
|
||||
const shape: Rectangle[] = []
|
||||
|
||||
for (let y = -radius; y <= radius; y++) {
|
||||
for (let x = -radius; x <= radius; x++) {
|
||||
if (x * x + y * y <= radius * radius) {
|
||||
shape.push({ x: radius + x, y: radius + y, width: 1, height: 1 })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
win.setShape(shape)
|
||||
}
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
||||
const preloadPath = fileURLToPath(new URL('../preload/index.mjs', import.meta.url))
|
||||
|
||||
const { width: defaultWindowWidth, height: defaultWindowHeight } = getDefaultWindowSizes()
|
||||
|
||||
const trayWindowOptions = {
|
||||
height: 350,
|
||||
width: 196,
|
||||
show: false,
|
||||
frame: false,
|
||||
fullscreenable: false,
|
||||
resizable: false,
|
||||
transparent: true,
|
||||
vibrancy: 'ultra-dark',
|
||||
webPreferences: {
|
||||
sandbox: false,
|
||||
preload: preloadPath,
|
||||
nodeIntegration: false,
|
||||
contextIsolation: true,
|
||||
nodeIntegrationInWorker: false,
|
||||
backgroundThrottling: true,
|
||||
webSecurity: false
|
||||
}
|
||||
}
|
||||
|
||||
const settingWindowOptions = {
|
||||
height: defaultWindowHeight,
|
||||
width: defaultWindowWidth,
|
||||
show: false,
|
||||
frame: true,
|
||||
center: true,
|
||||
fullscreenable: true,
|
||||
resizable: true,
|
||||
title: 'PicList',
|
||||
transparent: false,
|
||||
backgroundColor: '#ebeef5',
|
||||
titleBarStyle: 'hidden',
|
||||
webPreferences: {
|
||||
sandbox: false,
|
||||
webviewTag: true,
|
||||
backgroundThrottling: true,
|
||||
preload: preloadPath,
|
||||
nodeIntegration: false,
|
||||
contextIsolation: true,
|
||||
nodeIntegrationInWorker: false,
|
||||
webSecurity: false
|
||||
}
|
||||
} as IBrowserWindowOptions
|
||||
|
||||
if (process.platform !== 'darwin') {
|
||||
settingWindowOptions.frame = false
|
||||
settingWindowOptions.icon = logo
|
||||
}
|
||||
|
||||
const miniWindowOptions = {
|
||||
height: 64,
|
||||
width: 64,
|
||||
show: process.platform === 'linux',
|
||||
frame: false,
|
||||
fullscreenable: false,
|
||||
skipTaskbar: true,
|
||||
resizable: false,
|
||||
transparent: process.platform !== 'linux',
|
||||
icon: logo,
|
||||
webPreferences: {
|
||||
sandbox: false,
|
||||
preload: preloadPath,
|
||||
nodeIntegration: false,
|
||||
contextIsolation: true,
|
||||
backgroundThrottling: true,
|
||||
nodeIntegrationInWorker: false
|
||||
}
|
||||
} as IBrowserWindowOptions
|
||||
|
||||
if (db.get(configPaths.settings.miniWindowOntop)) {
|
||||
miniWindowOptions.alwaysOnTop = true
|
||||
}
|
||||
|
||||
const renameWindowOptions = {
|
||||
height: 270,
|
||||
width: 350,
|
||||
show: true,
|
||||
fullscreenable: false,
|
||||
icon: logo,
|
||||
resizable: true,
|
||||
webPreferences: {
|
||||
sandbox: false,
|
||||
preload: preloadPath,
|
||||
nodeIntegration: false,
|
||||
contextIsolation: true,
|
||||
nodeIntegrationInWorker: false,
|
||||
backgroundThrottling: false
|
||||
}
|
||||
} as IBrowserWindowOptions
|
||||
|
||||
if (process.platform !== 'darwin') {
|
||||
renameWindowOptions.show = true
|
||||
renameWindowOptions.backgroundColor = '#3f3c37'
|
||||
renameWindowOptions.autoHideMenuBar = true
|
||||
renameWindowOptions.transparent = false
|
||||
}
|
||||
|
||||
const toolboxWindowOptions = {
|
||||
height: 450,
|
||||
width: 800,
|
||||
show: false,
|
||||
frame: true,
|
||||
center: true,
|
||||
fullscreenable: false,
|
||||
resizable: false,
|
||||
title: `PicList ${$t('TOOLBOX')}`,
|
||||
backgroundColor: '#ebeef5',
|
||||
icon: logo,
|
||||
webPreferences: {
|
||||
sandbox: false,
|
||||
backgroundThrottling: true,
|
||||
preload: preloadPath,
|
||||
nodeIntegration: false,
|
||||
contextIsolation: true,
|
||||
nodeIntegrationInWorker: false,
|
||||
webSecurity: false
|
||||
}
|
||||
} as IBrowserWindowOptions
|
||||
|
||||
if (process.platform !== 'darwin') {
|
||||
toolboxWindowOptions.backgroundColor = '#3f3c37'
|
||||
toolboxWindowOptions.autoHideMenuBar = true
|
||||
toolboxWindowOptions.transparent = false
|
||||
}
|
||||
|
||||
windowList.set(IWindowList.TRAY_WINDOW, {
|
||||
isValid: process.platform !== 'linux',
|
||||
multiple: false,
|
||||
options: () => trayWindowOptions,
|
||||
callback(window) {
|
||||
if (!app.isPackaged && process.env.ELECTRON_RENDERER_URL) {
|
||||
window.loadURL(process.env.ELECTRON_RENDERER_URL)
|
||||
} else {
|
||||
window.loadFile(path.join(__dirname, '../renderer/index.html'))
|
||||
}
|
||||
window.on('blur', () => {
|
||||
window.hide()
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
windowList.set(IWindowList.SETTING_WINDOW, {
|
||||
isValid: true,
|
||||
multiple: false,
|
||||
options: () => settingWindowOptions,
|
||||
callback(window, windowManager) {
|
||||
if (!app.isPackaged && process.env.ELECTRON_RENDERER_URL) {
|
||||
window.loadURL(`${process.env.ELECTRON_RENDERER_URL}#main-page/upload`)
|
||||
} else {
|
||||
window.loadFile(path.join(__dirname, '../renderer/index.html'), {
|
||||
hash: 'main-page/upload'
|
||||
})
|
||||
}
|
||||
window.on('closed', () => {
|
||||
bus.emit(TOGGLE_SHORTKEY_MODIFIED_MODE, false)
|
||||
if (process.platform === 'linux') {
|
||||
process.nextTick(() => {
|
||||
app.quit()
|
||||
})
|
||||
}
|
||||
})
|
||||
bus.emit(CREATE_APP_MENU)
|
||||
windowManager.create(IWindowList.MINI_WINDOW)
|
||||
}
|
||||
})
|
||||
|
||||
windowList.set(IWindowList.MINI_WINDOW, {
|
||||
isValid: process.platform !== 'darwin',
|
||||
multiple: false,
|
||||
options: () => miniWindowOptions,
|
||||
callback(window) {
|
||||
if (!app.isPackaged && process.env.ELECTRON_RENDERER_URL) {
|
||||
window.loadURL(`${process.env.ELECTRON_RENDERER_URL}#mini-page`)
|
||||
} else {
|
||||
window.loadFile(path.join(__dirname, '../renderer/index.html'), {
|
||||
hash: 'mini-page'
|
||||
})
|
||||
}
|
||||
setMiniWindowShape(window)
|
||||
}
|
||||
})
|
||||
|
||||
windowList.set(IWindowList.RENAME_WINDOW, {
|
||||
isValid: true,
|
||||
multiple: true,
|
||||
options: () => renameWindowOptions,
|
||||
async callback(window, windowManager) {
|
||||
if (!app.isPackaged && process.env.ELECTRON_RENDERER_URL) {
|
||||
window.loadURL(`${process.env.ELECTRON_RENDERER_URL}#rename-page`)
|
||||
} else {
|
||||
window.loadFile(path.join(__dirname, '../renderer/index.html'), {
|
||||
hash: 'rename-page'
|
||||
})
|
||||
}
|
||||
const currentWindow = windowManager.getAvailableWindow(true)
|
||||
if (currentWindow && currentWindow.isVisible()) {
|
||||
const { x, y, width, height } = currentWindow.getBounds()
|
||||
const positionX = Math.floor(x + width / 2 - 150)
|
||||
const positionY = Math.floor(y + height / 2 - (height > 400 ? 88 : 0))
|
||||
window.setPosition(positionX, positionY, false)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
windowList.set(IWindowList.TOOLBOX_WINDOW, {
|
||||
isValid: true,
|
||||
multiple: false,
|
||||
options: () => toolboxWindowOptions,
|
||||
async callback(window, windowManager) {
|
||||
if (!app.isPackaged && process.env.ELECTRON_RENDERER_URL) {
|
||||
window.loadURL(`${process.env.ELECTRON_RENDERER_URL}#toolbox-page`)
|
||||
} else {
|
||||
window.loadFile(path.join(__dirname, '../renderer/index.html'), {
|
||||
hash: 'toolbox-page'
|
||||
})
|
||||
}
|
||||
const currentWindow = windowManager.getAvailableWindow(true)
|
||||
if (currentWindow && currentWindow.isVisible()) {
|
||||
const { x, y, width, height } = currentWindow.getBounds()
|
||||
const positionX = Math.floor(x + width / 2 - 400)
|
||||
const positionY = Math.floor(y + height / 2 - (height > 400 ? 225 : 0))
|
||||
window.setPosition(positionX, positionY, false)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
export default windowList
|
||||
|
||||
@@ -5,10 +5,10 @@ import type { IWindowListItem, IWindowManager } from '#/types/electron'
|
||||
import { IWindowList } from '~/utils/enum'
|
||||
|
||||
class WindowManager implements IWindowManager {
|
||||
#windowMap: Map< string, BrowserWindow> = new Map()
|
||||
#windowMap: Map<string, BrowserWindow> = new Map()
|
||||
#windowIdMap: Map<number, string> = new Map()
|
||||
|
||||
create (name: string) {
|
||||
create(name: string) {
|
||||
const windowConfig: IWindowListItem = windowList.get(name)!
|
||||
if (!windowConfig.isValid) return null
|
||||
|
||||
@@ -30,14 +30,14 @@ class WindowManager implements IWindowManager {
|
||||
return window
|
||||
}
|
||||
|
||||
get (name: string) {
|
||||
get(name: string) {
|
||||
if (this.has(name)) {
|
||||
return this.#windowMap.get(name)!
|
||||
}
|
||||
return this.create(name)
|
||||
}
|
||||
|
||||
has (name: string) {
|
||||
has(name: string) {
|
||||
return this.#windowMap.has(name)
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ class WindowManager implements IWindowManager {
|
||||
}
|
||||
}
|
||||
|
||||
getAvailableWindow (isSkipMiniWindow = false) {
|
||||
getAvailableWindow(isSkipMiniWindow = false) {
|
||||
const miniWindow = this.#windowMap.get(IWindowList.MINI_WINDOW)
|
||||
if (miniWindow && miniWindow.isVisible() && !isSkipMiniWindow) {
|
||||
return miniWindow
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
import { EventEmitter } from 'node:events'
|
||||
|
||||
class OptimizedBus extends EventEmitter {
|
||||
constructor () {
|
||||
super()
|
||||
this.setMaxListeners(50)
|
||||
}
|
||||
|
||||
once (event: string | symbol, listener: (...args: any[]) => void): this {
|
||||
const wrappedListener = (...args: any[]) => {
|
||||
try {
|
||||
listener(...args)
|
||||
} finally {
|
||||
this.removeListener(event, wrappedListener)
|
||||
}
|
||||
}
|
||||
return super.once(event, wrappedListener)
|
||||
}
|
||||
|
||||
cleanupListeners () {
|
||||
const events = this.eventNames()
|
||||
events.forEach(event => {
|
||||
const listenerCount = this.listenerCount(event)
|
||||
console.log(` listener count (${listenerCount}) for event: ${String(event)}`)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const bus = new OptimizedBus()
|
||||
|
||||
export default bus
|
||||
import { EventEmitter } from 'node:events'
|
||||
|
||||
class OptimizedBus extends EventEmitter {
|
||||
constructor() {
|
||||
super()
|
||||
this.setMaxListeners(50)
|
||||
}
|
||||
|
||||
once(event: string | symbol, listener: (...args: any[]) => void): this {
|
||||
const wrappedListener = (...args: any[]) => {
|
||||
try {
|
||||
listener(...args)
|
||||
} finally {
|
||||
this.removeListener(event, wrappedListener)
|
||||
}
|
||||
}
|
||||
return super.once(event, wrappedListener)
|
||||
}
|
||||
|
||||
cleanupListeners() {
|
||||
const events = this.eventNames()
|
||||
events.forEach(event => {
|
||||
const listenerCount = this.listenerCount(event)
|
||||
console.log(` listener count (${listenerCount}) for event: ${String(event)}`)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const bus = new OptimizedBus()
|
||||
|
||||
export default bus
|
||||
|
||||
@@ -23,7 +23,7 @@ const errorMsg = {
|
||||
brokenButBackup: $t('TIPS_PICGO_CONFIG_FILE_BROKEN_WITH_BACKUP')
|
||||
}
|
||||
|
||||
function dbChecker () {
|
||||
function dbChecker() {
|
||||
if (process.type !== 'renderer') {
|
||||
// db save bak
|
||||
try {
|
||||
@@ -80,7 +80,7 @@ function dbChecker () {
|
||||
/**
|
||||
* Get config path
|
||||
*/
|
||||
function dbPathChecker (): string {
|
||||
function dbPathChecker(): string {
|
||||
if (_configFilePath) {
|
||||
return _configFilePath
|
||||
}
|
||||
@@ -120,11 +120,11 @@ function dbPathChecker (): string {
|
||||
}
|
||||
}
|
||||
|
||||
function dbPathDir () {
|
||||
function dbPathDir() {
|
||||
return path.dirname(dbPathChecker())
|
||||
}
|
||||
|
||||
function getGalleryDBPath (): {
|
||||
function getGalleryDBPath(): {
|
||||
dbPath: string
|
||||
dbBackupPath: string
|
||||
} {
|
||||
|
||||
@@ -19,7 +19,7 @@ export const DB_PATH: string = getGalleryDBPath().dbPath
|
||||
class ConfigStore {
|
||||
#db: JSONStore
|
||||
|
||||
constructor () {
|
||||
constructor() {
|
||||
this.#db = new JSONStore(CONFIG_PATH)
|
||||
|
||||
if (!this.#db.has('picBed')) {
|
||||
@@ -43,11 +43,11 @@ class ConfigStore {
|
||||
this.read()
|
||||
}
|
||||
|
||||
read (flush?: boolean): IJSON {
|
||||
read(flush?: boolean): IJSON {
|
||||
return this.#db.read(flush)
|
||||
}
|
||||
|
||||
getSingle (key = ''): any {
|
||||
getSingle(key = ''): any {
|
||||
if (key === '') {
|
||||
return this.#db.read(true)
|
||||
}
|
||||
@@ -55,43 +55,43 @@ class ConfigStore {
|
||||
return this.#db.get(key)
|
||||
}
|
||||
|
||||
get (key: string): any
|
||||
get (key: string[]): any[]
|
||||
get (key: string | string[] = ''): any {
|
||||
get(key: string): any
|
||||
get(key: string[]): any[]
|
||||
get(key: string | string[] = ''): any {
|
||||
if (Array.isArray(key)) {
|
||||
return key.map(k => this.getSingle(k))
|
||||
}
|
||||
return this.getSingle(key)
|
||||
}
|
||||
|
||||
set (key: string, value: any): void {
|
||||
set(key: string, value: any): void {
|
||||
this.read(true)
|
||||
return this.#db.set(key, value)
|
||||
}
|
||||
|
||||
has (key: string) {
|
||||
has(key: string) {
|
||||
this.read(true)
|
||||
return this.#db.has(key)
|
||||
}
|
||||
|
||||
unset (key: string, value: any): boolean {
|
||||
unset(key: string, value: any): boolean {
|
||||
this.read(true)
|
||||
return this.#db.unset(key, value)
|
||||
}
|
||||
|
||||
saveConfig (config: Partial<IConfig>): void {
|
||||
saveConfig(config: Partial<IConfig>): void {
|
||||
Object.keys(config).forEach((name: string) => {
|
||||
this.set(name, config[name])
|
||||
})
|
||||
}
|
||||
|
||||
removeConfig (config: IConfig): void {
|
||||
removeConfig(config: IConfig): void {
|
||||
Object.keys(config).forEach((name: string) => {
|
||||
this.unset(name, config[name])
|
||||
})
|
||||
}
|
||||
|
||||
getConfigPath () {
|
||||
getConfigPath() {
|
||||
return CONFIG_PATH
|
||||
}
|
||||
}
|
||||
@@ -103,11 +103,11 @@ export default db
|
||||
// v2.3.0 add gallery db
|
||||
class GalleryDB {
|
||||
static #instance: DBStore
|
||||
private constructor () {
|
||||
private constructor() {
|
||||
console.log('init gallery db')
|
||||
}
|
||||
|
||||
static getInstance (): DBStore {
|
||||
static getInstance(): DBStore {
|
||||
if (!GalleryDB.#instance) {
|
||||
GalleryDB.#instance = new DBStore(DB_PATH, 'gallery')
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ picgo.GUI_VERSION = pkg.version
|
||||
|
||||
const originPicGoSaveConfig = picgo.saveConfig.bind(picgo)
|
||||
|
||||
function flushDB () {
|
||||
function flushDB() {
|
||||
db.read(true)
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ interface IConfigMap {
|
||||
}
|
||||
|
||||
export default class AlistApi {
|
||||
static async delete (configMap: IConfigMap): Promise<boolean> {
|
||||
static async delete(configMap: IConfigMap): Promise<boolean> {
|
||||
const { fileName, config } = configMap
|
||||
try {
|
||||
const { version, url, uploadPath, token } = config
|
||||
|
||||
@@ -26,7 +26,7 @@ const getAListToken = async (url: string, username: string, password: string) =>
|
||||
}
|
||||
|
||||
export default class AListplistApi {
|
||||
static async delete (configMap: IConfigMap): Promise<boolean> {
|
||||
static async delete(configMap: IConfigMap): Promise<boolean> {
|
||||
const { fileName, config } = configMap
|
||||
try {
|
||||
const { url, username, password, uploadPath } = config
|
||||
|
||||
@@ -9,11 +9,11 @@ interface IConfigMap {
|
||||
}
|
||||
|
||||
export default class AliyunApi {
|
||||
static #getKey (fileName: string, path?: string): string {
|
||||
static #getKey(fileName: string, path?: string): string {
|
||||
return path && path !== '/' ? `${path.replace(/^\/+|\/+$/, '')}/${fileName}` : fileName
|
||||
}
|
||||
|
||||
static async delete (configMap: IConfigMap): Promise<boolean> {
|
||||
static async delete(configMap: IConfigMap): Promise<boolean> {
|
||||
const { fileName, config } = configMap
|
||||
try {
|
||||
const client = new OSS({ ...config, region: config.area })
|
||||
|
||||
@@ -39,7 +39,7 @@ const apiMap: IStringKeyMap = {
|
||||
}
|
||||
|
||||
export default class ALLApi {
|
||||
static async delete (configMap: IStringKeyMap): Promise<boolean> {
|
||||
static async delete(configMap: IStringKeyMap): Promise<boolean> {
|
||||
const api = apiMap[configMap.type]
|
||||
return api ? await api.delete(configMap) : false
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import { removeFileFromS3InMain } from '~/utils/deleteFunc'
|
||||
import { deleteFailedLog } from '~/utils/deleteLog'
|
||||
|
||||
export default class AwsS3Api {
|
||||
static async delete (configMap: IStringKeyMap): Promise<boolean> {
|
||||
static async delete(configMap: IStringKeyMap): Promise<boolean> {
|
||||
try {
|
||||
return await removeFileFromS3InMain(getRawData(configMap))
|
||||
} catch (error: any) {
|
||||
|
||||
@@ -4,7 +4,7 @@ import { removeFileFromDogeInMain } from '~/utils/deleteFunc'
|
||||
import { deleteFailedLog } from '~/utils/deleteLog'
|
||||
|
||||
export default class AwsS3Api {
|
||||
static async delete (configMap: IStringKeyMap): Promise<boolean> {
|
||||
static async delete(configMap: IStringKeyMap): Promise<boolean> {
|
||||
try {
|
||||
return await removeFileFromDogeInMain(getRawData(configMap))
|
||||
} catch (error: any) {
|
||||
|
||||
@@ -10,18 +10,18 @@ interface IConfigMap {
|
||||
}
|
||||
|
||||
export default class GithubApi {
|
||||
static #createOctokit (token: string) {
|
||||
static #createOctokit(token: string) {
|
||||
return new Octokit({
|
||||
auth: token
|
||||
})
|
||||
}
|
||||
|
||||
static #createKey (path: string | undefined, fileName: string): string {
|
||||
static #createKey(path: string | undefined, fileName: string): string {
|
||||
const formatedFileName = fileName.replace(/%2F/g, '/')
|
||||
return path && path !== '/' ? `${path.replace(/^\/+|\/+$/, '')}/${formatedFileName}` : formatedFileName
|
||||
}
|
||||
|
||||
static async delete (configMap: IConfigMap): Promise<boolean> {
|
||||
static async delete(configMap: IConfigMap): Promise<boolean> {
|
||||
const {
|
||||
fileName,
|
||||
hash,
|
||||
|
||||
@@ -4,7 +4,7 @@ import { removeFileFromHuaweiInMain } from '~/utils/deleteFunc'
|
||||
import { deleteFailedLog } from '~/utils/deleteLog'
|
||||
|
||||
export default class HuaweicloudApi {
|
||||
static async delete (configMap: IStringKeyMap): Promise<boolean> {
|
||||
static async delete(configMap: IStringKeyMap): Promise<boolean> {
|
||||
try {
|
||||
return await removeFileFromHuaweiInMain(getRawData(configMap))
|
||||
} catch (error: any) {
|
||||
|
||||
@@ -11,7 +11,7 @@ interface IConfigMap {
|
||||
export default class ImgurApi {
|
||||
static #baseUrl = 'https://api.imgur.com/3'
|
||||
|
||||
static async delete (configMap: IConfigMap): Promise<boolean> {
|
||||
static async delete(configMap: IConfigMap): Promise<boolean> {
|
||||
const { config: { clientId = '', username = '', accessToken = '' } = {}, hash = '' } = configMap
|
||||
let Authorization: string, apiUrl: string
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ interface IConfigMap {
|
||||
}
|
||||
|
||||
export default class LocalApi {
|
||||
static async delete (configMap: IConfigMap): Promise<boolean> {
|
||||
static async delete(configMap: IConfigMap): Promise<boolean> {
|
||||
const { hash } = configMap
|
||||
if (!hash) {
|
||||
deleteLog(hash, 'Local', false, 'Local.delete: invalid params')
|
||||
|
||||
@@ -6,7 +6,7 @@ import type { IStringKeyMap } from '#/types/types'
|
||||
import { deleteFailedLog, deleteLog } from '~/utils/deleteLog'
|
||||
|
||||
export default class LskyplistApi {
|
||||
static async delete (configMap: IStringKeyMap): Promise<boolean> {
|
||||
static async delete(configMap: IStringKeyMap): Promise<boolean> {
|
||||
const { hash, config } = configMap
|
||||
if (!hash || !config || !config.token) {
|
||||
deleteLog(hash, 'Lskyplist', false, 'LskyplistApi.delete: invalid params')
|
||||
|
||||
@@ -4,7 +4,7 @@ import type { IStringKeyMap } from '#/types/types'
|
||||
import { deleteFailedLog, deleteLog } from '~/utils/deleteLog'
|
||||
|
||||
export default class PiclistApi {
|
||||
static async delete (configMap: IStringKeyMap): Promise<boolean> {
|
||||
static async delete(configMap: IStringKeyMap): Promise<boolean> {
|
||||
const { config, fullResult } = configMap
|
||||
const { host, port } = config
|
||||
if (!fullResult) return true
|
||||
|
||||
@@ -8,7 +8,7 @@ interface IConfigMap {
|
||||
}
|
||||
|
||||
export default class QiniuApi {
|
||||
static async delete (configMap: IConfigMap): Promise<boolean> {
|
||||
static async delete(configMap: IConfigMap): Promise<boolean> {
|
||||
const {
|
||||
fileName,
|
||||
config: { accessKey, secretKey, bucket, path }
|
||||
|
||||
@@ -4,7 +4,7 @@ import { removeFileFromSFTPInMain } from '~/utils/deleteFunc'
|
||||
import { deleteFailedLog } from '~/utils/deleteLog'
|
||||
|
||||
export default class SftpPlistApi {
|
||||
static async delete (configMap: IStringKeyMap): Promise<boolean> {
|
||||
static async delete(configMap: IStringKeyMap): Promise<boolean> {
|
||||
const { fileName, config } = configMap
|
||||
try {
|
||||
return await removeFileFromSFTPInMain(getRawData(config), fileName)
|
||||
|
||||
@@ -11,7 +11,7 @@ interface IConfigMap {
|
||||
export default class SmmsApi {
|
||||
static readonly #baseUrl = 'https://smms.app/api/v2'
|
||||
|
||||
static async delete (configMap: IConfigMap): Promise<boolean> {
|
||||
static async delete(configMap: IConfigMap): Promise<boolean> {
|
||||
const { hash, config } = configMap
|
||||
if (!hash || !config || !config.token) {
|
||||
deleteLog(hash, 'Smms', false, 'SmmsApi.delete: invalid params')
|
||||
|
||||
@@ -7,14 +7,14 @@ interface IConfigMap {
|
||||
config: PartialKeys<ITcYunConfig, 'path'>
|
||||
}
|
||||
export default class TcyunApi {
|
||||
static #createCOS (SecretId: string, SecretKey: string): COS {
|
||||
static #createCOS(SecretId: string, SecretKey: string): COS {
|
||||
return new COS({
|
||||
SecretId,
|
||||
SecretKey
|
||||
})
|
||||
}
|
||||
|
||||
static async delete (configMap: IConfigMap): Promise<boolean> {
|
||||
static async delete(configMap: IConfigMap): Promise<boolean> {
|
||||
const {
|
||||
fileName,
|
||||
config: { secretId, secretKey, bucket, area, path }
|
||||
|
||||
@@ -9,7 +9,7 @@ interface IConfigMap {
|
||||
}
|
||||
|
||||
export default class UpyunApi {
|
||||
static async delete (configMap: IConfigMap): Promise<boolean> {
|
||||
static async delete(configMap: IConfigMap): Promise<boolean> {
|
||||
const {
|
||||
fileName,
|
||||
config: { bucket, operator, password, path }
|
||||
|
||||
@@ -10,7 +10,7 @@ interface IConfigMap {
|
||||
}
|
||||
|
||||
export default class WebdavApi {
|
||||
static async delete (configMap: IConfigMap): Promise<boolean> {
|
||||
static async delete(configMap: IConfigMap): Promise<boolean> {
|
||||
const {
|
||||
fileName,
|
||||
config: { host, username, password, path, sslEnabled, authType }
|
||||
|
||||
@@ -8,7 +8,16 @@ import { BrowserWindow, dialog, ipcMain, IpcMainEvent, MessageBoxOptions, Notifi
|
||||
import fs from 'fs-extra'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
|
||||
import type { IGuiApi, ImgInfo, IShowFileExplorerOption, IShowInputBoxOption, IShowMessageBoxOption, IShowMessageBoxResult, IShowNotificationOption, IUploadOption } from '#/types/types'
|
||||
import type {
|
||||
IGuiApi,
|
||||
ImgInfo,
|
||||
IShowFileExplorerOption,
|
||||
IShowInputBoxOption,
|
||||
IShowMessageBoxOption,
|
||||
IShowMessageBoxResult,
|
||||
IShowNotificationOption,
|
||||
IUploadOption
|
||||
} from '#/types/types'
|
||||
import { SHOW_INPUT_BOX } from '~/events/constant'
|
||||
import { T as $t } from '~/i18n'
|
||||
import { handleCopyUrl } from '~/utils/common'
|
||||
@@ -21,18 +30,18 @@ class GuiApi implements IGuiApi {
|
||||
private static instance: GuiApi
|
||||
private windowId: number = -1
|
||||
private settingWindowId: number = -1
|
||||
private constructor () {
|
||||
private constructor() {
|
||||
console.log('init guiapi')
|
||||
}
|
||||
|
||||
static getInstance (): GuiApi {
|
||||
static getInstance(): GuiApi {
|
||||
if (!GuiApi.instance) {
|
||||
GuiApi.instance = new GuiApi()
|
||||
}
|
||||
return GuiApi.instance
|
||||
}
|
||||
|
||||
private async showSettingWindow () {
|
||||
private async showSettingWindow() {
|
||||
this.settingWindowId = await getSettingWindowId()
|
||||
const settingWindow = BrowserWindow.fromId(this.settingWindowId)
|
||||
if (settingWindow?.isVisible()) {
|
||||
@@ -46,11 +55,11 @@ class GuiApi implements IGuiApi {
|
||||
})
|
||||
}
|
||||
|
||||
private getWebcontentsByWindowId (id: number) {
|
||||
private getWebcontentsByWindowId(id: number) {
|
||||
return BrowserWindow.fromId(id)?.webContents
|
||||
}
|
||||
|
||||
async showInputBox (
|
||||
async showInputBox(
|
||||
options: IShowInputBoxOption = {
|
||||
title: '',
|
||||
placeholder: ''
|
||||
@@ -65,13 +74,13 @@ class GuiApi implements IGuiApi {
|
||||
})
|
||||
}
|
||||
|
||||
async showFileExplorer (options: IShowFileExplorerOption = {}) {
|
||||
async showFileExplorer(options: IShowFileExplorerOption = {}) {
|
||||
this.windowId = await getWindowId()
|
||||
const res = await dialog.showOpenDialog(BrowserWindow.fromId(this.windowId)!, options)
|
||||
return res.filePaths || []
|
||||
}
|
||||
|
||||
async upload (input: IUploadOption) {
|
||||
async upload(input: IUploadOption) {
|
||||
this.windowId = await getWindowId()
|
||||
const webContents = this.getWebcontentsByWindowId(this.windowId)
|
||||
const rawInput = cloneDeep(input)
|
||||
@@ -122,7 +131,7 @@ class GuiApi implements IGuiApi {
|
||||
return []
|
||||
}
|
||||
|
||||
showNotification (
|
||||
showNotification(
|
||||
options: IShowNotificationOption = {
|
||||
title: '',
|
||||
body: ''
|
||||
@@ -135,7 +144,7 @@ class GuiApi implements IGuiApi {
|
||||
notification.show()
|
||||
}
|
||||
|
||||
showMessageBox (
|
||||
showMessageBox(
|
||||
options: IShowMessageBoxOption = {
|
||||
title: '',
|
||||
message: '',
|
||||
@@ -159,7 +168,7 @@ class GuiApi implements IGuiApi {
|
||||
/**
|
||||
* get picgo config/data path
|
||||
*/
|
||||
async getConfigPath () {
|
||||
async getConfigPath() {
|
||||
const currentConfigPath = dbPathChecker()
|
||||
const galleryDBPath = getGalleryDBPath().dbPath
|
||||
return {
|
||||
@@ -169,12 +178,12 @@ class GuiApi implements IGuiApi {
|
||||
}
|
||||
}
|
||||
|
||||
get galleryDB (): DBStore {
|
||||
get galleryDB(): DBStore {
|
||||
return new Proxy<DBStore>(GalleryDB.getInstance(), {
|
||||
get (target, prop: keyof DBStore) {
|
||||
get(target, prop: keyof DBStore) {
|
||||
if (prop === 'overwrite') {
|
||||
return new Proxy(GalleryDB.getInstance().overwrite, {
|
||||
apply (target, ctx, args) {
|
||||
apply(target, ctx, args) {
|
||||
return new Promise(resolve => {
|
||||
const guiApi = GuiApi.getInstance()
|
||||
guiApi
|
||||
@@ -197,7 +206,7 @@ class GuiApi implements IGuiApi {
|
||||
}
|
||||
if (prop === 'removeById') {
|
||||
return new Proxy(GalleryDB.getInstance().removeById, {
|
||||
apply (target, ctx, args) {
|
||||
apply(target, ctx, args) {
|
||||
return new Promise(resolve => {
|
||||
const guiApi = GuiApi.getInstance()
|
||||
guiApi
|
||||
|
||||
Reference in New Issue
Block a user