feat(desktop): тихая установка обновления по флагу --update-now
Установка обновления всегда спрашивала согласие диалогом, поэтому сквозная проверка «поверх старой версии» не автоматизировалась (в headless-прогоне кликнуть некому), а на управляемых машинах обновление ставит оператор, а не пользователь. С флагом `--update-now` обёртка проверяет обновление сразу при старте (не через 30 секунд) и ставит найденное без диалога, после чего перезапускается; при отсутствии обновления работает как обычно. По умолчанию флаг выключен — трей, страница настроек и фоновая проверка по-прежнему спрашивают согласие. Подпись артефакта проверяется в обоих режимах: флаг убирает вопрос, но не проверку. Ход тихого обновления виден в журнале, а в строку запуска добавлена версия сборки — иначе после перезапуска не понять, какая версия работает. Решение — D-077, приёмка — desktop/README.md («Локальная проверка»).
This commit is contained in:
@@ -28,7 +28,9 @@ const UPDATE_PATH: &str = "/updates/{{target}}/{{arch}}/{{current_version}}";
|
||||
|
||||
/// Проверяет обновления. `interactive` — вызов из меню трея или настроек,
|
||||
/// тогда пользователь видит результат в диалоге; фоновая проверка молчит.
|
||||
pub async fn check<R: Runtime>(app: AppHandle<R>, interactive: bool) {
|
||||
/// `auto_install` — тихий режим (`--update-now`): найденное обновление ставится
|
||||
/// без вопроса, диалогов нет вовсе.
|
||||
pub async fn check<R: Runtime>(app: AppHandle<R>, interactive: bool, auto_install: bool) {
|
||||
if UPDATER_PUBKEY.is_empty() {
|
||||
log::info!("автообновление не настроено: в сборке нет публичного ключа подписи");
|
||||
if interactive {
|
||||
@@ -82,7 +84,7 @@ pub async fn check<R: Runtime>(app: AppHandle<R>, interactive: bool) {
|
||||
version: version.clone(),
|
||||
},
|
||||
);
|
||||
prompt_install(app, update, version).await;
|
||||
prompt_install(app, update, version, auto_install).await;
|
||||
}
|
||||
Ok(None) => {
|
||||
log::info!("обновлений нет");
|
||||
@@ -108,32 +110,42 @@ pub async fn check<R: Runtime>(app: AppHandle<R>, interactive: bool) {
|
||||
}
|
||||
}
|
||||
|
||||
/// Спрашивает согласие и устанавливает обновление.
|
||||
/// Спрашивает согласие и устанавливает обновление (в тихом режиме — сразу).
|
||||
async fn prompt_install<R: Runtime>(
|
||||
app: AppHandle<R>,
|
||||
update: tauri_plugin_updater::Update,
|
||||
version: String,
|
||||
auto_install: bool,
|
||||
) {
|
||||
let handle = app.clone();
|
||||
let question = format!(
|
||||
"Доступна версия {version}. Скачать и установить сейчас? Приложение будет перезапущено, \
|
||||
активный голосовой звонок прервётся."
|
||||
);
|
||||
let (tx, rx) = std::sync::mpsc::channel::<bool>();
|
||||
app.dialog()
|
||||
.message(question)
|
||||
.title("Обновление glchat")
|
||||
.buttons(MessageDialogButtons::YesNo)
|
||||
.show(move |confirmed| {
|
||||
let _ = tx.send(confirmed);
|
||||
});
|
||||
if auto_install {
|
||||
// Тихая установка: подпись артефакта проверяет плагин до распаковки —
|
||||
// флаг убирает вопрос пользователю, но не проверку релиза.
|
||||
log::info!(
|
||||
"тихое обновление по флагу: {} → {version}",
|
||||
app.package_info().version
|
||||
);
|
||||
} else {
|
||||
let question = format!(
|
||||
"Доступна версия {version}. Скачать и установить сейчас? Приложение будет перезапущено, \
|
||||
активный голосовой звонок прервётся."
|
||||
);
|
||||
let (tx, rx) = std::sync::mpsc::channel::<bool>();
|
||||
app.dialog()
|
||||
.message(question)
|
||||
.title("Обновление glchat")
|
||||
.buttons(MessageDialogButtons::YesNo)
|
||||
.show(move |confirmed| {
|
||||
let _ = tx.send(confirmed);
|
||||
});
|
||||
|
||||
// Диалог асинхронный: ждём ответ, не блокируя основной поток.
|
||||
let confirmed = tauri::async_runtime::spawn_blocking(move || rx.recv().unwrap_or(false))
|
||||
.await
|
||||
.unwrap_or(false);
|
||||
if !confirmed {
|
||||
return;
|
||||
// Диалог асинхронный: ждём ответ, не блокируя основной поток.
|
||||
let confirmed = tauri::async_runtime::spawn_blocking(move || rx.recv().unwrap_or(false))
|
||||
.await
|
||||
.unwrap_or(false);
|
||||
if !confirmed {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
match update
|
||||
@@ -146,14 +158,16 @@ async fn prompt_install<R: Runtime>(
|
||||
}
|
||||
Err(error) => {
|
||||
log::error!("установка обновления не удалась: {error}");
|
||||
app.dialog()
|
||||
.message(format!(
|
||||
"Обновление не установлено: {error}. Скачать установщик вручную можно на \
|
||||
странице инстанса."
|
||||
))
|
||||
.title("Обновление glchat")
|
||||
.buttons(MessageDialogButtons::Ok)
|
||||
.show(|_| {});
|
||||
if !auto_install {
|
||||
app.dialog()
|
||||
.message(format!(
|
||||
"Обновление не установлено: {error}. Скачать установщик вручную можно на \
|
||||
странице инстанса."
|
||||
))
|
||||
.title("Обновление glchat")
|
||||
.buttons(MessageDialogButtons::Ok)
|
||||
.show(|_| {});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user