Ariver
2026-06-03 024255c6a55c9f740ce740726616dc6ff4273b06
Rename app to PrivateVoice Dictation
25 files modified
177 ■■■■■ changed files
02-P-NBL/plan.md 5 ●●●●● patch | view | raw | blame | history
02-P-NBL/round-5/todo-list.md 13 ●●●● patch | view | raw | blame | history
CHANGELOG.md 15 ●●●●● patch | view | raw | blame | history
privatevoice.src/app.go 6 ●●●● patch | view | raw | blame | history
privatevoice.src/build/config.yml 6 ●●●● patch | view | raw | blame | history
privatevoice.src/build/darwin/Info.plist 12 ●●●● patch | view | raw | blame | history
privatevoice.src/build/linux/privatevoice-input.desktop 2 ●●● patch | view | raw | blame | history
privatevoice.src/build/windows/wails.exe.manifest 4 ●●●● patch | view | raw | blame | history
privatevoice.src/frontend/index.html 2 ●●● patch | view | raw | blame | history
privatevoice.src/frontend/package-lock.json 8 ●●●● patch | view | raw | blame | history
privatevoice.src/frontend/package.json 4 ●●●● patch | view | raw | blame | history
privatevoice.src/frontend/src/components/settings/SettingsWindow.svelte 22 ●●●●● patch | view | raw | blame | history
privatevoice.src/frontend/src/components/shared/AppIcon.svelte 2 ●●● patch | view | raw | blame | history
privatevoice.src/frontend/src/lib/i18n/en.json 24 ●●●● patch | view | raw | blame | history
privatevoice.src/frontend/src/lib/i18n/zh.json 22 ●●●● patch | view | raw | blame | history
privatevoice.src/internal/hotkey/hotkey_darwin.go 4 ●●●● patch | view | raw | blame | history
privatevoice.src/internal/startup/startup_linux.go 2 ●●● patch | view | raw | blame | history
privatevoice.src/internal/startup/startup_windows.go 2 ●●● patch | view | raw | blame | history
privatevoice.src/main.go 4 ●●●● patch | view | raw | blame | history
privatevoice.src/scripts/build-appstore-developerid-macos.sh 2 ●●● patch | view | raw | blame | history
privatevoice.src/scripts/build-appstore-macos.sh 2 ●●● patch | view | raw | blame | history
privatevoice.src/scripts/build-local-macos.sh 4 ●●●● patch | view | raw | blame | history
privatevoice.src/scripts/build-release-macos.sh 4 ●●●● patch | view | raw | blame | history
privatevoice.src/services/app_service.go 2 ●●● patch | view | raw | blame | history
privatevoice.src/wails.json 4 ●●●● patch | view | raw | blame | history
02-P-NBL/plan.md
@@ -521,10 +521,11 @@
### 10.5 后续 UI 与品牌命名调整
以下需求先记录,等进入合适的 UI/品牌整理节点再实现,不作为 Round 3 Moonshine 验收阻断项:
以下需求已进入 `v2.1.24 build 20260603.1934` 品牌命名调整:
- 左侧 Logo 区只显示 `PrivateVoice`,下方小字显示 `Private. Offline.`。
- App 正式名称从 `PrivateVoice Input` 改为 `PrivateVoice Dictation`。该调整需要同步处理界面显示、macOS App bundle 名称、DMG 文件名、Info.plist、release manifest、测试文档和用户可见文案。
- App 正式名称从 `PrivateVoice Input` 改为 `PrivateVoice Dictation`。
- 本轮不迁移用户数据目录,继续使用既有 `Application Support/PrivateVoice Input`,避免影响历史记录、模型文件和系统权限。
## 11. 总体建议
02-P-NBL/round-5/todo-list.md
@@ -67,12 +67,19 @@
- [ ] 用户验收候选包
- [ ] 用户验收
## 6. 暂缓记录
## 6. UI/品牌命名调整
以下事项已进入 `v2.1.24 build 20260603.1934`:
- [x] 左侧 Logo 区只显示 `PrivateVoice`,下方小字显示 `Private. Offline.`。
- [x] App 正式名称从 `PrivateVoice Input` 改为 `PrivateVoice Dictation`。
- [x] macOS App bundle 名称、DMG 文件名、Info.plist、Wails 构建配置和用户可见文案同步。
- [x] 不迁移用户数据目录,继续使用既有 `Application Support/PrivateVoice Input`。
## 7. 暂缓记录
以下事项不作为 Round 5 阻断项:
- 左侧 Logo 区只显示 `PrivateVoice`,下方小字显示 `Private. Offline.`。
- App 正式名称从 `PrivateVoice Input` 改为 `PrivateVoice Dictation`。
- 粤语作为独立语言版本。
- 欧洲语言 UI。
- 模型删除 UI 的完整成熟化。
CHANGELOG.md
@@ -1,5 +1,20 @@
# Changelog
## v2.1.24 (2026-06-03)
### QA 候选包
- **品牌命名调整**:App 正式名称从 `PrivateVoice Input` 改为 `PrivateVoice Dictation`,同步 macOS App bundle、DMG 文件名、Info.plist、Wails 构建配置和用户可见文案。
- **侧栏 Logo 区调整**:左侧品牌区只显示 `PrivateVoice`,下方小字显示 `Private. Offline.`。
- **升级兼容保护**:本轮不迁移用户数据目录,继续使用既有 `Application Support/PrivateVoice Input`,避免影响历史记录、模型文件和系统权限。
### 构建
- build: `20260603.1934`
- 说明: 本版本为 Round 5 后追加的 UI/品牌命名验收候选包。
---
## v2.1.23 (2026-06-03)
### QA 候选包
privatevoice.src/app.go
@@ -27,10 +27,10 @@
)
const (
    appVersion        = "2.1.23"
    appBuild          = "20260603.1904"
    appVersion        = "2.1.24"
    appBuild          = "20260603.1934"
    appDisplayVersion = appVersion + " (build " + appBuild + ")"
    appName           = "PrivateVoice Input"
    appName           = "PrivateVoice Dictation"
    silenceThreshold         = 0.05            // RMS below this = silence (matches HasVoiceActivity)
    silenceTimeoutDuration   = 3 * time.Second // auto-stop after this much silence in free-talk
privatevoice.src/build/config.yml
@@ -2,12 +2,12 @@
info:
  companyName: "PrivateVoice"
  productName: "PrivateVoice Input"
  productName: "PrivateVoice Dictation"
  productIdentifier: "com.privatevoice.input"
  description: "Private offline voice input tool"
  copyright: "(c) 2026, PrivateVoice"
  comments: "Private.Offline"
  version: "2.1.23"
  comments: "Private. Offline."
  version: "2.1.24"
dev_mode:
  root_path: .
privatevoice.src/build/darwin/Info.plist
@@ -3,25 +3,25 @@
<plist version="1.0">
<dict>
    <key>CFBundleExecutable</key>
    <string>PrivateVoice Input</string>
    <string>PrivateVoice Dictation</string>
    <key>CFBundleIconFile</key>
    <string>icon.icns</string>
    <key>CFBundleIdentifier</key>
    <string>com.privatevoice.input</string>
    <key>CFBundleName</key>
    <string>PrivateVoice Input</string>
    <string>PrivateVoice Dictation</string>
    <key>CFBundleDisplayName</key>
    <string>PrivateVoice Input</string>
    <string>PrivateVoice Dictation</string>
    <key>CFBundlePackageType</key>
    <string>APPL</string>
    <key>CFBundleShortVersionString</key>
    <string>2.1.23</string>
    <string>2.1.24</string>
    <key>CFBundleVersion</key>
    <string>20260603.1904</string>
    <string>20260603.1934</string>
    <key>LSMinimumSystemVersion</key>
    <string>11.0</string>
    <key>NSMicrophoneUsageDescription</key>
    <string>PrivateVoice Input needs microphone access for voice-to-text input.</string>
    <string>PrivateVoice Dictation needs microphone access for voice-to-text input.</string>
    <key>NSHighResolutionCapable</key>
    <true/>
    <key>LSUIElement</key>
privatevoice.src/build/linux/privatevoice-input.desktop
@@ -1,6 +1,6 @@
[Desktop Entry]
Type=Application
Name=PrivateVoice Input
Name=PrivateVoice Dictation
Comment=Private offline voice input tool
Exec=privatevoice-input
Icon=privatevoice-input
privatevoice.src/build/windows/wails.exe.manifest
@@ -2,8 +2,8 @@
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <assemblyIdentity
    type="win32"
    name="PrivateVoice.Input"
    version="2.1.23.0"
    name="PrivateVoice.Dictation"
    version="2.1.24.0"
    processorArchitecture="*"/>
  <dependency>
    <dependentAssembly>
privatevoice.src/frontend/index.html
@@ -3,7 +3,7 @@
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>PrivateVoice Input</title>
    <title>PrivateVoice Dictation</title>
    <link rel="stylesheet" href="/src/styles/global.css" />
  </head>
  <body>
privatevoice.src/frontend/package-lock.json
@@ -1,12 +1,12 @@
{
  "name": "privatevoice-input-frontend",
  "version": "2.1.23",
  "name": "privatevoice-dictation-frontend",
  "version": "2.1.24",
  "lockfileVersion": 3,
  "requires": true,
  "packages": {
    "": {
      "name": "privatevoice-input-frontend",
      "version": "2.1.23",
      "name": "privatevoice-dictation-frontend",
      "version": "2.1.24",
      "dependencies": {
        "@wailsio/runtime": "latest"
      },
privatevoice.src/frontend/package.json
@@ -1,7 +1,7 @@
{
  "name": "privatevoice-input-frontend",
  "name": "privatevoice-dictation-frontend",
  "private": true,
  "version": "2.1.23",
  "version": "2.1.24",
  "type": "module",
  "scripts": {
    "dev": "vite dev",
privatevoice.src/frontend/src/components/settings/SettingsWindow.svelte
@@ -29,7 +29,10 @@
  <nav class="sidebar">
    <div class="sidebar-header">
      <AppIcon size={24} />
      <span class="app-name">{t('app.name')}</span>
      <div class="brand-copy">
        <span class="brand-name">{t('app.brandName')}</span>
        <span class="brand-tagline">{t('app.brandTagline')}</span>
      </div>
    </div>
    <div class="nav-items">
@@ -117,9 +120,24 @@
    -webkit-app-region: no-drag;
  }
  .app-name {
  .brand-copy {
    display: flex;
    min-width: 0;
    flex-direction: column;
    gap: 2px;
  }
  .brand-name {
    font-weight: 600;
    font-size: var(--font-size-lg);
    line-height: 1.15;
    color: var(--color-label);
  }
  .brand-tagline {
    font-size: var(--font-size-xs);
    line-height: 1.2;
    color: var(--color-secondary-label);
  }
  .nav-items {
privatevoice.src/frontend/src/components/shared/AppIcon.svelte
@@ -9,7 +9,7 @@
  let {
    size = 56,
    label = 'PrivateVoice Input',
    label = 'PrivateVoice Dictation',
    elevated = false,
  }: Props = $props()
</script>
privatevoice.src/frontend/src/lib/i18n/en.json
@@ -1,7 +1,9 @@
{
  "app": {
    "name": "PrivateVoice Input",
    "secondaryName": "私语输入"
    "name": "PrivateVoice Dictation",
    "brandName": "PrivateVoice",
    "brandTagline": "Private. Offline.",
    "secondaryName": "Private. Offline."
  },
  "nav": {
    "home": "Home",
@@ -30,7 +32,7 @@
    "done": "Typed"
  },
  "home": {
    "tagline": "Private.Offline",
    "tagline": "Private. Offline.",
    "description": "Hold {key} to speak, release to recognize and type",
    "hotkeyLabel": "Trigger Hotkey",
    "modeHint": "Hold to record, release to type · Tap to start free talk, tap again to stop",
@@ -70,9 +72,9 @@
    "copyToClipboard": "Save Recognition to Clipboard",
    "copyToClipboardDesc": "Keep recognized text in the clipboard after input; off uses it only temporarily",
    "startAtLogin": "Start at Login",
    "startAtLoginDesc": "Launch PrivateVoice Input when you log in",
    "startAtLoginDesc": "Launch PrivateVoice Dictation when you log in",
    "hideDockIcon": "Hide Dock Icon",
    "hideDockIconDesc": "Show PrivateVoice Input only in the menu bar"
    "hideDockIconDesc": "Show PrivateVoice Dictation only in the menu bar"
  },
  "models": {
    "sensevoiceDesc": "Lightweight Chinese offline model for Chinese and mixed Chinese-English input.",
@@ -82,7 +84,7 @@
  },
  "permissions": {
    "title": "Permission Check",
    "subtitle": "PrivateVoice Input needs these permissions for recording, global hotkeys, and automatic text input",
    "subtitle": "PrivateVoice Dictation needs these permissions for recording, global hotkeys, and automatic text input",
    "refresh": "Refresh",
    "grant": "Grant",
    "granted": "Granted",
@@ -108,7 +110,7 @@
    },
    "backgroundActivity": {
      "title": "Background Activity / Login Item",
      "desc": "Starts PrivateVoice Input after login and allows it to run as a menu bar app in the background; it does not affect the currently running voice input."
      "desc": "Starts PrivateVoice Dictation after login and allows it to run as a menu bar app in the background; it does not affect the currently running voice input."
    }
  },
  "hotkeys": {
@@ -132,13 +134,13 @@
    "checkingUpdate": "Checking...",
    "isLatestVersion": "Up to date",
    "checkFailed": "Check failed",
    "tagline": "Private.Offline",
    "slogan": "Private.Offline",
    "tagline": "Private. Offline.",
    "slogan": "Private. Offline.",
    "legalText": "This app is a secondary development based on the open-source VoiceSnap project and follows the MIT License.",
    "legalDetails": "For complete copyright notices, license text, and improvement details, visit:",
    "supportUrl": "https://shanghai3168.github.io/privatevoice-support/",
    "openSupport": "Open copyright and license details",
    "copyright": "© {year} PrivateVoice Input · MIT License"
    "copyright": "© {year} PrivateVoice Dictation · MIT License"
  },
  "history": {
    "title": "Recognition History",
@@ -198,7 +200,7 @@
    "from": "Recognized As",
    "to": "Replace With",
    "fromPlaceholder": "e.g. voice snap",
    "toPlaceholder": "e.g. PrivateVoice Input",
    "toPlaceholder": "e.g. PrivateVoice Dictation",
    "add": "Add",
    "edit": "Edit",
    "save": "Save",
privatevoice.src/frontend/src/lib/i18n/zh.json
@@ -1,7 +1,9 @@
{
  "app": {
    "name": "私语输入",
    "secondaryName": "PrivateVoice Input"
    "name": "PrivateVoice Dictation",
    "brandName": "PrivateVoice",
    "brandTagline": "Private. Offline.",
    "secondaryName": "Private. Offline."
  },
  "nav": {
    "home": "首页",
@@ -70,9 +72,9 @@
    "copyToClipboard": "识别内容保存到剪贴板",
    "copyToClipboardDesc": "输入文字后仍保留在剪贴板,关闭后仅临时用于上屏",
    "startAtLogin": "开机自启动",
    "startAtLoginDesc": "登录系统时自动启动私语输入",
    "startAtLoginDesc": "登录系统时自动启动 PrivateVoice Dictation",
    "hideDockIcon": "隐藏 Dock 图标",
    "hideDockIconDesc": "只在菜单栏显示私语输入图标"
    "hideDockIconDesc": "只在菜单栏显示 PrivateVoice Dictation 图标"
  },
  "models": {
    "sensevoiceDesc": "轻量中文离线模型,适合中文和中英混输。",
@@ -82,7 +84,7 @@
  },
  "permissions": {
    "title": "权限检查",
    "subtitle": "私语输入需要这些权限才能稳定完成录音、全局热键和自动上屏",
    "subtitle": "PrivateVoice Dictation 需要这些权限才能稳定完成录音、全局热键和自动上屏",
    "refresh": "刷新",
    "grant": "去授权",
    "granted": "已授权",
@@ -104,11 +106,11 @@
    },
    "inputMonitoring": {
      "title": "输入监控",
      "desc": "用于在私语输入窗口不可见、其他 App 正在前台时监听右 Alt 全局热键。"
      "desc": "用于在 PrivateVoice Dictation 窗口不可见、其他 App 正在前台时监听右 Alt 全局热键。"
    },
    "backgroundActivity": {
      "title": "后台活动 / 登录项",
      "desc": "用于登录系统后自动启动私语输入,并允许它作为菜单栏应用在后台运行;不影响当前已经打开的语音输入。"
      "desc": "用于登录系统后自动启动 PrivateVoice Dictation,并允许它作为菜单栏应用在后台运行;不影响当前已经打开的语音输入。"
    }
  },
  "hotkeys": {
@@ -133,12 +135,12 @@
    "isLatestVersion": "已是最新版本",
    "checkFailed": "检查失败",
    "tagline": "永远离线·稳定极速",
    "slogan": "Private.Offline",
    "slogan": "Private. Offline.",
    "legalText": "本应用基于开源项目 VoiceSnap 进行二次开发,遵循 MIT License。",
    "legalDetails": "完整版权声明、许可文本及改进详情,请访问:",
    "supportUrl": "https://shanghai3168.github.io/privatevoice-support/",
    "openSupport": "打开版权与许可说明",
    "copyright": "© {year} PrivateVoice Input · MIT License"
    "copyright": "© {year} PrivateVoice Dictation · MIT License"
  },
  "history": {
    "title": "识别历史",
@@ -198,7 +200,7 @@
    "from": "识别结果",
    "to": "替换为",
    "fromPlaceholder": "例如:私语输入",
    "toPlaceholder": "例如:PrivateVoice Input",
    "toPlaceholder": "例如:PrivateVoice Dictation",
    "add": "添加",
    "edit": "编辑",
    "save": "保存",
privatevoice.src/internal/hotkey/hotkey_darwin.go
@@ -151,7 +151,7 @@
    if (g_activityToken != nil) return;
    g_activityToken = [[NSProcessInfo processInfo]
        beginActivityWithOptions:NSActivityUserInitiatedAllowingIdleSystemSleep
        reason:@"PrivateVoice Input global hotkey listener"];
        reason:@"PrivateVoice Dictation global hotkey listener"];
}
static void* eventTapThreadMain(void* arg) {
@@ -332,7 +332,7 @@
    C.beginHotkeyActivity()
    trusted := C.ensureAccessibility()
    if trusted == 0 {
        logger.Info("Accessibility permission not granted for current app identity — hotkey won't work until PrivateVoice Input is removed and re-added in System Settings > Privacy & Security > Accessibility")
        logger.Info("Accessibility permission not granted for current app identity — hotkey won't work until PrivateVoice Dictation is removed and re-added in System Settings > Privacy & Security > Accessibility")
    } else {
        logger.Info("Accessibility permission granted")
    }
privatevoice.src/internal/startup/startup_linux.go
@@ -10,7 +10,7 @@
const desktopEntry = `[Desktop Entry]
Type=Application
Name=PrivateVoice Input
Name=PrivateVoice Dictation
Exec=%s
Hidden=false
X-GNOME-Autostart-enabled=true
privatevoice.src/internal/startup/startup_windows.go
@@ -10,7 +10,7 @@
)
const registryKey = `SOFTWARE\Microsoft\Windows\CurrentVersion\Run`
const appName = "PrivateVoice Input"
const appName = "PrivateVoice Dictation"
var legacyAppNames = []string{"VoiceSnap"}
privatevoice.src/main.go
@@ -9,13 +9,13 @@
func main() {
    if err := paths.MigrateFromLegacyExecutableDir(); err != nil {
        os.Stderr.WriteString("PrivateVoice Input data migration failed: " + err.Error() + "\n")
        os.Stderr.WriteString("PrivateVoice Dictation data migration failed: " + err.Error() + "\n")
    }
    // Initialize logger
    logger.Init()
    exePath, _ := os.Executable()
    logger.Info("PrivateVoice Input starting... version=%s build=%s executable=%s dataDir=%s", appVersion, appBuild, exePath, paths.AppSupportDir())
    logger.Info("PrivateVoice Dictation starting... version=%s build=%s executable=%s dataDir=%s", appVersion, appBuild, exePath, paths.AppSupportDir())
    // Single instance check
    lock, err := singleinstance.Acquire()
privatevoice.src/scripts/build-appstore-developerid-macos.sh
@@ -19,7 +19,7 @@
#
set -euo pipefail
APP_NAME="PrivateVoice Input"
APP_NAME="PrivateVoice Dictation"
DEVELOPER_IDENTITY="${PRIVATEVOICE_DEVELOPER_IDENTITY:-Developer ID Application: Ningbo Zhuozhi Innovation Network Technology Co., Ltd. (3HY4G7M2AL)}"
KEYCHAIN_PROFILE="${PRIVATEVOICE_NOTARY_PROFILE:-privatevoice}"
SIGNING_KEYCHAIN="${PRIVATEVOICE_SIGNING_KEYCHAIN:-}"
privatevoice.src/scripts/build-appstore-macos.sh
@@ -12,7 +12,7 @@
#
set -euo pipefail
APP_NAME="PrivateVoice Input"
APP_NAME="PrivateVoice Dictation"
LOCAL_IDENTITY="${PRIVATEVOICE_LOCAL_SIGN_IDENTITY:-PrivateVoice Local Code Signing}"
KEYCHAIN="${PRIVATEVOICE_LOCAL_KEYCHAIN:-$HOME/Library/Keychains/login.keychain-db}"
APPSTORE_MIN_SYSTEM_VERSION="${PRIVATEVOICE_APPSTORE_MIN_SYSTEM_VERSION:-13.4}"
privatevoice.src/scripts/build-local-macos.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
#
# build-local-macos.sh - Build a locally signed macOS app and DMG for PrivateVoice Input.
# build-local-macos.sh - Build a locally signed macOS app and DMG for PrivateVoice Dictation.
#
# This script intentionally does not notarize. It creates or reuses a stable
# local Code Signing identity so macOS TCC permissions, such as Accessibility,
@@ -12,7 +12,7 @@
#
set -euo pipefail
APP_NAME="PrivateVoice Input"
APP_NAME="PrivateVoice Dictation"
DEFAULT_LOCAL_IDENTITY="PrivateVoice Local Code Signing"
LEGACY_LOCAL_IDENTITY="VoiceSnap Local Code Signing"
LOCAL_IDENTITY="${PRIVATEVOICE_LOCAL_SIGN_IDENTITY:-${VOICESNAP_LOCAL_SIGN_IDENTITY:-}}"
privatevoice.src/scripts/build-release-macos.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
#
# build-release-macos.sh — Build a signed & notarized macOS DMG for PrivateVoice Input
# build-release-macos.sh — Build a signed & notarized macOS DMG for PrivateVoice Dictation
#
# Prerequisites (one-time):
#   1. Install Developer ID certificate in Keychain
@@ -19,7 +19,7 @@
IDENTITY="Developer ID Application: Ningbo Zhuozhi Innovation Network Technology Co., Ltd. (3HY4G7M2AL)"
KEYCHAIN_PROFILE="privatevoice"
APP_NAME="PrivateVoice Input"
APP_NAME="PrivateVoice Dictation"
BUNDLE_ID="com.privatevoice.input"
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
privatevoice.src/services/app_service.go
@@ -35,7 +35,7 @@
// GetAppName returns the application name.
func (s *AppService) GetAppName() string {
    return "PrivateVoice Input"
    return "PrivateVoice Dictation"
}
// OpenURL opens a URL in the default browser.
privatevoice.src/wails.json
@@ -1,7 +1,7 @@
{
  "$schema": "https://wails.io/schemas/config.v3.json",
  "name": "PrivateVoice Input",
  "outputfilename": "PrivateVoice Input",
  "name": "PrivateVoice Dictation",
  "outputfilename": "PrivateVoice Dictation",
  "frontend:install": "npm install",
  "frontend:build": "npm run build",
  "frontend:dev:watcher": "npm run dev",