🚧 WIP(custom): v3.0.0 migrate to vite and esm

This commit is contained in:
Kuingsmile
2025-07-31 17:37:30 +08:00
parent cd76bc7c10
commit 054f4b4cff
597 changed files with 197292 additions and 13329 deletions

View File

@@ -1,12 +1,14 @@
import path from 'node:path'
import windowManager from 'apis/app/window/windowManager'
import axios from 'axios'
import { app, clipboard, dialog, shell } from 'electron'
import fs from 'fs-extra'
import path from 'path'
import { gte, lte } from 'semver'
import windowManager from 'apis/app/window/windowManager'
import { showNotification } from '~/utils/common'
import { IRemoteNoticeActionType, IRemoteNoticeTriggerCount, IRemoteNoticeTriggerHook } from '#/types/enum'
import { IRemoteNotice, IRemoteNoticeAction, IRemoteNoticeLocalCountStorage } from '#/types/types'
import { showNotification } from '~/utils/common'
// for test
const REMOTE_NOTICE_URL = 'https://release.piclist.cn/remote-notice.json'
@@ -21,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({}))
@@ -42,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',
@@ -66,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
@@ -100,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) {
@@ -115,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)
}
@@ -161,7 +163,7 @@ class RemoteNoticeHandler {
}
}
triggerHook(hook: IRemoteNoticeTriggerHook) {
triggerHook (hook: IRemoteNoticeTriggerHook) {
if (!this.remoteNotice || !this.remoteNotice.list) {
return
}

View File

@@ -1,30 +1,29 @@
import { globalShortcut } from 'electron'
import shortKeyService from 'apis/app/shortKey/shortKeyService'
import GuiApi from 'apis/gui'
import bus from '@core/bus'
import db from '@core/datastore'
import logger from '@core/picgo/logger'
import picgo from '@core/picgo'
import logger from '@core/picgo/logger'
import shortKeyService from 'apis/app/shortKey/shortKeyService'
import GuiApi from 'apis/gui'
import { globalShortcut } from 'electron'
import { TOGGLE_SHORTKEY_MODIFIED_MODE } from '#/events/constants'
import { IKeyCommandType, IPluginShortKeyConfig, IShortKeyConfig, IShortKeyConfigs, IShortKeyHandler } from '#/types/types'
import { configPaths } from '#/utils/configPaths'
class ShortKeyHandler {
private isInModifiedMode: boolean = false
constructor() {
constructor () {
bus.on(TOGGLE_SHORTKEY_MODIFIED_MODE, flag => {
this.isInModifiedMode = flag
})
}
init() {
async init () {
this.initBuiltInShortKey()
this.initPluginsShortKey()
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:'))
@@ -39,11 +38,11 @@ class ShortKeyHandler {
})
}
private initPluginsShortKey() {
private async initPluginsShortKey () {
// get enabled plugin
const pluginList = picgo.pluginLoader.getList()
for (const item of pluginList) {
const plugin = picgo.pluginLoader.getPlugin(item)
const plugin = await picgo.pluginLoader.getPlugin(item)
// if a plugin has commands
if (plugin && plugin.commands) {
if (typeof plugin.commands !== 'function') {
@@ -69,7 +68,7 @@ class ShortKeyHandler {
}
}
private registerShortKey(
private registerShortKey (
config: IShortKeyConfig | IPluginShortKeyConfig,
command: string,
handler: IShortKeyHandler,
@@ -98,7 +97,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)
@@ -122,7 +121,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)
@@ -135,7 +134,7 @@ class ShortKeyHandler {
return true
}
private async handler(command: string) {
private async handler (command: string) {
if (this.isInModifiedMode) {
return
}
@@ -151,8 +150,8 @@ class ShortKeyHandler {
}
}
registerPluginShortKey(pluginName: string) {
const plugin = picgo.pluginLoader.getPlugin(pluginName)
async registerPluginShortKey (pluginName: string) {
const plugin = await picgo.pluginLoader.getPlugin(pluginName)
if (plugin && plugin.commands) {
if (typeof plugin.commands !== 'function') {
logger.warn(`${pluginName}'s commands is not a function`)
@@ -171,7 +170,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))

View File

@@ -1,23 +1,25 @@
import logger from '@core/picgo/logger'
import { 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()]
}
}

View File

@@ -1,3 +1,8 @@
import db, { GalleryDB } from '@core/datastore'
import picgo from '@core/picgo'
import uploader from 'apis/app/uploader'
import { handleSecondaryUpload, uploadClipboardFiles } from 'apis/app/uploader/apis'
import windowManager from 'apis/app/window/windowManager'
import {
app,
clipboard,
@@ -10,31 +15,23 @@ import {
Tray
} from 'electron'
import fs from 'fs-extra'
import { cloneDeep } from 'lodash'
import db, { GalleryDB } from '@core/datastore'
import picgo from '@core/picgo'
import uploader from 'apis/app/uploader'
import { handleSecondaryUpload, uploadClipboardFiles } from 'apis/app/uploader/apis'
import windowManager from 'apis/app/window/windowManager'
import { cloneDeep } from 'lodash-es'
import pkg from 'root/package.json'
import { IPasteStyle, IWindowList } from '#/types/enum'
import { IBounds, ImgInfo } from '#/types/types'
import { configPaths } from '#/utils/configPaths'
import { buildPicBedListMenu } from '~/events/remotes/menu'
import { T } from '~/i18n'
import clipboardPoll from '~/utils/clipboardPoll'
import { ensureFilePath, handleCopyUrl, setTray, tray } from '~/utils/common'
import { isMacOSVersionGreaterThanOrEqualTo } from '~/utils/getMacOSVersion'
import pasteTemplate from '~/utils/pasteTemplate'
import { configPaths } from '#/utils/configPaths'
import { IPasteStyle, IWindowList } from '#/types/enum'
import pkg from 'root/package.json'
import { hideMiniWindow, openMainWindow, openMiniWindow } from '~/utils/windowHelper'
let contextMenu: Menu | null
export function setDockMenu() {
export function setDockMenu () {
const isListeningClipboard = db.get(configPaths.settings.isListeningClipboard) || false
const dockMenu = Menu.buildFromTemplate([
{
@@ -43,7 +40,7 @@ export function setDockMenu() {
},
{
label: T('START_WATCH_CLIPBOARD'),
click() {
click () {
db.set(configPaths.settings.isListeningClipboard, true)
clipboardPoll.startListening()
clipboardPoll.on('change', () => {
@@ -56,7 +53,7 @@ export function setDockMenu() {
},
{
label: T('STOP_WATCH_CLIPBOARD'),
click() {
click () {
db.set(configPaths.settings.isListeningClipboard, false)
clipboardPoll.stopListening()
clipboardPoll.removeAllListeners()
@@ -65,10 +62,10 @@ export function setDockMenu() {
visible: isListeningClipboard
}
])
app.dock.setMenu(dockMenu)
app.dock?.setMenu(dockMenu)
}
export function createMenu() {
export function createMenu () {
const submenu = buildPicBedListMenu()
const appMenu = Menu.buildFromTemplate([
{
@@ -77,7 +74,7 @@ export function createMenu() {
{ label: T('OPEN_MAIN_WINDOW'), click: openMainWindow },
{
label: T('RELOAD_APP'),
click() {
click () {
app.relaunch()
app.exit(0)
}
@@ -105,7 +102,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 =
@@ -130,7 +127,7 @@ export function createContextMenu() {
if (process.platform === 'darwin' || process.platform === 'win32') {
const submenu = buildPicBedListMenu()
const template: Array<MenuItemConstructorOptions | MenuItem> = [
const template: (MenuItemConstructorOptions | MenuItem)[] = [
{ label: T('OPEN_MAIN_WINDOW'), click: openMainWindow },
{ label: T('CHOOSE_DEFAULT_PICBED'), type: 'submenu', submenu },
{
@@ -145,7 +142,7 @@ export function createContextMenu() {
},
{
label: T('RELOAD_APP'),
click() {
click () {
app.relaunch()
app.exit(0)
}
@@ -158,7 +155,7 @@ export function createContextMenu() {
0,
{
label: T('OPEN_MINI_WINDOW'),
click() {
click () {
openMiniWindow(false)
},
visible: !isMiniWindowVisible
@@ -183,7 +180,7 @@ export function createContextMenu() {
{ label: T('OPEN_MAIN_WINDOW'), click: openMainWindow },
{
label: T('OPEN_MINI_WINDOW'),
click() {
click () {
openMiniWindow(false)
},
visible: !isMiniWindowVisible
@@ -205,7 +202,7 @@ export function createContextMenu() {
},
{
label: T('ABOUT'),
click() {
click () {
dialog.showMessageBox({
title: 'PicList',
message: 'PicList',
@@ -222,13 +219,13 @@ export function createContextMenu() {
const getTrayIcon = () => {
if (process.platform === 'darwin') {
const isMacOSGreaterThan11 = isMacOSVersionGreaterThanOrEqualTo('11')
return isMacOSGreaterThan11 ? `${__static}/menubar-newdarwinTemplate.png` : `${__static}/menubar.png`
return isMacOSGreaterThan11 ? './resources/menubar-newdarwinTemplate.png' : './resources/menubar.png'
} else {
return `${__static}/menubar-nodarwin.png`
return './resources/menubar-nodarwin.png'
}
}
export function createTray(tooltip: string) {
export function createTray (tooltip: string) {
const menubarPic = getTrayIcon()
setTray(new Tray(menubarPic))
tray.setToolTip(tooltip)
@@ -241,6 +238,7 @@ export function createTray(tooltip: string) {
createContextMenu()
tray!.popUpContextMenu(contextMenu!)
})
tray.on('click', (_, bounds) => {
if (process.platform === 'darwin') {
toggleWindow(bounds)
@@ -293,9 +291,9 @@ export function createTray(tooltip: string) {
tray.on('drag-enter', () => {
if (nativeTheme.shouldUseDarkColors) {
tray!.setImage(`${__static}/upload-dark.png`)
tray!.setImage('./resources/upload-dark.png')
} else {
tray!.setImage(`${__static}/upload.png`)
tray!.setImage('./resources/upload.png')
}
})
@@ -305,54 +303,56 @@ export function createTray(tooltip: string) {
// drop-files only be supported in macOS
// so the tray window must be available
tray.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)!
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[] = []
for (let i = 0; i < imgs.length; i++) {
if (deleteLocalFile) {
await fs.remove(rawInput[i])
}
const [pasteTextItem, shortUrl] = await pasteTemplate(
pasteStyle,
imgs[i],
db.get(configPaths.settings.customLink)
)
imgs[i].shortUrl = shortUrl
pasteText.push(pasteTextItem)
const isShowResultNotification =
if (process.platform === 'darwin') {
(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)!
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[] = []
for (let i = 0; i < imgs.length; i++) {
if (deleteLocalFile) {
await fs.remove(rawInput[i])
}
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!
if (isShowResultNotification) {
const notification = new Notification({
title: T('UPLOAD_SUCCEED'),
body: shortUrl || imgs[i].imgUrl!
// icon: files[i]
})
setTimeout(() => {
notification.show()
}, i * 100)
})
setTimeout(() => {
notification.show()
}, i * 100)
}
await GalleryDB.getInstance().insert(imgs[i])
}
await GalleryDB.getInstance().insert(imgs[i])
handleCopyUrl(pasteText.join('\n'))
trayWindow.webContents.send('dragFiles', imgs)
}
handleCopyUrl(pasteText.join('\n'))
trayWindow.webContents.send('dragFiles', imgs)
}
})
})
}
// toggleWindow()
} else if (process.platform === 'linux') {
// click事件在Ubuntu上无法触发Unity不支持在Mac和Windows上可以触发

View File

@@ -1,21 +1,19 @@
import { Notification, WebContents } from 'electron'
import fs from 'fs-extra'
import { cloneDeep } from 'lodash'
import picgo from '@core/picgo'
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 { T } from '~/i18n/index'
import { handleCopyUrl, handleUrlEncodeWithSetting } from '~/utils/common'
import pasteTemplate from '~/utils/pasteTemplate'
import { Notification, WebContents } from 'electron'
import fs from 'fs-extra'
import { cloneDeep } from 'lodash-es'
import { IPicGo } from 'piclist'
import { IPasteStyle, IWindowList } from '#/types/enum'
import { IFileWithPath, ImgInfo, IStringKeyMap, IUploadOption } from '#/types/types'
import { configPaths } from '#/utils/configPaths'
import { T } from '~/i18n/index'
import { handleCopyUrl, handleUrlEncodeWithSetting } from '~/utils/common'
import { changeCurrentUploader } from '~/utils/handleUploaderConfig'
import { IPicGo } from 'piclist'
import pasteTemplate from '~/utils/pasteTemplate'
const handleClipboardUploading = async (): Promise<false | ImgInfo[]> => {
const useBuiltinClipboard =
@@ -213,8 +211,8 @@ export const handleSecondaryUpload = async (
trayWindow?.webContents?.send('uploadFiles', secondImgs)
}
} else {
for (let i = 0; i < secondImgs.length; i++) {
await GalleryDB.getInstance().insert(secondImgs[i])
for (const secondImgsItem of secondImgs) {
await GalleryDB.getInstance().insert(secondImgsItem)
}
if (uploadType === 'tray') {
trayWindow?.webContents?.send('dragFiles', secondImgs)

View File

@@ -1,28 +1,27 @@
import dayjs from 'dayjs'
import { BrowserWindow, clipboard, ipcMain, Notification, WebContents } from 'electron'
import fs from 'fs-extra'
import path from 'path'
import { IPicGo } from 'piclist'
import util from 'util'
import writeFile from 'write-file-atomic'
import windowManager from 'apis/app/window/windowManager'
import path from 'node:path'
import util from 'node:util'
import db from '@core/datastore'
import picgo from '@core/picgo'
import logger from '@core/picgo/logger'
import { T } from '~/i18n'
import { showNotification, getClipboardFilePath, calcDurationRange } from '~/utils/common'
import windowManager from 'apis/app/window/windowManager'
import dayjs from 'dayjs'
import { BrowserWindow, clipboard, ipcMain, IpcMainEvent, Notification, WebContents } from 'electron'
import fs from 'fs-extra'
import { IPicGo } from 'piclist'
import writeFile from 'write-file-atomic'
import { GET_RENAME_FILE_NAME, RENAME_FILE_NAME, TALKING_DATA_EVENT } from '#/events/constants'
import { ICOREBuildInEvent, IWindowList } from '#/types/enum'
import { IAnalyticsData, ImgInfo, ITalkingDataOptions, IUploadOption } from '#/types/types'
import { configPaths } from '#/utils/configPaths'
import { CLIPBOARD_IMAGE_FOLDER } from '#/utils/static'
import { T } from '~/i18n'
import { calcDurationRange, getClipboardFilePath, showNotification } from '~/utils/common'
const waitForRename = (window: BrowserWindow, id: number): Promise<string | null> => {
return new Promise(resolve => {
ipcMain.once(`${RENAME_FILE_NAME}${id}`, (_: Event, newName: string) => {
ipcMain.once(`${RENAME_FILE_NAME}${id}`, (_: IpcMainEvent, newName: string) => {
resolve(newName)
window.close()
})
@@ -52,12 +51,12 @@ const handleTalkingData = (webContents: WebContents, options: IAnalyticsData) =>
class Uploader {
private webContents: WebContents | null = null
constructor() {
constructor () {
this.init()
}
init() {
picgo.on(ICOREBuildInEvent.NOTIFICATION, (message: Electron.NotificationConstructorOptions | undefined) => {
init () {
picgo.on(ICOREBuildInEvent.NOTIFICATION, (message: any) => {
new Notification(message).show()
})
@@ -88,7 +87,7 @@ class Uploader {
: item.fileName
if (rename) {
const window = windowManager.create(IWindowList.RENAME_WINDOW)!
ipcMain.on(GET_RENAME_FILE_NAME, evt => {
ipcMain.on(GET_RENAME_FILE_NAME, (evt, _) => {
try {
if (evt.sender.id === window.webContents.id) {
logger.info('rename window ready, wait for rename...')
@@ -108,12 +107,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
@@ -131,7 +130,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()
@@ -147,7 +146,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()
@@ -163,7 +162,7 @@ class Uploader {
}
}
async uploadReturnCtx(img?: IUploadOption, skipProcess = false): Promise<IPicGo | false> {
async uploadReturnCtx (img?: IUploadOption, skipProcess = false): Promise<IPicGo | false> {
try {
const startTime = Date.now()
const ctx = await picgo.uploadReturnCtx(img, skipProcess)
@@ -198,7 +197,7 @@ class Uploader {
}
}
async upload(img?: IUploadOption): Promise<ImgInfo[] | false> {
async upload (img?: IUploadOption): Promise<ImgInfo[] | false> {
try {
const startTime = Date.now()
const output = await picgo.upload(img)

View File

@@ -2,25 +2,27 @@ const isDevelopment = process.env.NODE_ENV !== 'production'
export const MANUAL_WINDOW_URL =
process.env.NODE_ENV === 'development'
? `${process.env.WEBPACK_DEV_SERVER_URL as string}#documents`
: 'picgo://./index.html#documents'
? 'http://localhost:3000#documents'
: 'index.html#documents'
export const MINI_WINDOW_URL = isDevelopment
? `${process.env.WEBPACK_DEV_SERVER_URL as string}#mini-page`
: 'picgo://./index.html#mini-page'
? 'http://localhost:3000#mini-page'
: 'index.html#mini-page'
export const RENAME_WINDOW_URL =
process.env.NODE_ENV === 'development'
? `${process.env.WEBPACK_DEV_SERVER_URL as string}#rename-page`
: 'picgo://./index.html#rename-page'
? 'http://localhost:3000#rename-page'
: 'index.html#rename-page'
export const SETTING_WINDOW_URL = isDevelopment
? `${process.env.WEBPACK_DEV_SERVER_URL as string}#main-page/upload`
: 'picgo://./index.html#main-page/upload'
? 'http://localhost:3000#main-page/upload'
: 'index.html#main-page/upload'
export const TRAY_WINDOW_URL = isDevelopment ? (process.env.WEBPACK_DEV_SERVER_URL as string) : 'picgo://./index.html'
export const TRAY_WINDOW_URL = isDevelopment ? 'http://localhost:3000' : 'index.html'
console.log(TRAY_WINDOW_URL)
export const TOOLBOX_WINDOW_URL =
process.env.NODE_ENV === 'development'
? `${process.env.WEBPACK_DEV_SERVER_URL as string}#toolbox-page`
: 'picgo://./index.html#toolbox-page'
? 'http://localhost:3000#toolbox-page'
: 'index.html#toolbox-page'

View File

@@ -1,24 +1,26 @@
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 } from 'electron'
import { TOGGLE_SHORTKEY_MODIFIED_MODE } from '#/events/constants'
import { IWindowListItem } from '#/types/electron'
import { IWindowList } from '#/types/enum'
import { IBrowserWindowOptions } from '#/types/types'
import { configPaths } from '#/utils/configPaths'
import { T } from '~/i18n'
import {
MANUAL_WINDOW_URL,
MINI_WINDOW_URL,
RENAME_WINDOW_URL,
SETTING_WINDOW_URL,
TRAY_WINDOW_URL,
TOOLBOX_WINDOW_URL
TOOLBOX_WINDOW_URL,
TRAY_WINDOW_URL
} from './constants'
import bus from '@core/bus'
import { CREATE_APP_MENU } from '@core/bus/constants'
import db from '@core/datastore'
import { T } from '~/i18n'
import { TOGGLE_SHORTKEY_MODIFIED_MODE } from '#/events/constants'
import { IWindowList } from '#/types/enum'
import { configPaths } from '#/utils/configPaths'
const windowList = new Map<IWindowList, IWindowListItem>()
const handleWindowParams = (windowURL: string) => windowURL
@@ -33,6 +35,7 @@ const getDefaultWindowSizes = (): { width: number; height: number } => {
height: mainWindowHeight || 800
}
}
const preloadPath = fileURLToPath(new URL('../preload/index.mjs', import.meta.url))
const { width: defaultWindowWidth, height: defaultWindowHeight } = getDefaultWindowSizes()
@@ -46,8 +49,10 @@ const trayWindowOptions = {
transparent: true,
vibrancy: 'ultra-dark',
webPreferences: {
nodeIntegration: !!process.env.ELECTRON_NODE_INTEGRATION,
contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION,
sandbox: false,
preload: preloadPath,
nodeIntegration: false,
contextIsolation: true,
nodeIntegrationInWorker: true,
backgroundThrottling: false,
webSecurity: false
@@ -66,10 +71,12 @@ const manualWindowOptions = {
vibrancy: 'ultra-dark',
transparent: false,
webPreferences: {
sandbox: false,
webviewTag: true,
backgroundThrottling: false,
nodeIntegration: !!process.env.ELECTRON_NODE_INTEGRATION,
contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION,
preload: preloadPath,
nodeIntegration: false,
contextIsolation: true,
nodeIntegrationInWorker: true,
webSecurity: false
}
@@ -88,10 +95,12 @@ const settingWindowOptions = {
transparent: true,
titleBarStyle: 'hidden',
webPreferences: {
sandbox: false,
webviewTag: true,
backgroundThrottling: false,
nodeIntegration: !!process.env.ELECTRON_NODE_INTEGRATION,
contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION,
preload: preloadPath,
nodeIntegration: false,
contextIsolation: true,
nodeIntegrationInWorker: true,
webSecurity: false
}
@@ -102,7 +111,7 @@ if (process.platform !== 'darwin') {
settingWindowOptions.frame = false
settingWindowOptions.backgroundColor = '#3f3c37'
settingWindowOptions.transparent = false
settingWindowOptions.icon = `${__static}/logo.png`
settingWindowOptions.icon = '.resources/logo.png'
}
const miniWindowOptions = {
@@ -114,11 +123,13 @@ const miniWindowOptions = {
skipTaskbar: true,
resizable: false,
transparent: process.platform !== 'linux',
icon: `${__static}/logo.png`,
icon: './resources/logo.png',
webPreferences: {
sandbox: false,
preload: preloadPath,
nodeIntegration: false,
contextIsolation: true,
backgroundThrottling: false,
nodeIntegration: !!process.env.ELECTRON_NODE_INTEGRATION,
contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION,
nodeIntegrationInWorker: true
}
} as IBrowserWindowOptions
@@ -135,8 +146,10 @@ const renameWindowOptions = {
resizable: false,
vibrancy: 'ultra-dark',
webPreferences: {
nodeIntegration: !!process.env.ELECTRON_NODE_INTEGRATION,
contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION,
sandbox: false,
preload: preloadPath,
nodeIntegration: false,
contextIsolation: true,
nodeIntegrationInWorker: true,
backgroundThrottling: false
}
@@ -159,11 +172,13 @@ const toolboxWindowOptions = {
resizable: false,
title: `PicList ${T('TOOLBOX')}`,
vibrancy: 'ultra-dark',
icon: `${__static}/logo.png`,
icon: './resources/logo.png',
webPreferences: {
sandbox: false,
backgroundThrottling: false,
nodeIntegration: !!process.env.ELECTRON_NODE_INTEGRATION,
contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION,
preload: preloadPath,
nodeIntegration: false,
contextIsolation: true,
nodeIntegrationInWorker: true,
webSecurity: false
}
@@ -179,7 +194,7 @@ windowList.set(IWindowList.TRAY_WINDOW, {
isValid: process.platform !== 'linux',
multiple: false,
options: () => trayWindowOptions,
callback(window) {
callback (window) {
window.loadURL(handleWindowParams(TRAY_WINDOW_URL))
window.on('blur', () => {
window.hide()
@@ -191,7 +206,7 @@ windowList.set(IWindowList.MANUAL_WINDOW, {
isValid: true,
multiple: false,
options: () => manualWindowOptions,
callback(window) {
callback (window) {
window.loadURL(handleWindowParams(MANUAL_WINDOW_URL))
window.focus()
}
@@ -201,8 +216,9 @@ windowList.set(IWindowList.SETTING_WINDOW, {
isValid: true,
multiple: false,
options: () => settingWindowOptions,
callback(window, windowManager) {
callback (window, windowManager) {
window.loadURL(handleWindowParams(SETTING_WINDOW_URL))
window.webContents.openDevTools({ mode: 'detach' })
window.on('closed', () => {
bus.emit(TOGGLE_SHORTKEY_MODIFIED_MODE, false)
if (process.platform === 'linux') {
@@ -220,7 +236,7 @@ windowList.set(IWindowList.MINI_WINDOW, {
isValid: process.platform !== 'darwin',
multiple: false,
options: () => miniWindowOptions,
callback(window) {
callback (window) {
window.loadURL(handleWindowParams(MINI_WINDOW_URL))
}
})
@@ -229,7 +245,7 @@ windowList.set(IWindowList.RENAME_WINDOW, {
isValid: true,
multiple: true,
options: () => renameWindowOptions,
async callback(window, windowManager) {
async callback (window, windowManager) {
window.loadURL(handleWindowParams(RENAME_WINDOW_URL))
const currentWindow = windowManager.getAvailableWindow(true)
if (currentWindow && currentWindow.isVisible()) {
@@ -245,7 +261,7 @@ windowList.set(IWindowList.TOOLBOX_WINDOW, {
isValid: true,
multiple: false,
options: () => toolboxWindowOptions,
async callback(window, windowManager) {
async callback (window, windowManager) {
window.loadURL(TOOLBOX_WINDOW_URL)
const currentWindow = windowManager.getAvailableWindow(true)
if (currentWindow && currentWindow.isVisible()) {

View File

@@ -1,13 +1,14 @@
import windowList from 'apis/app/window/windowList'
import { BrowserWindow } from 'electron'
import windowList from 'apis/app/window/windowList'
import { IWindowListItem, IWindowManager } from '#/types/electron'
import { IWindowList } from '#/types/enum'
class WindowManager implements IWindowManager {
#windowMap: Map<IWindowList | string, BrowserWindow> = new Map()
#windowIdMap: Map<number, IWindowList | string> = new Map()
create(name: IWindowList) {
create (name: IWindowList) {
const windowConfig: IWindowListItem = windowList.get(name)!
if (!windowConfig.isValid) return null
@@ -29,14 +30,14 @@ class WindowManager implements IWindowManager {
return window
}
get(name: IWindowList) {
get (name: IWindowList) {
if (this.has(name)) {
return this.#windowMap.get(name)!
}
return this.create(name)
}
has(name: IWindowList) {
has (name: IWindowList) {
return this.#windowMap.has(name)
}
@@ -48,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