☰
PicGo 2.4.1 版本解析:macOS 菜单栏图标控制、剪贴板上传修复与 Electron 38 迁移实践
2026/9/30 2:34:37 网站建设 项目流程
  • 桌面应用
  • 开发工具
  • 插件系统

【免费下载链接】PicGo

:rocket: The Ultimate Image Uploader for Efficient Creators. Supports Obsidian, Typora, VS Code etc. and 60+ image hosting services (S3, GitHub, Cloudflare R2, Imgur, Aliyun OSS...). Paste, upload, done.

项目地址:https://gitcode.com/gh_mirrors/pi/PicGo
点击查看免费下载

导读

PicGo 2.4.1 是一次聚焦 macOS 体验与构建基础设施的维护性版本,核心内容包括:新增showMenubarIcon配置项用于控制 macOS 顶部菜单栏图标的显示与隐藏、修复 macOS 菜单栏窗口无法读取剪贴板图片以及 Intel 架构应用无法打开的问题,并将 Electron 升级到 v38、底层构建框架迁移到 Electron-vite,同时统一了 Windows/Linux 主窗口样式并补齐 ARM64 与 Linux deb 构建产物。本文结合当前仓库源码(system/index.ts、settings-section-appearance.tsx、uploader/index.ts 等)逐项解析这些变更背后的实现细节,帮助读者理解 PicGo 的菜单栏/托盘体系、剪贴板图片链路以及 Electron-vite 构建配置。

一、showMenubarIcon:macOS 顶部栏图标开关的实现原理

1.1 配置项的定义与默认值

showMenubarIcon在 2.4.1 中作为新增设置项(对应上游 issue #1222)进入 PicGo 的配置体系。从源码看,它被定义在设置配置类型中,默认值为true:

  • 类型声明位于 src/universal/types/view.d.ts,与showDockIcon并列;
  • 渲染进程的默认配置定义在 src/renderer/components/main/settings/utils.ts,showMenubarIcon: true;
  • 存储层的归一化处理位于 src/renderer/store/utils.ts,通过normalizeBoolean确保旧配置缺失时回退到默认值true。

也就是说,2.4.1 之后即使老用户从未设置过该字段,行为也保持兼容(默认显示菜单栏图标)。

1.2 配置持久化路径:settings.showMenubarIcon

在 PicGo 中,配置以settings.xxx的点分键形式写入配置文件(data.json)。菜单栏图标开关的完整链路为:

  1. 用户在“设置 → 外观”面板中操作 Switch 控件;
  2. 组件调用saveSettingsConfig("settings.showMenubarIcon", checked);
  3. 保存后触发 store/settings/actions.ts 中的showMenubarIcon分支;
  4. 通过 renderer/adapters/settings.ts 发送IRPCActionType.SHOW_MENUBAR_ICONRPC 请求到主进程。

界面层的具体实现见 settings-section-appearance.tsx:该开关只在 macOS(isMac为 true)时显示,且带有一段重要提示文案。

1.3 主进程的托盘生命周期管理

主进程侧的核心函数是handleMenubarIcon(system/index.ts),它的语义如下:

export function handleMenubarIcon (visible?: boolean) { if (!isMacOS) { if (!tray) { createTray() } return } const shouldShow = visible !== undefined ? visible : (picgo.getConfig<boolean>('settings.showMenubarIcon') !== false) if (shouldShow) { if (!tray) { createTray() } } else { destroyTray() } }

要点解读:

  • 平台分支:对非 macOS 平台(Windows/Linux),该函数强制创建托盘且不响应隐藏请求——也就是说showMenubarIcon是 macOS 专属设置,其他平台始终显示托盘图标;
  • 读取配置:visible参数未传入时,读取settings.showMenubarIcon且!== false判断,与默认值true保持一致性;
  • 销毁逻辑:destroyTray会移除监听、销毁 Tray 实例并隐藏 TRAY_WINDOW(system/index.ts),避免隐藏图标后残留浮窗。

createTray(system/index.ts)中还包含一组平台差异化行为:

  • macOS 使用模板图标menubar-newdarwinTemplate.png(macOS 11+)或menubar.png,支持系统明暗主题自动着色(getTrayIcon与drag-enter/drag-end时切换upload-dark.png/upload.png);
  • macOS/Windows 上监听click弹出托盘窗口、right-click弹出上下文菜单、drop-files直接拖拽上传;Linux(Unity)不支持点击事件,改用tray.setContextMenu。

1.4 重要提醒:Dock 与菜单栏图标全关时的恢复手段

多语言文案 public/i18n/zh-CN.yml 中明确提示:

若“显示 Dock 栏图标”和“显示顶部栏图标”都关闭,将会无法找到 PicGo 主界面。需要手动修改配置文件里的showDockIcon或showMenubarIcon为true才能恢复。

与之对应的handleDockIcon(system/index.ts)在 macOS 上通过app.dock.show()/hide()控制 Dock 图标。因此若两个开关同时关闭,应用将没有可见入口,恢复方式是编辑配置文件将任一字段改回true后重启。

二、剪贴板图片链路的修复与uploadWithBuildInClipboard

2.1 问题背景与修复意义

2.4.1 修复了“macOS 菜单栏窗口无法读取剪贴板图片”的问题(上游 issue #1310)。理解这条链路,需要先看 macOS 托盘窗口的完整上传路径。

在 macOS 上点击菜单栏图标时,主进程会读取系统剪贴板并组装ImgInfo数组,再通过webContents.send('clipboardFiles', obj)推送给 TRAY_WINDOW(system/index.ts)。其中涉及两种剪贴板取图方式:

  1. 文件路径方式:调用getClipboardFilePathList()(基于clip-filepaths,见 common.ts),返回剪贴板中的文件路径列表;
  2. 原生图像方式:clipboard.readImage()读取位图数据。

在 2.4.1 之前的版本,托盘窗口依赖的取图链路存在缺陷导致无法正常读取剪贴板图片,2.4.1 统一并加固了这一路径。

2.2uploadWithBuildInClipboard:内置剪贴板上传的兜底实现

主进程 IPC 监听uploadClipboardFiles事件时(ipcList.ts),会调用 uploader 的uploadWithBuildInClipboard()。该方法的完整实现位于 uploader/index.ts:

async uploadWithBuildInClipboard (): Promise<ImgInfo[]|false> { let filePath = '' try { const imgPath = getClipboardFilePathList() if (!imgPath.length) { const nativeImage = clipboard.readImage() if (nativeImage.isEmpty()) { return false } const buffer = nativeImage.toPNG() const baseDir = picgo.baseDir const fileName = `${dayjs().format('YYYYMMDDHHmmssSSS')}.png` filePath = path.join(baseDir, CLIPBOARD_IMAGE_FOLDER, fileName) await writeFile(filePath, buffer) return await this.upload([filePath]) } else { return await this.upload(imgPath) } } catch (e: any) { logger.error(e) return false } finally { if (filePath) { fse.unlink(filePath) } } }

逻辑要点:

  • 优先文件路径:剪贴板中存在文件路径时直接以上传文件的方式处理;
  • 降级为位图:无文件路径时读取clipboard.readImage(),若为空返回false;
  • 临时落盘:将位图以YYYYMMDDHHmmssSSS.png命名写入picgo.baseDir下的剪贴板图片目录,上传后在finally中删除临时文件,不留垃圾数据。

这条链路的有效性同样被测试验证:src/__tests__/main/uploader-apis.spec.ts中配置settings.useBuiltinClipboard = true后断言uploadWithBuildInClipboard被调用、普通upload不被调用(uploader-apis.spec.ts)。此外apis.ts中handleClipboardUploading会根据settings.useBuiltinClipboard决定走内置剪贴板还是文件选择器(apis.ts),与本次修复共同构成了完整的剪贴板上传体系。

三、macOS Intel 构建无法打开的修复

2.4.1 修复了 macOS Intel(x64)架构应用无法打开的问题(issue #1363 / #1310)。从当前仓库的构建配置 electron-builder.config.ts 可以看到 macOS 目标同时产出arm64与x64两种架构的 dmg:

mac: { icon: 'build/icons/icon.icns', extendInfo: { LSUIElement: 0 }, target: [ { target: 'dmg', arch: ['arm64', 'x64'] } ], artifactName: 'PicGo-${version}-${arch}.${ext}', hardenedRuntime: true, entitlements: 'build/entitlements.mac.plist', entitlementsInherit: 'build/entitlements.mac.plist', notarize: false }

LSUIElement: 0表示应用保留 Dock 图标;hardenedRuntime与 entitlements 用于 macOS 签名/公证环境。Intel 机型必须选择x64架构产物安装,2.4.1 通过对 x64 构建流程的修复(该版本 changelog 指向 #1363、#1310)解决了此前 x64 包无法启动的问题。从仓库scripts/notarize.js的存在可以推断项目在签名环节做了额外处理(可通过SKIP_NOTARIZE环境变量跳过,见 electron-builder.config.ts)。

四、Electron 38 与 Electron-vite 构建框架迁移

4.1 依赖层面的变更证据

当前仓库 package.json 中已固化本次迁移的成果:

  • "electron": "^38"(devDependencies);
  • "electron-vite": "^4.0.1";
  • 构建脚本统一为 electron-vite 系列:build(electron-vite build)、dev(electron-vite dev)、preview(electron-vite preview);
  • 平台打包通过electron-builder配合 electron-builder.config.ts 执行(build:win/build:mac/build:linux)。

4.2 三进程构建配置

electron.vite.config.ts 是本次迁移的核心配置文件,它同时管理主进程、preload 与渲染进程三个构建目标:

进程入口输出目录说明
mainsrc/background.tsdist_electron/mainexternalizeDepsPlugin()外部化依赖
preloadsrc/preload/index.tsdist_electron/preload排除@picgo/i18n
renderersrc/renderer/index.htmldist_electron/renderer集成 React、TailwindCSS、TanStack Router

配置中的路径别名体系(@→src/renderer、~→src、#→src/universal、apis、@core)被主进程源码广泛使用,例如import uploader from 'apis/app/uploader'、import picgo from '@core/picgo',这正是 Electron-vite 对多进程工程化组织的支持体现。

值得注意的是,虽然当前package.json中仍保留vue、element-plus、vue-router等依赖,渲染进程实际已由 TanStack Router + React 驱动(src/renderer/main.tsx、routeTree.gen.ts),可以推断迁移过程伴随了渲染层技术栈的演进;2.4.1 的核心承诺是“构建框架切换”,本文以配置证据为准,不做过度引申。

4.3 构建与打包命令

迁移后的常用命令(需在仓库根目录执行):

pnpm install # 安装依赖(postinstall 自动执行 electron-builder install-app-deps) pnpm dev # electron-vite dev 启动开发模式 pnpm build # electron-vite build 构建三进程产物 pnpm build:mac # 构建 + electron-builder 打包 macOS pnpm build:win # 构建 + electron-builder 打包 Windows pnpm build:linux # 构建 + electron-builder 打包 Linux pnpm tsc # TypeScript 类型检查 pnpm test # vitest 运行测试

五、Windows/Linux 主窗口样式统一与新增构建产物

2.4.1 的另一项用户可见变更是:Windows 与 Linux 主窗口样式统一为与 macOS 一致的外观,同时新增了 Linuxdeb包以及 Windows/Linux 的 ARM64 构建。

从 electron-builder.config.ts 可以看到当前产物矩阵:

平台目标格式架构
Windowsnsis 安装包x64、ia32、arm64
LinuxAppImagex64、arm64
Linuxdebx64、arm64(2.4.1 新增)
Linuxsnapx64
macOSdmgarm64、x64

同时nsis配置了oneClick: false、allowToChangeInstallationDirectory: true,即 Windows 安装器允许用户选择安装目录。Linux 包声明了maintainer与category: 'Utility',方便桌面环境归类应用。

六、小结

PicGo 2.4.1 表面上是一次小版本维护,实则包含三条值得研究的工程链路:

  1. 配置驱动的主进程能力:showMenubarIcon从渲染层设置、store 归一化、RPC 适配器到主进程handleMenubarIcon/createTray/destroyTray的完整生命周期,展示了 Electron 应用“设置项-IPC-系统集成”的标准写法;
  2. 剪贴板取图的双路径兜底:getClipboardFilePathList+clipboard.readImage()+ 临时文件落盘的组合,是 macOS 托盘上传稳定性修复的关键;
  3. 构建体系的现代化:Electron 38 + Electron-vite 的迁移在 package.json 与 electron.vite.config.ts 中留下完整证据,deb与 ARM64 产物则拓宽了 Linux 与 ARM 设备的安装渠道。

对于想要深入源码的读者,建议按以下顺序阅读:system/index.ts(托盘/菜单栏核心)→ settings-section-appearance.tsx(设置界面)→ uploader/index.ts(剪贴板上传)→ electron.vite.config.ts(构建配置),并配合 uploader-apis.spec.ts 理解测试对行为的锁定。

  • 桌面应用
  • 开发工具
  • 插件系统

【免费下载链接】PicGo

:rocket: The Ultimate Image Uploader for Efficient Creators. Supports Obsidian, Typora, VS Code etc. and 60+ image hosting services (S3, GitHub, Cloudflare R2, Imgur, Aliyun OSS...). Paste, upload, done.

项目地址:https://gitcode.com/gh_mirrors/pi/PicGo
点击查看免费下载

相关推荐

上一篇:radix-vue SelectRoot 组件完全指南:从 Props 到源码原理的深度剖析
下一篇:SeaTunnel 本地部署实战指南:从二进制包下载、Connector 插件安装到引擎选型运行

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询