From 8f8244af056a2874a7ab6d20a5a4fa9aafc12f77 Mon Sep 17 00:00:00 2001 From: Melorise <0d00@0721.hk> Date: Mon, 24 Aug 2026 00:14:40 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20=E8=AE=BE=E7=BD=AE=E9=A1=B5=E6=94=B9?= =?UTF-8?q?=E4=B8=BA=E6=8C=89=E9=9C=80=E5=88=9B=E5=BB=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit AI-assisted-by: Codex AI-model: gpt-5.6-sol AI-reasoning-effort: medium Co-authored-by: Codex --- AGENTS.md | 2 +- CHANGELOG.md | 6 +++++ CLAUDE.md | 2 +- linux/fcitx5/CMakeLists.txt | 2 +- linux/fcitx5/meloasr.conf.in | 2 +- package-lock.json | 4 +-- package.json | 2 +- packaging/README.md | 4 +-- packaging/arch/PKGBUILD | 2 +- packaging/arch/README.md | 2 +- packaging/assets/meloasr.metainfo.xml | 1 + packaging/deb/build-deb.sh | 2 +- packaging/rpm/build-rpm.sh | 2 +- packaging/rpm/meloasr-binary.spec | 3 +++ src/main/index.ts | 4 +-- src/main/settings-window.ts | 37 ++++++++++++++++++--------- src/main/tray-controller.ts | 4 +-- 17 files changed, 51 insertions(+), 30 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 0c57f94..987d3d4 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -2,7 +2,7 @@ ## 项目范围 -MeloASR 是仅面向 Linux 的 Fcitx5 桌面语音输入工具。项目名为 `MeloASR`,分发包名为 `meloasr`,当前版本为 `0.1.12`。 +MeloASR 是仅面向 Linux 的 Fcitx5 桌面语音输入工具。项目名为 `MeloASR`,分发包名为 `meloasr`,当前版本为 `0.1.13`。 不得恢复 Windows、PowerShell 或 Tauri 输出路径。发行版差异只能存在于依赖说明和打包配置,不能进入语音输入核心逻辑。 diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d7d9a9..d37754e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ 本项目遵循 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/) 的格式。 +## [0.1.13] - 2026-08-24 + +### 变更 + +- 设置页改为按需创建,关闭窗口后立即销毁其 renderer 以降低常驻内存。 + ## [0.1.12] - 2026-08-23 ### 变更 diff --git a/CLAUDE.md b/CLAUDE.md index 0c57f94..987d3d4 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -2,7 +2,7 @@ ## 项目范围 -MeloASR 是仅面向 Linux 的 Fcitx5 桌面语音输入工具。项目名为 `MeloASR`,分发包名为 `meloasr`,当前版本为 `0.1.12`。 +MeloASR 是仅面向 Linux 的 Fcitx5 桌面语音输入工具。项目名为 `MeloASR`,分发包名为 `meloasr`,当前版本为 `0.1.13`。 不得恢复 Windows、PowerShell 或 Tauri 输出路径。发行版差异只能存在于依赖说明和打包配置,不能进入语音输入核心逻辑。 diff --git a/linux/fcitx5/CMakeLists.txt b/linux/fcitx5/CMakeLists.txt index 1fe45a3..4274dc4 100644 --- a/linux/fcitx5/CMakeLists.txt +++ b/linux/fcitx5/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.16) -project(meloasr-fcitx5 VERSION 0.1.12 LANGUAGES CXX) +project(meloasr-fcitx5 VERSION 0.1.13 LANGUAGES CXX) include(GNUInstallDirs) include(CTest) diff --git a/linux/fcitx5/meloasr.conf.in b/linux/fcitx5/meloasr.conf.in index b4622d0..fffb191 100644 --- a/linux/fcitx5/meloasr.conf.in +++ b/linux/fcitx5/meloasr.conf.in @@ -6,7 +6,7 @@ Comment[zh_CN]=将 MeloASR 网页后端连接到当前输入上下文 Type=SharedLibrary Library=@MELOASR_LIBRARY_PATH@ Category=Module -Version=0.1.12 +Version=0.1.13 OnDemand=False Configurable=False diff --git a/package-lock.json b/package-lock.json index f9f7b15..48e6803 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "meloasr", - "version": "0.1.12", + "version": "0.1.13", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "meloasr", - "version": "0.1.12", + "version": "0.1.13", "devDependencies": { "@types/node": "^24.0.0", "electron": "42.3.0", diff --git a/package.json b/package.json index d9f8682..4fd368b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "meloasr", "productName": "MeloASR", - "version": "0.1.12", + "version": "0.1.13", "private": true, "author": "MeloASR contributors", "description": "基于网页语音识别后端和 Fcitx5 的 Linux 实时语音输入工具", diff --git a/packaging/README.md b/packaging/README.md index 065a55e..3851d04 100644 --- a/packaging/README.md +++ b/packaging/README.md @@ -1,6 +1,6 @@ # Linux 分发打包 -MeloASR 0.1.12 的系统包由两部分组成: +MeloASR 0.1.13 的系统包由两部分组成: - Electron 应用安装到 `/opt/meloasr`,命令入口为 `/usr/bin/meloasr`; - Fcitx5 常驻 addon 由目标发行版中的 CMake/Fcitx5 开发包编译,并安装到该环境报告的 addon 目录。 @@ -40,7 +40,7 @@ npm run build:linux:dir packaging/deb/build-deb.sh ``` -产物位于 `packaging/out/meloasr_0.1.12_.deb`。依赖名称按 Debian/Ubuntu 系列填写,但尚未在各发行版完成安装验证。 +产物位于 `packaging/out/meloasr_0.1.13_.deb`。依赖名称按 Debian/Ubuntu 系列填写,但尚未在各发行版完成安装验证。 ## rpm diff --git a/packaging/arch/PKGBUILD b/packaging/arch/PKGBUILD index 917ccec..c07b91e 100644 --- a/packaging/arch/PKGBUILD +++ b/packaging/arch/PKGBUILD @@ -1,5 +1,5 @@ pkgname=meloasr -pkgver=0.1.12 +pkgver=0.1.13 pkgrel=1 pkgdesc='Web-backed voice input for Fcitx5' arch=('x86_64') diff --git a/packaging/arch/README.md b/packaging/arch/README.md index 194c5e3..6e7579d 100644 --- a/packaging/arch/README.md +++ b/packaging/arch/README.md @@ -1,6 +1,6 @@ # Arch Linux 构建 -发布时把项目源码归档为 `meloasr-0.1.12.tar.gz`,与 `PKGBUILD` 放在同一目录,随后运行: +发布时把项目源码归档为 `meloasr-0.1.13.tar.gz`,与 `PKGBUILD` 放在同一目录,随后运行: ```bash makepkg --syncdeps --cleanbuild diff --git a/packaging/assets/meloasr.metainfo.xml b/packaging/assets/meloasr.metainfo.xml index 4eb1b80..6abf1e3 100644 --- a/packaging/assets/meloasr.metainfo.xml +++ b/packaging/assets/meloasr.metainfo.xml @@ -16,6 +16,7 @@ meloasr + diff --git a/packaging/deb/build-deb.sh b/packaging/deb/build-deb.sh index 60d9b46..2104903 100755 --- a/packaging/deb/build-deb.sh +++ b/packaging/deb/build-deb.sh @@ -2,7 +2,7 @@ set -euo pipefail project_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/../.." && pwd)" -version="${MELOASR_VERSION:-0.1.12}" +version="${MELOASR_VERSION:-0.1.13}" arch="${MELOASR_DEB_ARCH:-$(dpkg --print-architecture)}" app_dir="${1:-${MELOASR_ELECTRON_APP_DIR:-${project_dir}/release/linux-unpacked}}" work_dir="${project_dir}/packaging/out/deb-root" diff --git a/packaging/rpm/build-rpm.sh b/packaging/rpm/build-rpm.sh index 4d70191..25cdcf4 100755 --- a/packaging/rpm/build-rpm.sh +++ b/packaging/rpm/build-rpm.sh @@ -2,7 +2,7 @@ set -euo pipefail project_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/../.." && pwd)" -version="${MELOASR_VERSION:-0.1.12}" +version="${MELOASR_VERSION:-0.1.13}" app_dir="${1:-${MELOASR_ELECTRON_APP_DIR:-${project_dir}/release/linux-unpacked}}" stage_dir="${project_dir}/packaging/out/rpm-root" top_dir="${project_dir}/packaging/out/rpmbuild" diff --git a/packaging/rpm/meloasr-binary.spec b/packaging/rpm/meloasr-binary.spec index 9a6072c..aa7d41c 100644 --- a/packaging/rpm/meloasr-binary.spec +++ b/packaging/rpm/meloasr-binary.spec @@ -36,6 +36,9 @@ tar -C %{buildroot} -xzf %{SOURCE0} /etc/xdg/autostart/meloasr.desktop %changelog +* Mon Aug 24 2026 MeloASR contributors - 0.1.13-1 +- Create the settings renderer only when it is opened and destroy it on close. + * Sun Aug 23 2026 MeloASR contributors - 0.1.12-1 - Disable Electron GPU acceleration for background web renderers. diff --git a/src/main/index.ts b/src/main/index.ts index 208da68..d94dfe1 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -39,9 +39,7 @@ async function bootstrap(): Promise { const repositoryUrl = process.env.MELOASR_REPOSITORY_URL?.trim() || 'https://github.com/Melorise/MeloASR'; const settingsWindow = new SettingsWindow(settings, backends, overlay, sessions, repositoryUrl); - const settingsWindowReady = settingsWindow.create(); registerIpc({ settings, autoStart, bridge, backends, overlay, sessions, settingsWindow }); - await settingsWindowReady; const tray = new TrayController( backends, settingsWindow, @@ -68,7 +66,7 @@ async function bootstrap(): Promise { await backends.ensure(settings.get().backendId); tray.refresh(); - app.on('second-instance', () => settingsWindow.show()); + app.on('second-instance', () => void settingsWindow.show()); app.on('before-quit', () => { (app as typeof app & { isQuitting?: boolean }).isQuitting = true; }); app.on('will-quit', () => { tray.destroy(); diff --git a/src/main/settings-window.ts b/src/main/settings-window.ts index 0b772fd..e2a0419 100644 --- a/src/main/settings-window.ts +++ b/src/main/settings-window.ts @@ -9,6 +9,7 @@ import type { SettingsStore } from './settings-store'; export class SettingsWindow { window: BrowserWindow | null = null; + private creating: Promise | null = null; constructor( private readonly settings: SettingsStore, @@ -18,8 +19,19 @@ export class SettingsWindow { private readonly repositoryUrl: string | null ) {} - async create(): Promise { - this.window = new BrowserWindow({ + private async ensureWindow(): Promise { + if (this.window && !this.window.isDestroyed()) return this.window; + if (this.creating) return this.creating; + this.creating = this.createWindow(); + try { + return await this.creating; + } finally { + this.creating = null; + } + } + + private async createWindow(): Promise { + const window = new BrowserWindow({ width: 720, height: 820, minWidth: 640, @@ -35,18 +47,19 @@ export class SettingsWindow { sandbox: true } }); - this.window.on('close', (event) => { - if ((app as typeof app & { isQuitting?: boolean }).isQuitting) return; - event.preventDefault(); - this.window?.hide(); + this.window = window; + window.on('closed', () => { + this.overlay.endPositioning(); + if (this.window === window) this.window = null; }); - this.window.on('hide', () => this.overlay.endPositioning()); - await this.window.loadFile(path.join(__dirname, '..', 'renderer', 'settings.html')); + await window.loadFile(path.join(__dirname, '..', 'renderer', 'settings.html')); + return window; } - show(): void { - this.window?.show(); - this.window?.focus(); + async show(): Promise { + const window = await this.ensureWindow(); + window.show(); + window.focus(); this.publish(); } @@ -60,7 +73,7 @@ export class SettingsWindow { const definition = this.backends.activeDefinition(); const decision = resolveDebugLoginAction(Boolean(current.loginNoticeShown[definition.id]), confirmed); if (decision.action === 'prompt') { - this.show(); + await this.show(); this.window?.webContents.send('settings:login-notice', { backendLabel: definition.label }); return; } diff --git a/src/main/tray-controller.ts b/src/main/tray-controller.ts index 2b34be4..22996c9 100644 --- a/src/main/tray-controller.ts +++ b/src/main/tray-controller.ts @@ -31,7 +31,7 @@ export class TrayController { create(): void { this.tray = new Tray(trayImage('loading')); this.tray.setToolTip('MeloASR · 正在加载'); - this.tray.on('click', () => this.settingsWindow.show()); + this.tray.on('click', () => void this.settingsWindow.show()); this.refresh(); } @@ -44,7 +44,7 @@ export class TrayController { this.tray.setImage(trayImage(state)); this.tray.setToolTip(`MeloASR · ${status.detail}`); this.tray.setContextMenu(Menu.buildFromTemplate([ - { label: '设置', click: () => this.settingsWindow.show() }, + { label: '设置', click: () => void this.settingsWindow.show() }, { label: '打开登录/调试页面', click: () => void this.settingsWindow.openDebug() }, { type: 'separator' }, { label: '重启', click: this.onRestart },