mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-04-16 15:20:39 +08:00
fix: handle edge cases and add missing i18n
This commit is contained in:
parent
05fba11baa
commit
b7ae5f0ac9
@ -26,6 +26,11 @@ notifications:
|
|||||||
appHidden:
|
appHidden:
|
||||||
title: تم إخفاء التطبيق
|
title: تم إخفاء التطبيق
|
||||||
body: Clash Verge يعمل في الخلفية.
|
body: Clash Verge يعمل في الخلفية.
|
||||||
|
updateReady:
|
||||||
|
title: Clash Verge Update
|
||||||
|
body: A new version (v{version}) has been downloaded and is ready to install.
|
||||||
|
installNow: Install Now
|
||||||
|
later: Later
|
||||||
service:
|
service:
|
||||||
adminInstallPrompt: يتطلب تثبيت خدمة Clash Verge صلاحيات المسؤول.
|
adminInstallPrompt: يتطلب تثبيت خدمة Clash Verge صلاحيات المسؤول.
|
||||||
adminUninstallPrompt: يتطلب إلغاء تثبيت خدمة Clash Verge صلاحيات المسؤول.
|
adminUninstallPrompt: يتطلب إلغاء تثبيت خدمة Clash Verge صلاحيات المسؤول.
|
||||||
|
|||||||
@ -26,6 +26,11 @@ notifications:
|
|||||||
appHidden:
|
appHidden:
|
||||||
title: Anwendung ausgeblendet
|
title: Anwendung ausgeblendet
|
||||||
body: Clash Verge läuft im Hintergrund.
|
body: Clash Verge läuft im Hintergrund.
|
||||||
|
updateReady:
|
||||||
|
title: Clash Verge Update
|
||||||
|
body: A new version (v{version}) has been downloaded and is ready to install.
|
||||||
|
installNow: Install Now
|
||||||
|
later: Later
|
||||||
service:
|
service:
|
||||||
adminInstallPrompt: Für die Installation des Clash-Verge-Dienstes sind Administratorrechte erforderlich.
|
adminInstallPrompt: Für die Installation des Clash-Verge-Dienstes sind Administratorrechte erforderlich.
|
||||||
adminUninstallPrompt: Für die Deinstallation des Clash-Verge-Dienstes sind Administratorrechte erforderlich.
|
adminUninstallPrompt: Für die Deinstallation des Clash-Verge-Dienstes sind Administratorrechte erforderlich.
|
||||||
|
|||||||
@ -26,6 +26,11 @@ notifications:
|
|||||||
appHidden:
|
appHidden:
|
||||||
title: Application Hidden
|
title: Application Hidden
|
||||||
body: Clash Verge is running in the background.
|
body: Clash Verge is running in the background.
|
||||||
|
updateReady:
|
||||||
|
title: Clash Verge Update
|
||||||
|
body: A new version (v{version}) has been downloaded and is ready to install.
|
||||||
|
installNow: Install Now
|
||||||
|
later: Later
|
||||||
service:
|
service:
|
||||||
adminInstallPrompt: Installing the Clash Verge service requires administrator privileges.
|
adminInstallPrompt: Installing the Clash Verge service requires administrator privileges.
|
||||||
adminUninstallPrompt: Uninstalling the Clash Verge service requires administrator privileges.
|
adminUninstallPrompt: Uninstalling the Clash Verge service requires administrator privileges.
|
||||||
|
|||||||
@ -26,6 +26,11 @@ notifications:
|
|||||||
appHidden:
|
appHidden:
|
||||||
title: Aplicación oculta
|
title: Aplicación oculta
|
||||||
body: Clash Verge se está ejecutando en segundo plano.
|
body: Clash Verge se está ejecutando en segundo plano.
|
||||||
|
updateReady:
|
||||||
|
title: Clash Verge Update
|
||||||
|
body: A new version (v{version}) has been downloaded and is ready to install.
|
||||||
|
installNow: Install Now
|
||||||
|
later: Later
|
||||||
service:
|
service:
|
||||||
adminInstallPrompt: Instalar el servicio de Clash Verge requiere privilegios de administrador.
|
adminInstallPrompt: Instalar el servicio de Clash Verge requiere privilegios de administrador.
|
||||||
adminUninstallPrompt: Desinstalar el servicio de Clash Verge requiere privilegios de administrador.
|
adminUninstallPrompt: Desinstalar el servicio de Clash Verge requiere privilegios de administrador.
|
||||||
|
|||||||
@ -26,6 +26,11 @@ notifications:
|
|||||||
appHidden:
|
appHidden:
|
||||||
title: برنامه پنهان شد
|
title: برنامه پنهان شد
|
||||||
body: Clash Verge در پسزمینه در حال اجراست.
|
body: Clash Verge در پسزمینه در حال اجراست.
|
||||||
|
updateReady:
|
||||||
|
title: Clash Verge Update
|
||||||
|
body: A new version (v{version}) has been downloaded and is ready to install.
|
||||||
|
installNow: Install Now
|
||||||
|
later: Later
|
||||||
service:
|
service:
|
||||||
adminInstallPrompt: نصب سرویس Clash Verge به دسترسی مدیر نیاز دارد.
|
adminInstallPrompt: نصب سرویس Clash Verge به دسترسی مدیر نیاز دارد.
|
||||||
adminUninstallPrompt: حذف سرویس Clash Verge به دسترسی مدیر نیاز دارد.
|
adminUninstallPrompt: حذف سرویس Clash Verge به دسترسی مدیر نیاز دارد.
|
||||||
|
|||||||
@ -26,6 +26,11 @@ notifications:
|
|||||||
appHidden:
|
appHidden:
|
||||||
title: Aplikasi Disembunyikan
|
title: Aplikasi Disembunyikan
|
||||||
body: Clash Verge berjalan di latar belakang.
|
body: Clash Verge berjalan di latar belakang.
|
||||||
|
updateReady:
|
||||||
|
title: Clash Verge Update
|
||||||
|
body: A new version (v{version}) has been downloaded and is ready to install.
|
||||||
|
installNow: Install Now
|
||||||
|
later: Later
|
||||||
service:
|
service:
|
||||||
adminInstallPrompt: Menginstal layanan Clash Verge memerlukan hak administrator.
|
adminInstallPrompt: Menginstal layanan Clash Verge memerlukan hak administrator.
|
||||||
adminUninstallPrompt: Menghapus instalasi layanan Clash Verge memerlukan hak administrator.
|
adminUninstallPrompt: Menghapus instalasi layanan Clash Verge memerlukan hak administrator.
|
||||||
|
|||||||
@ -26,6 +26,11 @@ notifications:
|
|||||||
appHidden:
|
appHidden:
|
||||||
title: アプリが非表示
|
title: アプリが非表示
|
||||||
body: Clash Verge はバックグラウンドで実行中です。
|
body: Clash Verge はバックグラウンドで実行中です。
|
||||||
|
updateReady:
|
||||||
|
title: Clash Verge Update
|
||||||
|
body: A new version (v{version}) has been downloaded and is ready to install.
|
||||||
|
installNow: Install Now
|
||||||
|
later: Later
|
||||||
service:
|
service:
|
||||||
adminInstallPrompt: Clash Verge サービスのインストールには管理者権限が必要です。
|
adminInstallPrompt: Clash Verge サービスのインストールには管理者権限が必要です。
|
||||||
adminUninstallPrompt: Clash Verge サービスのアンインストールには管理者権限が必要です。
|
adminUninstallPrompt: Clash Verge サービスのアンインストールには管理者権限が必要です。
|
||||||
|
|||||||
@ -26,6 +26,11 @@ notifications:
|
|||||||
appHidden:
|
appHidden:
|
||||||
title: 앱이 숨겨짐
|
title: 앱이 숨겨짐
|
||||||
body: Clash Verge가 백그라운드에서 실행 중입니다.
|
body: Clash Verge가 백그라운드에서 실행 중입니다.
|
||||||
|
updateReady:
|
||||||
|
title: Clash Verge Update
|
||||||
|
body: A new version (v{version}) has been downloaded and is ready to install.
|
||||||
|
installNow: Install Now
|
||||||
|
later: Later
|
||||||
service:
|
service:
|
||||||
adminInstallPrompt: Clash Verge 서비스 설치에는 관리자 권한이 필요합니다.
|
adminInstallPrompt: Clash Verge 서비스 설치에는 관리자 권한이 필요합니다.
|
||||||
adminUninstallPrompt: Clash Verge 서비스 제거에는 관리자 권한이 필요합니다.
|
adminUninstallPrompt: Clash Verge 서비스 제거에는 관리자 권한이 필요합니다.
|
||||||
|
|||||||
@ -26,6 +26,11 @@ notifications:
|
|||||||
appHidden:
|
appHidden:
|
||||||
title: Приложение скрыто
|
title: Приложение скрыто
|
||||||
body: Clash Verge работает в фоновом режиме.
|
body: Clash Verge работает в фоновом режиме.
|
||||||
|
updateReady:
|
||||||
|
title: Clash Verge Update
|
||||||
|
body: A new version (v{version}) has been downloaded and is ready to install.
|
||||||
|
installNow: Install Now
|
||||||
|
later: Later
|
||||||
service:
|
service:
|
||||||
adminInstallPrompt: Для установки службы Clash Verge требуются права администратора.
|
adminInstallPrompt: Для установки службы Clash Verge требуются права администратора.
|
||||||
adminUninstallPrompt: Для удаления службы Clash Verge требуются права администратора.
|
adminUninstallPrompt: Для удаления службы Clash Verge требуются права администратора.
|
||||||
|
|||||||
@ -26,6 +26,11 @@ notifications:
|
|||||||
appHidden:
|
appHidden:
|
||||||
title: Uygulama Gizlendi
|
title: Uygulama Gizlendi
|
||||||
body: Clash Verge arka planda çalışıyor.
|
body: Clash Verge arka planda çalışıyor.
|
||||||
|
updateReady:
|
||||||
|
title: Clash Verge Update
|
||||||
|
body: A new version (v{version}) has been downloaded and is ready to install.
|
||||||
|
installNow: Install Now
|
||||||
|
later: Later
|
||||||
service:
|
service:
|
||||||
adminInstallPrompt: Clash Verge hizmetini kurmak için yönetici ayrıcalıkları gerekir.
|
adminInstallPrompt: Clash Verge hizmetini kurmak için yönetici ayrıcalıkları gerekir.
|
||||||
adminUninstallPrompt: Clash Verge hizmetini kaldırmak için yönetici ayrıcalıkları gerekir.
|
adminUninstallPrompt: Clash Verge hizmetini kaldırmak için yönetici ayrıcalıkları gerekir.
|
||||||
|
|||||||
@ -26,6 +26,11 @@ notifications:
|
|||||||
appHidden:
|
appHidden:
|
||||||
title: Кушымта яшерелде
|
title: Кушымта яшерелде
|
||||||
body: Clash Verge фон режимында эшли.
|
body: Clash Verge фон режимында эшли.
|
||||||
|
updateReady:
|
||||||
|
title: Clash Verge Update
|
||||||
|
body: A new version (v{version}) has been downloaded and is ready to install.
|
||||||
|
installNow: Install Now
|
||||||
|
later: Later
|
||||||
service:
|
service:
|
||||||
adminInstallPrompt: Clash Verge хезмәтен урнаштыру өчен администратор хокуклары кирәк.
|
adminInstallPrompt: Clash Verge хезмәтен урнаштыру өчен администратор хокуклары кирәк.
|
||||||
adminUninstallPrompt: Clash Verge хезмәтен бетерү өчен администратор хокуклары кирәк.
|
adminUninstallPrompt: Clash Verge хезмәтен бетерү өчен администратор хокуклары кирәк.
|
||||||
|
|||||||
@ -26,6 +26,11 @@ notifications:
|
|||||||
appHidden:
|
appHidden:
|
||||||
title: 应用已隐藏
|
title: 应用已隐藏
|
||||||
body: Clash Verge 正在后台运行。
|
body: Clash Verge 正在后台运行。
|
||||||
|
updateReady:
|
||||||
|
title: Clash Verge 更新
|
||||||
|
body: 新版本 (v{version}) 已下载完成,是否立即安装?
|
||||||
|
installNow: 立即安装
|
||||||
|
later: 稍后
|
||||||
service:
|
service:
|
||||||
adminInstallPrompt: 安装 Clash Verge 服务需要管理员权限
|
adminInstallPrompt: 安装 Clash Verge 服务需要管理员权限
|
||||||
adminUninstallPrompt: 卸载 Clash Verge 服务需要管理员权限
|
adminUninstallPrompt: 卸载 Clash Verge 服务需要管理员权限
|
||||||
|
|||||||
@ -26,6 +26,11 @@ notifications:
|
|||||||
appHidden:
|
appHidden:
|
||||||
title: 應用已隱藏
|
title: 應用已隱藏
|
||||||
body: Clash Verge 正在背景執行。
|
body: Clash Verge 正在背景執行。
|
||||||
|
updateReady:
|
||||||
|
title: Clash Verge Update
|
||||||
|
body: A new version (v{version}) has been downloaded and is ready to install.
|
||||||
|
installNow: Install Now
|
||||||
|
later: Later
|
||||||
service:
|
service:
|
||||||
adminInstallPrompt: 安裝 Clash Verge 服務需要管理員權限
|
adminInstallPrompt: 安裝 Clash Verge 服務需要管理員權限
|
||||||
adminUninstallPrompt: 卸载 Clash Verge 服務需要管理員權限
|
adminUninstallPrompt: 卸载 Clash Verge 服務需要管理員權限
|
||||||
|
|||||||
@ -158,11 +158,18 @@ impl SilentUpdater {
|
|||||||
logging!(
|
logging!(
|
||||||
info,
|
info,
|
||||||
Type::System,
|
Type::System,
|
||||||
"Update cache version ({}) > current ({}), attempting startup install",
|
"Update cache version ({}) > current ({}), asking user to install",
|
||||||
cached_version,
|
cached_version,
|
||||||
current_version
|
current_version
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Ask user for confirmation — they can skip and use the app normally.
|
||||||
|
// The cache is preserved so next launch will ask again.
|
||||||
|
if !Self::ask_user_to_install(app_handle, cached_version).await {
|
||||||
|
logging!(info, Type::System, "User skipped update install, starting normally");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Read cached bytes
|
// Read cached bytes
|
||||||
let bytes = match Self::read_cache_bytes() {
|
let bytes = match Self::read_cache_bytes() {
|
||||||
Ok(b) => b,
|
Ok(b) => b,
|
||||||
@ -177,8 +184,8 @@ impl SilentUpdater {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Need a fresh Update object from the server to call install()
|
// Need a fresh Update object from the server to call install().
|
||||||
// Network should be available at startup (user just booted)
|
// This is a lightweight HTTP request (< 1s), not a re-download.
|
||||||
let update = match app_handle.updater() {
|
let update = match app_handle.updater() {
|
||||||
Ok(updater) => match updater.check().await {
|
Ok(updater) => match updater.check().await {
|
||||||
Ok(Some(u)) => u,
|
Ok(Some(u)) => u,
|
||||||
@ -210,6 +217,20 @@ impl SilentUpdater {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Verify the server's version matches the cached version.
|
||||||
|
// If server now has a newer version, our cached bytes are stale.
|
||||||
|
if update.version != *cached_version {
|
||||||
|
logging!(
|
||||||
|
info,
|
||||||
|
Type::System,
|
||||||
|
"Server version ({}) != cached version ({}), cache is stale, cleaning up",
|
||||||
|
update.version,
|
||||||
|
cached_version
|
||||||
|
);
|
||||||
|
Self::delete_cache();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
let version = update.version.clone();
|
let version = update.version.clone();
|
||||||
logging!(info, Type::System, "Installing cached update v{version} at startup...");
|
logging!(info, Type::System, "Installing cached update v{version} at startup...");
|
||||||
|
|
||||||
@ -231,18 +252,15 @@ impl SilentUpdater {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
Ok(Ok(Err(e))) => {
|
Ok(Ok(Err(e))) => {
|
||||||
logging!(warn, Type::System, "Startup install failed: {e}, cleaning up");
|
logging!(warn, Type::System, "Startup install failed: {e}, will retry next launch");
|
||||||
Self::delete_cache();
|
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
Ok(Err(e)) => {
|
Ok(Err(e)) => {
|
||||||
logging!(warn, Type::System, "Startup install task panicked: {e}, cleaning up");
|
logging!(warn, Type::System, "Startup install task panicked: {e}, will retry next launch");
|
||||||
Self::delete_cache();
|
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
logging!(warn, Type::System, "Startup install timed out (30s), cleaning up");
|
logging!(warn, Type::System, "Startup install timed out (30s), will retry next launch");
|
||||||
Self::delete_cache();
|
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -256,6 +274,36 @@ impl SilentUpdater {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ─── User Confirmation Dialog ────────────────────────────────────────────────
|
||||||
|
|
||||||
|
impl SilentUpdater {
|
||||||
|
/// Show a native dialog asking the user to install or skip the update.
|
||||||
|
/// Returns true if user chose to install, false if they chose to skip.
|
||||||
|
async fn ask_user_to_install(app_handle: &tauri::AppHandle, version: &str) -> bool {
|
||||||
|
use tauri_plugin_dialog::{DialogExt as _, MessageDialogButtons, MessageDialogKind};
|
||||||
|
|
||||||
|
let title = clash_verge_i18n::t!("notifications.updateReady.title").to_string();
|
||||||
|
let body = clash_verge_i18n::t!("notifications.updateReady.body")
|
||||||
|
.replace("{version}", version);
|
||||||
|
let install_now = clash_verge_i18n::t!("notifications.updateReady.installNow").to_string();
|
||||||
|
let later = clash_verge_i18n::t!("notifications.updateReady.later").to_string();
|
||||||
|
|
||||||
|
let (tx, rx) = tokio::sync::oneshot::channel();
|
||||||
|
|
||||||
|
app_handle
|
||||||
|
.dialog()
|
||||||
|
.message(body)
|
||||||
|
.title(title)
|
||||||
|
.buttons(MessageDialogButtons::OkCancelCustom(install_now, later))
|
||||||
|
.kind(MessageDialogKind::Info)
|
||||||
|
.show(move |confirmed| {
|
||||||
|
let _ = tx.send(confirmed);
|
||||||
|
});
|
||||||
|
|
||||||
|
rx.await.unwrap_or(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ─── Update Splash Window ────────────────────────────────────────────────────
|
// ─── Update Splash Window ────────────────────────────────────────────────────
|
||||||
|
|
||||||
impl SilentUpdater {
|
impl SilentUpdater {
|
||||||
@ -513,7 +561,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_cache_meta_missing_field() {
|
fn test_cache_meta_missing_required_field() {
|
||||||
let result = serde_json::from_str::<UpdateCacheMeta>(r#"{"version":"2.5.0"}"#);
|
let result = serde_json::from_str::<UpdateCacheMeta>(r#"{"version":"2.5.0"}"#);
|
||||||
assert!(result.is_err()); // missing downloaded_at
|
assert!(result.is_err()); // missing downloaded_at
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user