mirror of
https://github.com/storytold/soundcraft.git
synced 2026-11-09 20:04:53 +00:00
Updates: the updater reports installing, ready, installed and failed, and installs at exit
Moves the craft-libs crates (craft-update, craft-docpath, craft-media, craft-ui) from c5a1cbfb5f to a branch that merges storytold/craft-libs #687 and #696. - The result dialog shows whenever the updater reports a status, so the first start after an update says whether it installed or failed. Closing it dismisses the status; the startup prompt still takes over. - Restart to Update in the dialog asks the app to close through the usual close path. - on_exit starts the helper of a ready update, since the system Quit ends the process before the updater is dropped.
This commit is contained in:
1 parent
ddeb7e791f
commit
20338e0832
4 files changed
+92
-31
No files matched your search
Generated
+6
-19
@@ -1064,17 +1064,17 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "craft-docpath"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/storytold/craft-libs?rev=c5a1cbfb5f9049f9270955caffb5bee5997aebf7#c5a1cbfb5f9049f9270955caffb5bee5997aebf7"
|
||||
source = "git+https://github.com/dotCooCoo/craft-libs?rev=c7c84230631cbc01ee928f0a0e0d838b1ed612ae#c7c84230631cbc01ee928f0a0e0d838b1ed612ae"
|
||||
|
||||
[[package]]
|
||||
name = "craft-fonts-build"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/storytold/craft-libs?rev=c5a1cbfb5f9049f9270955caffb5bee5997aebf7#c5a1cbfb5f9049f9270955caffb5bee5997aebf7"
|
||||
source = "git+https://github.com/dotCooCoo/craft-libs?rev=c7c84230631cbc01ee928f0a0e0d838b1ed612ae#c7c84230631cbc01ee928f0a0e0d838b1ed612ae"
|
||||
|
||||
[[package]]
|
||||
name = "craft-i18n"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/storytold/craft-libs?rev=c5a1cbfb5f9049f9270955caffb5bee5997aebf7#c5a1cbfb5f9049f9270955caffb5bee5997aebf7"
|
||||
source = "git+https://github.com/dotCooCoo/craft-libs?rev=c7c84230631cbc01ee928f0a0e0d838b1ed612ae#c7c84230631cbc01ee928f0a0e0d838b1ed612ae"
|
||||
dependencies = [
|
||||
"fixed_decimal",
|
||||
"icu_decimal",
|
||||
@@ -1097,7 +1097,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "craft-media"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/storytold/craft-libs?rev=c5a1cbfb5f9049f9270955caffb5bee5997aebf7#c5a1cbfb5f9049f9270955caffb5bee5997aebf7"
|
||||
source = "git+https://github.com/dotCooCoo/craft-libs?rev=c7c84230631cbc01ee928f0a0e0d838b1ed612ae#c7c84230631cbc01ee928f0a0e0d838b1ed612ae"
|
||||
dependencies = [
|
||||
"thiserror 2.0.21",
|
||||
]
|
||||
@@ -1105,7 +1105,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "craft-ui"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/storytold/craft-libs?rev=c5a1cbfb5f9049f9270955caffb5bee5997aebf7#c5a1cbfb5f9049f9270955caffb5bee5997aebf7"
|
||||
source = "git+https://github.com/dotCooCoo/craft-libs?rev=c7c84230631cbc01ee928f0a0e0d838b1ed612ae#c7c84230631cbc01ee928f0a0e0d838b1ed612ae"
|
||||
dependencies = [
|
||||
"craft-fonts-build",
|
||||
"craft-i18n",
|
||||
@@ -1126,7 +1126,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "craft-update"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/storytold/craft-libs?rev=c5a1cbfb5f9049f9270955caffb5bee5997aebf7#c5a1cbfb5f9049f9270955caffb5bee5997aebf7"
|
||||
source = "git+https://github.com/dotCooCoo/craft-libs?rev=c7c84230631cbc01ee928f0a0e0d838b1ed612ae#c7c84230631cbc01ee928f0a0e0d838b1ed612ae"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"dunce",
|
||||
@@ -6456,7 +6456,6 @@ dependencies = [
|
||||
"nix",
|
||||
"typed-path",
|
||||
"windows-sys 0.61.2",
|
||||
"zopfli",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6471,18 +6470,6 @@ version = "1.0.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b"
|
||||
|
||||
[[package]]
|
||||
name = "zopfli"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aaf7fc5d30c28483d93805c4a5e12b05bbb52407fa67c5f8bd552374cd01fb11"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"crc32fast",
|
||||
"log",
|
||||
"simd-adler32",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zune-core"
|
||||
version = "0.5.3"
|
||||
|
||||
+4
-4
@@ -50,15 +50,15 @@ zip = { version = "9", default-features = false }
|
||||
cpal = "0.18"
|
||||
|
||||
# Which file paths stored in a session may be opened.
|
||||
craft-docpath = { version = "0.1.0", git = "https://github.com/storytold/craft-libs", rev = "c5a1cbfb5f9049f9270955caffb5bee5997aebf7" }
|
||||
craft-docpath = { version = "0.1.0", git = "https://github.com/dotCooCoo/craft-libs", rev = "c7c84230631cbc01ee928f0a0e0d838b1ed612ae" }
|
||||
|
||||
# Video containers and bitstreams, shared with the other craft apps.
|
||||
craft-media = { version = "0.1.0", git = "https://github.com/storytold/craft-libs", rev = "c5a1cbfb5f9049f9270955caffb5bee5997aebf7" }
|
||||
craft-media = { version = "0.1.0", git = "https://github.com/dotCooCoo/craft-libs", rev = "c7c84230631cbc01ee928f0a0e0d838b1ed612ae" }
|
||||
# craft-update: app-specific pretend versions apply to startup and manual checks.
|
||||
craft-update = { version = "=0.1.0", git = "https://github.com/storytold/craft-libs", rev = "c5a1cbfb5f9049f9270955caffb5bee5997aebf7", features = ["egui"] }
|
||||
craft-update = { version = "=0.1.0", git = "https://github.com/dotCooCoo/craft-libs", rev = "c7c84230631cbc01ee928f0a0e0d838b1ed612ae", features = ["egui"] }
|
||||
|
||||
# ui
|
||||
craft-ui = { version = "0.1.0", git = "https://github.com/storytold/craft-libs", rev = "c5a1cbfb5f9049f9270955caffb5bee5997aebf7", features = ["serde"] }
|
||||
craft-ui = { version = "0.1.0", git = "https://github.com/dotCooCoo/craft-libs", rev = "c7c84230631cbc01ee928f0a0e0d838b1ed612ae", features = ["serde"] }
|
||||
egui = { version = "0.37" }
|
||||
# Resizable table columns (About ▸ Contributors / Models); no image loaders.
|
||||
egui_extras = { version = "0.37", default-features = false }
|
||||
|
||||
@@ -108,9 +108,11 @@ impl eframe::App for App {
|
||||
logger.report_audio_thread();
|
||||
}
|
||||
// The system Quit (⌘Q) ends the process from inside the event loop, so `run_native` never
|
||||
// returns: release the player's plugin instances and shut plugin hosting down here.
|
||||
// returns: release the player's plugin instances and shut plugin hosting down here, and
|
||||
// start the helper of an update that waits for the app to close.
|
||||
self.0.player = None;
|
||||
soundcraft_engine::shutdown_plugin_hosts();
|
||||
self.0.start_pending_update();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,19 @@ impl SoundApp {
|
||||
pub fn set_startup_update_check(&mut self, on: bool) {
|
||||
self.updates_rt.startup_check = on;
|
||||
}
|
||||
|
||||
/// Starts the helper of an update that waits for the app to close. Call it when the exit is certain.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub fn start_pending_update(&mut self) {
|
||||
self.updates_rt.updater.start_pending_update();
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether the result dialog shows: while the updater reports something (a requested check, or what the last update
|
||||
/// came to, which the check at start reads), and not while the startup prompt is open.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn shows_result(status: &Status, prompt_open: bool) -> bool {
|
||||
!matches!(status, Status::Idle) && !prompt_open
|
||||
}
|
||||
|
||||
pub(crate) fn check(app: &mut SoundApp) {
|
||||
@@ -62,7 +75,6 @@ pub(crate) fn tick(app: &mut SoundApp, ctx: &egui::Context) {
|
||||
let rt = &mut app.updates_rt;
|
||||
if std::mem::take(&mut rt.check_requested) {
|
||||
rt.updater.check_now(ctx);
|
||||
rt.manual_window_open = true;
|
||||
} else if rt.startup_check {
|
||||
rt.updater.check_at_start(ctx);
|
||||
}
|
||||
@@ -82,20 +94,19 @@ pub(crate) fn show(app: &mut SoundApp, ctx: &egui::Context) {
|
||||
Action::Close => ctx.send_viewport_cmd(egui::ViewportCommand::Close),
|
||||
Action::None => {}
|
||||
}
|
||||
// Help ▸ Check for Updates shows its outcome in the shared result dialog until the user closes it.
|
||||
// Help ▸ Check for Updates, and the first start after an update, show their outcome in the shared result dialog
|
||||
// until the user closes it. A found update goes to the startup prompt, which takes over from the dialog.
|
||||
let rt = &mut app.updates_rt;
|
||||
rt.manual_window_open = shows_result(rt.updater.status(), rt.updater.prompt_open());
|
||||
if rt.manual_window_open {
|
||||
match rt.result_dialog.show(ctx, rt.updater.status()) {
|
||||
CheckResultResponse::Close => rt.manual_window_open = false,
|
||||
CheckResultResponse::CheckAgain => rt.updater.check_now(ctx),
|
||||
CheckResultResponse::RestartToUpdate => rt.updater.restart_to_update(),
|
||||
CheckResultResponse::None => {}
|
||||
}
|
||||
// A found update goes to the startup prompt, which takes over from the dialog.
|
||||
if matches!(rt.updater.status(), Status::Idle) {
|
||||
rt.manual_window_open = false;
|
||||
}
|
||||
}
|
||||
// Closing the dialog dismisses the outcome it showed.
|
||||
// Closing the dialog, or the prompt taking over, dismisses the outcome it showed.
|
||||
if !rt.manual_window_open {
|
||||
rt.updater.dismiss_status();
|
||||
}
|
||||
@@ -115,3 +126,64 @@ pub(crate) fn show(app: &mut SoundApp, ctx: &egui::Context) {
|
||||
app.updates_rt.manual_window_open = open;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(test, not(target_arch = "wasm32")))]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::Services;
|
||||
use craft_update::Paths;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// One pass of the update check and its windows, with `events` as the frame's input, dropping texture deltas the
|
||||
/// tests do not inspect.
|
||||
fn frame(app: &mut SoundApp, ctx: &egui::Context, events: Vec<egui::Event>) {
|
||||
let raw = egui::RawInput { events, ..Default::default() };
|
||||
let mut out = ctx.run_ui(raw, |ui| {
|
||||
tick(app, ui.ctx());
|
||||
show(app, ui.ctx());
|
||||
});
|
||||
out.textures_delta.clear();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_result_dialog_shows_every_reported_status_until_the_prompt_opens() {
|
||||
for status in [
|
||||
Status::Checking,
|
||||
Status::UpToDate,
|
||||
Status::Failed("offline".into()),
|
||||
Status::Installing,
|
||||
Status::Ready,
|
||||
Status::Managed,
|
||||
Status::Updated("0.2.0".into()),
|
||||
Status::InstallFailed("disk full".into()),
|
||||
] {
|
||||
assert!(shows_result(&status, false), "{status:?}");
|
||||
assert!(!shows_result(&status, true), "{status:?} with the prompt open");
|
||||
}
|
||||
assert!(!shows_result(&Status::Idle, false));
|
||||
}
|
||||
|
||||
/// The first start after an update says so in the result dialog, which stays until the user closes it.
|
||||
#[test]
|
||||
fn the_first_start_after_an_update_reports_it_until_closed() {
|
||||
let dir = std::env::temp_dir().join(format!("soundcraft-update-result-{}", std::process::id()));
|
||||
let paths = Paths::under(&dir);
|
||||
std::fs::create_dir_all(&paths.data).unwrap();
|
||||
std::fs::write(paths.data.join("self-update-done.txt"), "v0.2.0").unwrap();
|
||||
let mut app = SoundApp::new(soundcraft_engine::Engine::default(), None, Services::default());
|
||||
app.updates_rt.updater =
|
||||
Updater::new(&crate::UPDATE_APP, "0.2.0").with_source(Arc::new(|| Ok(None))).with_pins_path(dir.join("pins.json")).with_paths(paths);
|
||||
app.set_startup_update_check(true);
|
||||
let ctx = egui::Context::default();
|
||||
for _ in 0..3 {
|
||||
frame(&mut app, &ctx, Vec::new());
|
||||
}
|
||||
assert_eq!(app.updates_rt.updater.status(), &Status::Updated("0.2.0".into()));
|
||||
assert!(app.updates_rt.manual_window_open);
|
||||
let escape = egui::Event::Key { key: egui::Key::Escape, physical_key: None, pressed: true, repeat: false, modifiers: egui::Modifiers::NONE };
|
||||
frame(&mut app, &ctx, vec![escape]);
|
||||
assert_eq!(app.updates_rt.updater.status(), &Status::Idle);
|
||||
assert!(!app.updates_rt.manual_window_open);
|
||||
let _ = std::fs::remove_dir_all(dir);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user