From ce96a0e5272d6bcdf732dd0fc1ff8a9d9c834a0c Mon Sep 17 00:00:00 2001
From: Ariver <shanghai3168@gmail.com>
Date: Wed, 03 Jun 2026 15:00:58 +0800
Subject: [PATCH] Fix Round 4 model download QA issues

---
 privatevoice.src/app.go |   49 +++++++++++++++++++++++++++++++++++--------------
 1 files changed, 35 insertions(+), 14 deletions(-)

diff --git a/privatevoice.src/app.go b/privatevoice.src/app.go
index 54bbc93..ae058d4 100755
--- a/privatevoice.src/app.go
+++ b/privatevoice.src/app.go
@@ -14,6 +14,7 @@
 	"voicesnap/internal/history"
 	"voicesnap/internal/hotkey"
 	"voicesnap/internal/input"
+	"voicesnap/internal/language"
 	"voicesnap/internal/logger"
 	"voicesnap/internal/overlay"
 	"voicesnap/internal/sound"
@@ -26,8 +27,8 @@
 )
 
 const (
-	appVersion        = "2.1.18"
-	appBuild          = "20260601.1905"
+	appVersion        = "2.1.21"
+	appBuild          = "20260603.1327"
 	appDisplayVersion = appVersion + " (build " + appBuild + ")"
 	appName           = "PrivateVoice Input"
 
@@ -47,6 +48,7 @@
 	cfg      *config.Config
 	recorder *audio.Recorder
 	eng      engine.Engine
+	engineMu sync.Mutex
 	hk       hotkey.Listener
 	paster   input.Paster
 	history  *history.Store
@@ -110,7 +112,7 @@
 	// Create services for Wails bindings
 	appService := services.NewAppService(app.cfg, appDisplayVersion)
 	configService := services.NewConfigService(app.cfg)
-	engineService := services.NewEngineService()
+	engineService := services.NewEngineService(app.cfg)
 	app.engineService = engineService
 	hotkeyService := services.NewHotkeyService(app.cfg)
 	permissionService := services.NewPermissionService()
@@ -186,7 +188,7 @@
 	tray.SetTemplateIcon(trayIcon)
 
 	showLabel, exitLabel := "Show Settings", "Exit"
-	if isChinese() {
+	if language.Resolve(app.cfg.LanguageMode, app.cfg.LanguageID, language.NewSystemDetector()).UILocale == "zh" {
 		showLabel, exitLabel = "显示设置", "退出"
 	}
 
@@ -596,7 +598,17 @@
 		return
 	}
 
-	text, err := a.eng.Recognize(samples)
+	a.engineMu.Lock()
+	eng := a.eng
+	if eng == nil {
+		a.engineMu.Unlock()
+		logger.Error("Recognition skipped: engine not ready")
+		a.indicator.SetStatus(overlay.StatusError, "引擎未就绪")
+		a.delayedHideIf(autoHide, 2000)
+		return
+	}
+	text, err := eng.Recognize(samples)
+	a.engineMu.Unlock()
 	if err != nil {
 		logger.Error("Recognition failed: %v", err)
 		a.indicator.SetStatus(overlay.StatusError, "错误")
@@ -686,6 +698,7 @@
 	eng, err := engine.New()
 	if err != nil {
 		logger.Error("Engine initialization failed: %v", err)
+		a.replaceEngine(nil)
 		status := "need_model"
 		if modelExists {
 			status = "error"
@@ -700,9 +713,7 @@
 		return
 	}
 
-	a.mu.Lock()
-	a.eng = eng
-	a.mu.Unlock()
+	a.replaceEngine(eng)
 
 	logger.Info("ASR engine ready: %s", eng.HardwareInfo())
 	if a.engineService != nil {
@@ -727,6 +738,20 @@
 	a.indicator.SetStatus(overlay.StatusReady, hotkeyReadyText(keyName, hotkeyMode))
 	a.indicator.Show()
 	a.delayedHideIf(autoHide, 2000)
+}
+
+func (a *App) replaceEngine(eng engine.Engine) {
+	a.engineMu.Lock()
+	defer a.engineMu.Unlock()
+
+	a.mu.Lock()
+	old := a.eng
+	a.eng = eng
+	a.mu.Unlock()
+
+	if old != nil && old != eng {
+		old.Close()
+	}
 }
 
 func hotkeyReadyText(keyName, mode string) string {
@@ -910,9 +935,7 @@
 	if a.recorder != nil {
 		a.recorder.Close()
 	}
-	if a.eng != nil {
-		a.eng.Close()
-	}
+	a.replaceEngine(nil)
 	a.wg.Wait()
 	logger.Info("Cleanup complete")
 }
@@ -945,7 +968,5 @@
 
 // SetEngine sets the engine after model download.
 func (a *App) SetEngine(eng engine.Engine) {
-	a.mu.Lock()
-	defer a.mu.Unlock()
-	a.eng = eng
+	a.replaceEngine(eng)
 }

--
Gitblit v1.9.3