Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,10 @@ AI页配置 OpenAI-compatible endpoint、model、API key、超时、SSE与thinki

若端点不在本机,转写文本会发送到该接口;语音编辑还会发送当前应用提供的 surrounding text、光标与选区。

### Linux 应用菜单

完成用户安装或系统包的用户激活后,可从应用菜单搜索「VoCoType 设置」,直接打开设置中心。

### Playground、诊断与设置中心

Linux使用 GTK 3/C++设置中心,macOS使用 AppKit原生设置中心。两端均覆盖模型、麦克风、AI、术语、诊断和教程;macOS另外负责首次安装/升级 InputMethodKit组件。设置文本区域支持系统原生 `⌘Z`,同时兼容 `Ctrl+Z`撤销和对应重做快捷键。
Expand Down
6 changes: 6 additions & 0 deletions packaging/scripts/stage-system-package.sh
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,12 @@ install -Dm755 "$PROJECT_DIR/scripts/install/common/install-native-user.sh" \
install -Dm755 "$PROJECT_DIR/scripts/install/common/uninstall-native-user.sh" \
"$source_root/scripts/install/common/uninstall-native-user.sh"

install -Dm644 "$PROJECT_DIR/scripts/install/common/desktop-integration.sh" \
"$source_root/scripts/install/common/desktop-integration.sh"
install -Dm644 "$PROJECT_DIR/resources/desktop/io.github.LeonardNJU.VoCoType.Settings.desktop" \
"$source_root/resources/desktop/io.github.LeonardNJU.VoCoType.Settings.desktop"
install -Dm644 "$PROJECT_DIR/web/icon-192.png" "$source_root/web/icon-192.png"

# Compile the desktop/runtime-facing programs for the target distribution.
cmake -S "$PROJECT_DIR/src/desktop" -B "$DESKTOP_BUILD" \
-DCMAKE_BUILD_TYPE=Release \
Expand Down
58 changes: 58 additions & 0 deletions scripts/install/common/desktop-integration.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#!/usr/bin/env bash
# Shared by source installs and per-user activation of system packages.
# shellcheck shell=bash

desktop_exec_path() {
local value=$1
value=${value//\\/\\\\}
value=${value//\"/\\\"}
value=${value//\$/\\\$}
value=${value//\`/\\\`}
value=${value//%/%%}
# Desktop Entry string escaping is applied before Exec argument unquoting.
value=${value//\\/\\\\}
printf '"%s"' "$value"
}

desktop_string_value() {
local value=$1
value=${value//\\/\\\\}
value=${value//$'\n'/\\n}
value=${value//$'\r'/\\r}
value=${value//$'\t'/\\t}
printf '%s' "$value"
}

install_desktop_entries() {
local root=$1 settings=$2
local data="${XDG_DATA_HOME:-$HOME/.local/share}"
local desktop=io.github.LeonardNJU.VoCoType.Settings.desktop
local icon="$data/icons/hicolor/192x192/apps/vocotype.png"
mkdir -p "$data/applications" "$data/icons/hicolor/192x192/apps"
install -m644 "$root/web/icon-192.png" "$icon"
# Use an absolute Icon path so KDE does not need a refreshed icon-theme cache.
# The configured command must work even when ~/.local/bin is absent from PATH.
# env also avoids GLib testing an unexpanded %% in the executable filename.
while IFS= read -r line; do
case "$line" in
Icon=*) printf 'Icon=%s\n' "$(desktop_string_value "$icon")" ;;
Exec=*) printf 'Exec=/usr/bin/env %s\n' "$(desktop_exec_path "$settings")" ;;
*) printf '%s\n' "$line" ;;
esac
done < "$root/resources/desktop/$desktop" > "$data/applications/$desktop"
if command -v update-desktop-database >/dev/null 2>&1; then
update-desktop-database "$data/applications" >/dev/null 2>&1 || true
fi
if command -v gtk-update-icon-cache >/dev/null 2>&1; then
gtk-update-icon-cache -f -t "$data/icons/hicolor" >/dev/null 2>&1 || true
fi
}

remove_desktop_entries() {
local data="${XDG_DATA_HOME:-$HOME/.local/share}"
command rm -f "$data/applications/io.github.LeonardNJU.VoCoType.Settings.desktop" \
"$data/icons/hicolor/192x192/apps/vocotype.png"
if command -v update-desktop-database >/dev/null 2>&1; then
update-desktop-database "$data/applications" >/dev/null 2>&1 || true
fi
}
4 changes: 4 additions & 0 deletions scripts/install/common/install-native-user.sh
Original file line number Diff line number Diff line change
Expand Up @@ -455,4 +455,8 @@ case "$FRAMEWORK" in
universal) install_fcitx; install_ibus ;;
esac
cleanup_legacy_runtime
# Both source and package activation install a discoverable settings entry.
. "$SCRIPT_DIR/desktop-integration.sh"
install_desktop_entries "$PROJECT_DIR" "$USER_BIN/vocotype-settings"
log "The VoCoType settings entry is installed in the application menu."
log "✓ Native-only runtime installed. Configuration and model caches were preserved."
4 changes: 3 additions & 1 deletion scripts/install/common/uninstall-native-user.sh
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,9 @@ if [[ "$PURGE_RUNTIME" == true ]]; then
rm -rf "$HOME/.local/lib/vocotype-native" "$HOME/.local/lib/vocotype-streaming"
fi
if ! fcitx_present && ! ibus_present; then
rm -f "$HOME/.local/bin/vocotype-settings"
. "$SCRIPT_DIR/desktop-integration.sh"
remove_desktop_entries
command rm -f "$HOME/.local/bin/vocotype-settings"
fi
if [[ "$REMOVE_USER_DATA" == true ]]; then
rm -rf "${XDG_CONFIG_HOME:-$HOME/.config}/vocotype"
Expand Down
37 changes: 37 additions & 0 deletions scripts/test/desktop-integration.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)

export TEST_DESKTOP_DIR
TEST_DESKTOP_DIR=$(mktemp -d)
trap 'command rm -rf "$TEST_DESKTOP_DIR"' EXIT
export XDG_DATA_HOME="$TEST_DESKTOP_DIR/data" XDG_CONFIG_HOME="$TEST_DESKTOP_DIR/config"
export XDG_CACHE_HOME="$TEST_DESKTOP_DIR/cache"
# Keep the test desktop isolated from the real session.
export XDG_RUNTIME_DIR="$TEST_DESKTOP_DIR/runtime"
mkdir -m700 "$XDG_RUNTIME_DIR"
export GTK_USE_PORTAL=0 NO_AT_BRIDGE=1 GSETTINGS_BACKEND=memory
. "$ROOT/scripts/install/common/desktop-integration.sh"
# Exercise Exec quoting instead of assuming the home directory has no spaces,
# percent field codes, backslashes, quotes, or shell metacharacters.
# shellcheck disable=SC1003
launcher="$TEST_DESKTOP_DIR/"'settings space % $ ` " \'
# The child launcher expands the exported test path when invoked.
# shellcheck disable=SC2016
printf '#!/usr/bin/env bash\ntouch "$TEST_DESKTOP_DIR/launched"\n' > "$launcher"
chmod +x "$launcher"
install_desktop_entries "$ROOT" "$launcher"
settings="$XDG_DATA_HOME/applications/io.github.LeonardNJU.VoCoType.Settings.desktop"
desktop-file-validate "$settings"
grep -Fxq "Icon=$XDG_DATA_HOME/icons/hicolor/192x192/apps/vocotype.png" "$settings"
cmp "$ROOT/web/icon-192.png" "$XDG_DATA_HOME/icons/hicolor/192x192/apps/vocotype.png"
timeout 10 dbus-run-session -- gio launch "$settings"
for _ in {1..50}; do
[[ -f "$TEST_DESKTOP_DIR/launched" ]] && break
sleep 0.1
done
[[ -f "$TEST_DESKTOP_DIR/launched" ]]
remove_desktop_entries
[[ ! -e "$settings" ]]
[[ ! -e "$XDG_DATA_HOME/icons/hicolor/192x192/apps/vocotype.png" ]]
printf 'Application menu installation, launch, and uninstall: PASS\n'