fix: app restarting after the user closes when there's a pending update (#6074)
* fix: app restarting after the user closes when there's a pending update * add logging and fix tauri variable * use state * use atomicbool
This commit is contained in:
@@ -109,6 +109,7 @@ import {
|
|||||||
getUpdateSize,
|
getUpdateSize,
|
||||||
isDev,
|
isDev,
|
||||||
isNetworkMetered,
|
isNetworkMetered,
|
||||||
|
setRestartAfterPendingUpdate,
|
||||||
} from '@/helpers/utils.js'
|
} from '@/helpers/utils.js'
|
||||||
import i18n from '@/i18n.config'
|
import i18n from '@/i18n.config'
|
||||||
import { createContentInstall, provideContentInstall } from '@/providers/content-install'
|
import { createContentInstall, provideContentInstall } from '@/providers/content-install'
|
||||||
@@ -1025,6 +1026,13 @@ async function downloadUpdate(versionToDownload) {
|
|||||||
|
|
||||||
async function installUpdate() {
|
async function installUpdate() {
|
||||||
restarting.value = true
|
restarting.value = true
|
||||||
|
try {
|
||||||
|
await setRestartAfterPendingUpdate(true)
|
||||||
|
} catch (e) {
|
||||||
|
restarting.value = false
|
||||||
|
handleError(e)
|
||||||
|
return
|
||||||
|
}
|
||||||
setTimeout(async () => {
|
setTimeout(async () => {
|
||||||
await handleClose()
|
await handleClose()
|
||||||
}, 250)
|
}, 250)
|
||||||
|
|||||||
@@ -22,6 +22,10 @@ export async function removeEnqueuedUpdate() {
|
|||||||
return await invoke('remove_enqueued_update')
|
return await invoke('remove_enqueued_update')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function setRestartAfterPendingUpdate(should_restart) {
|
||||||
|
return await invoke('set_restart_after_pending_update', { shouldRestart: should_restart })
|
||||||
|
}
|
||||||
|
|
||||||
// One of 'Windows', 'Linux', 'MacOS'
|
// One of 'Windows', 'Linux', 'MacOS'
|
||||||
export async function getOS() {
|
export async function getOS() {
|
||||||
return await invoke('plugin:utils|get_os')
|
return await invoke('plugin:utils|get_os')
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
use native_dialog::{DialogBuilder, MessageLevel};
|
use native_dialog::{DialogBuilder, MessageLevel};
|
||||||
use std::env;
|
use std::env;
|
||||||
|
use std::sync::atomic::Ordering;
|
||||||
use tauri::{Listener, Manager};
|
use tauri::{Listener, Manager};
|
||||||
use tauri_plugin_fs::FsExt;
|
use tauri_plugin_fs::FsExt;
|
||||||
use theseus::prelude::*;
|
use theseus::prelude::*;
|
||||||
@@ -96,6 +97,17 @@ fn restart_app(app: tauri::AppHandle) {
|
|||||||
app.restart();
|
app.restart();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
async fn set_restart_after_pending_update(
|
||||||
|
should_restart: bool,
|
||||||
|
) -> api::Result<()> {
|
||||||
|
let state = State::get().await?;
|
||||||
|
state
|
||||||
|
.restart_after_pending_update
|
||||||
|
.store(should_restart, Ordering::Relaxed);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
// if Tauri app is called with arguments, then those arguments will be treated as commands
|
// if Tauri app is called with arguments, then those arguments will be treated as commands
|
||||||
// ie: deep links or filepaths for .mrpacks
|
// ie: deep links or filepaths for .mrpacks
|
||||||
fn main() {
|
fn main() {
|
||||||
@@ -245,6 +257,7 @@ fn main() {
|
|||||||
get_update_size,
|
get_update_size,
|
||||||
enqueue_update_for_installation,
|
enqueue_update_for_installation,
|
||||||
remove_enqueued_update,
|
remove_enqueued_update,
|
||||||
|
set_restart_after_pending_update,
|
||||||
toggle_decorations,
|
toggle_decorations,
|
||||||
show_window,
|
show_window,
|
||||||
restart_app,
|
restart_app,
|
||||||
@@ -262,7 +275,13 @@ fn main() {
|
|||||||
#[cfg(feature = "updater")]
|
#[cfg(feature = "updater")]
|
||||||
if matches!(event, tauri::RunEvent::Exit) {
|
if matches!(event, tauri::RunEvent::Exit) {
|
||||||
let update_data = app.state::<PendingUpdateData>().inner();
|
let update_data = app.state::<PendingUpdateData>().inner();
|
||||||
if let Some((update, data)) = &*update_data.0.lock().unwrap() {
|
let should_restart = State::get_if_initialized()
|
||||||
|
.map(|s| {
|
||||||
|
s.restart_after_pending_update.load(Ordering::Relaxed)
|
||||||
|
})
|
||||||
|
.unwrap_or(false);
|
||||||
|
if let Some((update, data)) = &*update_data.0.lock().unwrap()
|
||||||
|
{
|
||||||
fn set_changelog_toast(version: Option<String>) {
|
fn set_changelog_toast(version: Option<String>) {
|
||||||
let toast_result: theseus::Result<()> = tauri::async_runtime::block_on(async move {
|
let toast_result: theseus::Result<()> = tauri::async_runtime::block_on(async move {
|
||||||
let mut settings = settings::get().await?;
|
let mut settings = settings::get().await?;
|
||||||
@@ -271,27 +290,46 @@ fn main() {
|
|||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
if let Err(e) = toast_result {
|
if let Err(e) = toast_result {
|
||||||
tracing::warn!("Failed to set pending_update_toast: {e}")
|
tracing::warn!(
|
||||||
|
"Failed to set pending_update_toast: {e}"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
set_changelog_toast(Some(update.version.clone()));
|
set_changelog_toast(Some(update.version.clone()));
|
||||||
if let Err(e) = update.install(data) {
|
match update.install(data) {
|
||||||
tracing::error!("Error while updating: {e}");
|
Ok(()) => {
|
||||||
set_changelog_toast(None);
|
if should_restart {
|
||||||
|
tracing::info!(
|
||||||
|
"Pending update installed successfully (version {}); restarting because user requested reload",
|
||||||
|
update.version
|
||||||
|
);
|
||||||
|
app.restart();
|
||||||
|
} else {
|
||||||
|
tracing::info!(
|
||||||
|
"Pending update installed successfully (version {}); exiting without relaunch (user did not request reload)",
|
||||||
|
update.version
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
tracing::error!(
|
||||||
|
"Pending update install failed (version {}): {e}",
|
||||||
|
update.version
|
||||||
|
);
|
||||||
|
set_changelog_toast(None);
|
||||||
|
|
||||||
DialogBuilder::message()
|
DialogBuilder::message()
|
||||||
.set_level(MessageLevel::Error)
|
.set_level(MessageLevel::Error)
|
||||||
.set_title("Update error")
|
.set_title("Update error")
|
||||||
.set_text(format!("Failed to install update due to an error:\n{e}"))
|
.set_text(format!("Failed to install update due to an error:\n{e}"))
|
||||||
.alert()
|
.alert()
|
||||||
.show()
|
.show()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
app.restart();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
if let tauri::RunEvent::Opened { urls } = event {
|
if let tauri::RunEvent::Opened { urls } = event {
|
||||||
tracing::info!("Handling webview open {urls:?}");
|
tracing::info!("Handling webview open {urls:?}");
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
//! Theseus state management system
|
//! Theseus state management system
|
||||||
use crate::util::fetch::{FetchSemaphore, IoSemaphore};
|
use crate::util::fetch::{FetchSemaphore, IoSemaphore};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use std::sync::atomic::AtomicBool;
|
||||||
use tokio::sync::{OnceCell, Semaphore};
|
use tokio::sync::{OnceCell, Semaphore};
|
||||||
|
|
||||||
use crate::state::fs_watcher::FileWatcher;
|
use crate::state::fs_watcher::FileWatcher;
|
||||||
@@ -83,6 +84,8 @@ pub struct State {
|
|||||||
/// Friends socket
|
/// Friends socket
|
||||||
pub friends_socket: FriendsSocket,
|
pub friends_socket: FriendsSocket,
|
||||||
|
|
||||||
|
pub restart_after_pending_update: AtomicBool,
|
||||||
|
|
||||||
pub(crate) pool: SqlitePool,
|
pub(crate) pool: SqlitePool,
|
||||||
|
|
||||||
pub(crate) file_watcher: FileWatcher,
|
pub(crate) file_watcher: FileWatcher,
|
||||||
@@ -146,6 +149,10 @@ impl State {
|
|||||||
LAUNCHER_STATE.initialized()
|
LAUNCHER_STATE.initialized()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_if_initialized() -> Option<Arc<Self>> {
|
||||||
|
LAUNCHER_STATE.get().map(Arc::clone)
|
||||||
|
}
|
||||||
|
|
||||||
#[tracing::instrument]
|
#[tracing::instrument]
|
||||||
async fn initialize_state(
|
async fn initialize_state(
|
||||||
app_identifier: String,
|
app_identifier: String,
|
||||||
@@ -194,6 +201,7 @@ impl State {
|
|||||||
discord_rpc,
|
discord_rpc,
|
||||||
process_manager,
|
process_manager,
|
||||||
friends_socket,
|
friends_socket,
|
||||||
|
restart_after_pending_update: AtomicBool::new(false),
|
||||||
pool,
|
pool,
|
||||||
file_watcher,
|
file_watcher,
|
||||||
// app_identifier,
|
// app_identifier,
|
||||||
|
|||||||
Reference in New Issue
Block a user