mirror of
https://github.com/storytold/wordcraft.git
synced 2026-10-29 12:57:09 -06:00
Merge pull request #4298 from dylanmtaylor/feat/startup-update-prompt
feat: startup update prompt modal and direct self-updating
This commit is contained in:
Generated
+209
-16
@@ -1036,6 +1036,31 @@ dependencies = [
|
||||
"egui",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "craft-update"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/storytold/craft-libs?rev=db19c373c8d59a545972ca340987aecfb3611a4b#db19c373c8d59a545972ca340987aecfb3611a4b"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"dunce",
|
||||
"egui",
|
||||
"flate2",
|
||||
"getrandom 0.3.4",
|
||||
"log",
|
||||
"plist",
|
||||
"semver",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2 0.10.9",
|
||||
"tar",
|
||||
"tempfile",
|
||||
"ureq",
|
||||
"verifysign",
|
||||
"winreg",
|
||||
"winsafe",
|
||||
"zip 9.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "craft-winprint-gdi"
|
||||
version = "0.1.0"
|
||||
@@ -1163,6 +1188,12 @@ dependencies = [
|
||||
"syn 2.0.119",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deranged"
|
||||
version = "0.5.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e9de72ce2ad1f90dc62fa25f0f430ef85eb4b0d8fa0be4f30373bc40a21d28e"
|
||||
|
||||
[[package]]
|
||||
name = "derive_arbitrary"
|
||||
version = "1.4.2"
|
||||
@@ -1514,7 +1545,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3042,6 +3073,18 @@ dependencies = [
|
||||
"jni-sys 0.3.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.31.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d"
|
||||
dependencies = [
|
||||
"bitflags 2.13.2",
|
||||
"cfg-if",
|
||||
"cfg_aliases",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nohash-hasher"
|
||||
version = "0.2.0"
|
||||
@@ -3057,6 +3100,12 @@ dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-conv"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441"
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.19"
|
||||
@@ -3467,7 +3516,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d8fae84b431384b68627d0f9b3b1245fcf9f46f6c0e3dc902e9dce64edd1967"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3694,6 +3743,19 @@ version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
|
||||
|
||||
[[package]]
|
||||
name = "plist"
|
||||
version = "1.10.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "327a4cb2ad49dc48adfdc9da89e22c64d488b508c67a044d71ba729e4521a285"
|
||||
dependencies = [
|
||||
"base64 0.23.1",
|
||||
"indexmap",
|
||||
"quick-xml 0.42.0",
|
||||
"serde",
|
||||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "png"
|
||||
version = "0.18.1"
|
||||
@@ -3778,6 +3840,12 @@ dependencies = [
|
||||
"zerovec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "powerfmt"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4a6394b9e965e73d0a289ee54f589087e2c676aedf60885baf52c76b771e4958"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.21"
|
||||
@@ -3887,6 +3955,15 @@ dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quick-xml"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41b1177fdf999d2321d3fb46ff47159d9c1fb9ad66a4879f8c50a0b504615e9b"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quinn"
|
||||
version = "0.11.12"
|
||||
@@ -3941,7 +4018,7 @@ dependencies = [
|
||||
"once_cell",
|
||||
"socket2",
|
||||
"tracing",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4318,7 +4395,7 @@ dependencies = [
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys 0.12.1",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4328,7 +4405,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "48e13bd8c0e9365c43cfa5c9e8f9ad49d3c8444926c9aac819e0e4dc503c8fdf"
|
||||
dependencies = [
|
||||
"aws-lc-rs",
|
||||
"log",
|
||||
"once_cell",
|
||||
"ring",
|
||||
"rustls-pki-types",
|
||||
"rustls-webpki",
|
||||
"subtle",
|
||||
@@ -4375,7 +4454,7 @@ dependencies = [
|
||||
"security-framework",
|
||||
"security-framework-sys",
|
||||
"webpki-root-certs",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4490,6 +4569,10 @@ name = "semver"
|
||||
version = "1.0.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "send_wrapper"
|
||||
@@ -4973,7 +5056,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5158,7 +5241,7 @@ dependencies = [
|
||||
"getrandom 0.4.3",
|
||||
"once_cell",
|
||||
"rustix 1.1.5",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5233,6 +5316,36 @@ dependencies = [
|
||||
"zune-jpeg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.55"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdb87b95ec50ddfa440816d227a17b2ccbdda963a316a727fda0fc4334f7d134"
|
||||
dependencies = [
|
||||
"deranged",
|
||||
"num-conv",
|
||||
"powerfmt",
|
||||
"serde_core",
|
||||
"time-core",
|
||||
"time-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time-core"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109"
|
||||
|
||||
[[package]]
|
||||
name = "time-macros"
|
||||
version = "0.2.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7e689342a48d2ea927c87ea50cabf8594854bf940e9310208848d680d668ed85"
|
||||
dependencies = [
|
||||
"num-conv",
|
||||
"time-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tiny-skia-path"
|
||||
version = "0.12.0"
|
||||
@@ -5474,6 +5587,12 @@ dependencies = [
|
||||
"rustc-hash 2.1.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typed-path"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ce898823d8cd0f028662d2f349694b1af0a5cc9be83f1d213a00d3147445e1e"
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.20.1"
|
||||
@@ -5488,7 +5607,7 @@ checksum = "f2f6fb2847f6742cd76af783a2a2c49e9375d0a111c7bef6f71cd9e738c72d6e"
|
||||
dependencies = [
|
||||
"memoffset",
|
||||
"tempfile",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5566,6 +5685,35 @@ version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
|
||||
|
||||
[[package]]
|
||||
name = "ureq"
|
||||
version = "3.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cde93ff05758a36a851a398a772b0b79a82fbe3c186a46f2696baaeaf84c966b"
|
||||
dependencies = [
|
||||
"base64 0.23.1",
|
||||
"flate2",
|
||||
"log",
|
||||
"percent-encoding",
|
||||
"rustls",
|
||||
"rustls-pki-types",
|
||||
"rustls-platform-verifier",
|
||||
"ureq-proto",
|
||||
"utf8-zero",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ureq-proto"
|
||||
version = "0.6.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "841583fc36089d7d59419568ae157f43a5a03a2e5a81ba87c77d1596ef46e922"
|
||||
dependencies = [
|
||||
"base64 0.23.1",
|
||||
"http",
|
||||
"httparse",
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "2.5.8"
|
||||
@@ -5584,6 +5732,12 @@ version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246"
|
||||
|
||||
[[package]]
|
||||
name = "utf8-zero"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8c0a043c9540bae7c578c88f91dda8bd82e59ae27c21baca69c8b191aaf5a6e"
|
||||
|
||||
[[package]]
|
||||
name = "utf8_iter"
|
||||
version = "1.0.4"
|
||||
@@ -5634,6 +5788,16 @@ dependencies = [
|
||||
"vello_common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "verifysign"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6acfcc42a8d44f340d001193d97ef56bf33210b51ad760ae8308c97d5241ca51"
|
||||
dependencies = [
|
||||
"core-foundation 0.10.1",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.5"
|
||||
@@ -5858,7 +6022,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "338e30461b3a2b67d70eb30a6d89f8e0c93a833e07d2ae89085cd070c4a00ac0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quick-xml",
|
||||
"quick-xml 0.41.0",
|
||||
"quote",
|
||||
]
|
||||
|
||||
@@ -6114,7 +6278,7 @@ version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
||||
dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6483,6 +6647,16 @@ dependencies = [
|
||||
"xml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winreg"
|
||||
version = "0.55.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb5a765337c50e9ec252c2069be9bf91c7df47afb103b642ba3a53bf8101be97"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winresource"
|
||||
version = "0.1.31"
|
||||
@@ -6531,6 +6705,7 @@ dependencies = [
|
||||
"chrono",
|
||||
"clipboard-win",
|
||||
"craft-print",
|
||||
"craft-update",
|
||||
"dispatch2",
|
||||
"eframe",
|
||||
"egui",
|
||||
@@ -6617,7 +6792,7 @@ dependencies = [
|
||||
"image",
|
||||
"log",
|
||||
"proptest",
|
||||
"quick-xml",
|
||||
"quick-xml 0.41.0",
|
||||
"sha1 0.11.0",
|
||||
"sha2 0.11.0",
|
||||
"thiserror 2.0.21",
|
||||
@@ -6625,7 +6800,7 @@ dependencies = [
|
||||
"wordcraft-doc",
|
||||
"wordcraft-geom",
|
||||
"zeroize",
|
||||
"zip",
|
||||
"zip 3.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6656,7 +6831,7 @@ dependencies = [
|
||||
"wordcraft-proof",
|
||||
"wordcraft-render",
|
||||
"zeroize",
|
||||
"zip",
|
||||
"zip 3.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6684,10 +6859,10 @@ dependencies = [
|
||||
"js-sys",
|
||||
"log",
|
||||
"proptest",
|
||||
"quick-xml",
|
||||
"quick-xml 0.41.0",
|
||||
"wordcraft-doc",
|
||||
"wordcraft-geom",
|
||||
"zip",
|
||||
"zip 3.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6791,6 +6966,7 @@ dependencies = [
|
||||
"chrono",
|
||||
"craft-i18n",
|
||||
"craft-ui",
|
||||
"craft-update",
|
||||
"egui",
|
||||
"egui_kittest",
|
||||
"image",
|
||||
@@ -6809,7 +6985,7 @@ dependencies = [
|
||||
"wordcraft-render",
|
||||
"wordcraft-zotero",
|
||||
"zbus",
|
||||
"zip",
|
||||
"zip 3.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -7242,6 +7418,23 @@ dependencies = [
|
||||
"zopfli",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zip"
|
||||
version = "9.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2886b00003a72c4ccee3f42cfc34908d33b2508a74d827dc2a4244706475c704"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"flate2",
|
||||
"getrandom 0.4.3",
|
||||
"indexmap",
|
||||
"memchr",
|
||||
"nix",
|
||||
"typed-path",
|
||||
"windows-sys 0.61.2",
|
||||
"zopfli",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zlib-rs"
|
||||
version = "0.6.8"
|
||||
|
||||
@@ -55,6 +55,7 @@ wuff = "0.2.9"
|
||||
vello_cpu = "0.2"
|
||||
image = { version = "0.25", default-features = false, features = ["png", "jpeg", "webp", "gif", "bmp", "tiff"] }
|
||||
craft-pdf = { git = "https://github.com/storytold/craft-libs", rev = "17744430be327d0257496a6a31c8d38fe20a6756", version = "=0.1.0", default-features = false, features = ["write"] }
|
||||
craft-update = { git = "https://github.com/storytold/craft-libs", version = "=0.1.0", rev = "db19c373c8d59a545972ca340987aecfb3611a4b", features = ["egui"] }
|
||||
quick-xml = "0.41"
|
||||
zip = { version = "3", default-features = false, features = ["deflate"] }
|
||||
# zlib streams (compressed metafile pictures in `.doc` drawings); already in the lock as a dependency of other crates.
|
||||
|
||||
@@ -83,3 +83,6 @@ pollster = "0.4"
|
||||
arboard = { workspace = true, features = ["image-data"] }
|
||||
# The control server's random key.
|
||||
getrandom = "0.3"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
craft-update = { workspace = true }
|
||||
|
||||
@@ -337,6 +337,11 @@ fn open_non_unicode(app: &mut WordApp, path: &std::path::Path) {
|
||||
/// geometry, opens requested documents or the Start screen, starts the control server when
|
||||
/// asked, and runs the eframe event loop.
|
||||
fn main() -> eframe::Result {
|
||||
// Windows: the update helper is a copy of this program started with `--finish-update`.
|
||||
#[cfg(windows)]
|
||||
if let Some(result) = craft_update::self_update::finish(&craft_update::suite::WORDCRAFT, &std::env::args_os().skip(1).collect::<Vec<_>>()) {
|
||||
std::process::exit(i32::from(result.is_err()));
|
||||
}
|
||||
// First, so the panic hook and every start-up warning are recorded (`logging`).
|
||||
let logger = logging::install();
|
||||
logging::install_panic_hook();
|
||||
@@ -445,6 +450,7 @@ fn main() -> eframe::Result {
|
||||
let mut session = Session::new(doc);
|
||||
session.system_region = region;
|
||||
let mut app = WordApp::new(session, services(file_dialog, &cc.egui_ctx));
|
||||
app.set_startup_update_check(true);
|
||||
load_prefs(&mut app);
|
||||
load_user_dictionary(&mut app);
|
||||
// A region chosen in File › Options replaces the system's for the first blank
|
||||
|
||||
@@ -42,6 +42,7 @@ zbus = "=5.19.0"
|
||||
# Comment times in the user's own time zone (`local_time.rs`); the web app asks the browser.
|
||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||
chrono = { version = "0.4.45", default-features = false, features = ["clock"] }
|
||||
craft-update = { workspace = true }
|
||||
|
||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||
# The browser clock (`SystemTime::now()`/`Instant::now()` panic on wasm32).
|
||||
|
||||
@@ -83,6 +83,7 @@ pub mod table_pen;
|
||||
pub mod table_resize;
|
||||
pub mod table_ruler;
|
||||
pub mod theme;
|
||||
pub mod updates_ui;
|
||||
pub mod widgets;
|
||||
pub mod window_close;
|
||||
pub mod window_geometry;
|
||||
@@ -568,6 +569,7 @@ pub struct WordApp {
|
||||
pub mac_titlebar: chrome::MacTitleBar,
|
||||
/// Focus (#1678): the ribbon is dropped down from the Focus bar, over the page.
|
||||
pub(crate) focus_ribbon: bool,
|
||||
pub(crate) updates_rt: updates_ui::Runtime,
|
||||
control_rx: Option<std::sync::mpsc::Receiver<ControlRequest>>,
|
||||
/// Admitted `ui.screenshot` requests: count/byte budgets, retries and completion slots.
|
||||
shots: control::Shots,
|
||||
@@ -735,6 +737,7 @@ impl WordApp {
|
||||
integrated_titlebar: false,
|
||||
mac_titlebar: chrome::MacTitleBar::default(),
|
||||
focus_ribbon: false,
|
||||
updates_rt: updates_ui::Runtime::default(),
|
||||
control_rx: None,
|
||||
shots: control::Shots::default(),
|
||||
capture_epoch: 0,
|
||||
@@ -1628,6 +1631,10 @@ impl WordApp {
|
||||
fn ui_command(&mut self, id: &str, p: &Value) -> Option<Result<Value, String>> {
|
||||
let s = |k: &str| p.get(k).and_then(Value::as_str);
|
||||
Some(Ok(match id {
|
||||
"ui.checkForUpdates" | "help.checkForUpdates" => {
|
||||
crate::updates_ui::check(self);
|
||||
Value::Null
|
||||
}
|
||||
"ui.tab" => {
|
||||
let tab = s("tab").unwrap_or("Home").to_string();
|
||||
if tab == "File" {
|
||||
@@ -2244,6 +2251,7 @@ impl WordApp {
|
||||
|
||||
/// Per-frame logic before layout: control requests, screenshots, shortcuts, file drops.
|
||||
pub fn logic(&mut self, ctx: &egui::Context) {
|
||||
updates_ui::tick(self, ctx);
|
||||
let lang = i18n::Lang::from_pref(&self.ui.language);
|
||||
i18n::set_current(lang);
|
||||
// New documents are written in the interface's language when WordCraft can proof it
|
||||
@@ -2637,6 +2645,7 @@ impl WordApp {
|
||||
fn show_overlays(&mut self, ui: &mut egui::Ui, ctx: &egui::Context) {
|
||||
content_controls::popup(self, ctx);
|
||||
dialogs::show(self, ctx);
|
||||
updates_ui::show(self, ctx);
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
file_browser::show(self, ctx);
|
||||
colors::show(self, ctx);
|
||||
@@ -3018,6 +3027,7 @@ pub(crate) fn works_without_document(id: &str) -> bool {
|
||||
| "ui.discord"
|
||||
| "ui.caretAnimation"
|
||||
| "ui.startScreen"
|
||||
| "ui.checkForUpdates"
|
||||
) || id.starts_with("help.")
|
||||
}
|
||||
|
||||
|
||||
@@ -2431,6 +2431,7 @@ fn outlining(app: &mut WordApp, ui: &mut Ui) {
|
||||
fn help(app: &mut WordApp, ui: &mut Ui) {
|
||||
group(ui, "Help", None, app, |ui, app| {
|
||||
big(ui, app, "help", "Help", "ui.dialog", json!({"name": "about"}), false);
|
||||
big(ui, app, "checkForUpdates", "Check for\nUpdates…", "ui.checkForUpdates", json!({}), false);
|
||||
big(ui, app, "discord", "Community\nDiscord", "ui.discord", json!({}), false);
|
||||
});
|
||||
group(ui, "Agents", None, app, |ui, app| {
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
//! Software updates, background check at startup, and startup prompt modal.
|
||||
|
||||
use crate::WordApp;
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use craft_update::updater::{Action, Status, Updater};
|
||||
|
||||
pub(crate) struct Runtime {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
updater: Updater,
|
||||
/// The desktop app turns the check at start on; tests and the web build leave it off.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
startup_check: bool,
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
check_requested: bool,
|
||||
/// The context of the last frame, to wake the UI when a check is queued from a menu callback.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
repaint: Option<egui::Context>,
|
||||
pub(crate) manual_window_open: bool,
|
||||
pub(crate) status_message: Option<String>,
|
||||
}
|
||||
|
||||
impl Default for Runtime {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
updater: Updater::new(&craft_update::suite::WORDCRAFT, env!("CARGO_PKG_VERSION")),
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
startup_check: false,
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
check_requested: false,
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
repaint: None,
|
||||
manual_window_open: false,
|
||||
status_message: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl WordApp {
|
||||
/// Whether the app asks for a newer release when it starts (off until the desktop app turns it on).
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub fn set_startup_update_check(&mut self, on: bool) {
|
||||
self.updates_rt.startup_check = on;
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn check(app: &mut WordApp) {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
{
|
||||
app.updates_rt.check_requested = true;
|
||||
if let Some(ctx) = &app.updates_rt.repaint {
|
||||
ctx.request_repaint();
|
||||
}
|
||||
}
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
{
|
||||
app.updates_rt.manual_window_open = true;
|
||||
app.updates_rt.status_message = Some(tl!("Update check is not supported in the web browser.").to_string());
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn tick(app: &mut WordApp, ctx: &egui::Context) {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
{
|
||||
let rt = &mut app.updates_rt;
|
||||
rt.repaint = Some(ctx.clone());
|
||||
if std::mem::take(&mut rt.check_requested) {
|
||||
rt.updater.check_now(ctx);
|
||||
} else if rt.startup_check {
|
||||
rt.updater.check_at_start(ctx);
|
||||
}
|
||||
rt.updater.tick(ctx);
|
||||
}
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
let _ = (app, ctx);
|
||||
}
|
||||
|
||||
pub(crate) fn show(app: &mut WordApp, ctx: &egui::Context) {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
{
|
||||
// The restart helper is scheduled before the app closes, so no update starts over unsaved work.
|
||||
let clean = !(app.session.dirty || app.save_unconfirmed() || app.printing.busy() || crate::panes::has_comment_drafts(app));
|
||||
match app.updates_rt.updater.show_if(ctx, clean) {
|
||||
Action::OpenUrl(url) => ctx.open_url(egui::OpenUrl::new_tab(url)),
|
||||
Action::Close => ctx.send_viewport_cmd(egui::ViewportCommand::Close),
|
||||
Action::None => {}
|
||||
}
|
||||
// The window answers Help ▸ Check for Updates, so it follows the updater's status.
|
||||
let rt = &mut app.updates_rt;
|
||||
(rt.manual_window_open, rt.status_message) = match rt.updater.status() {
|
||||
Status::Idle => (false, None),
|
||||
Status::Checking => (true, None),
|
||||
Status::UpToDate => {
|
||||
(true, Some(tl!("WordCraft {version} is currently the newest version available.").replace("{version}", env!("CARGO_PKG_VERSION"))))
|
||||
}
|
||||
Status::Failed(e) => (true, Some(tl!("Could not check for updates:\n{error}").replace("{error}", e))),
|
||||
};
|
||||
}
|
||||
|
||||
if app.updates_rt.manual_window_open {
|
||||
let mut open = true;
|
||||
let mut close = false;
|
||||
egui::Window::new(tl!("Check for Updates"))
|
||||
.open(&mut open)
|
||||
.resizable(false)
|
||||
.collapsible(false)
|
||||
.anchor(egui::Align2::CENTER_CENTER, egui::vec2(0.0, 0.0))
|
||||
.show(ctx, |ui| {
|
||||
if let Some(msg) = &app.updates_rt.status_message {
|
||||
ui.label(msg);
|
||||
} else {
|
||||
ui.label(tl!("Checking for updates…"));
|
||||
}
|
||||
ui.add_space(8.0);
|
||||
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
|
||||
if ui.button(tl!("Close")).clicked() {
|
||||
close = true;
|
||||
}
|
||||
});
|
||||
});
|
||||
if !open || close {
|
||||
app.updates_rt.manual_window_open = false;
|
||||
app.updates_rt.status_message = None;
|
||||
}
|
||||
}
|
||||
|
||||
// Closing the window dismisses the outcome it showed.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
if !app.updates_rt.manual_window_open {
|
||||
app.updates_rt.updater.dismiss_status();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user