forked from 1b-agent/fieldcraft-upstream
UI: update notice, Help › Check for Updates and Reinstall, Settings › Updates (#231)
The window checks at start-up at most once a day when automatic checks are on (Settings and
the first run's question), never while that question is open and never without a host, so the
browser and tests make no network call. A newer release shows a quiet notice in the status bar
("FieldCraft X is available — What's new · Install · Skip"); Install downloads and verifies
through the host, then asks to restart, saving or asking about unsaved changes first, and the
host swaps the release in after the window closes. A .deb/.rpm install offers the system's
installer and the command instead. Skip this version is kept in the preferences.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
This commit is contained in:
1 parent
69c1440cbe
commit
2e28a69c04
9 files changed
+664
-9
No files matched your search
@@ -214,6 +214,12 @@ pub struct Prefs {
|
||||
pub usage_automation: bool,
|
||||
/// The random id usage is sent under, made when the user first agrees; empty before.
|
||||
pub install_id: String,
|
||||
/// Check for updates at start-up, at most once a day ([`crate::updates`]).
|
||||
pub update_check: bool,
|
||||
/// When the last automatic check was made (seconds since the Unix epoch; 0: never).
|
||||
pub update_checked_at: u64,
|
||||
/// The version the user skipped (the automatic check does not offer it); empty for none.
|
||||
pub update_skip: String,
|
||||
}
|
||||
|
||||
impl Default for Prefs {
|
||||
@@ -224,6 +230,9 @@ impl Default for Prefs {
|
||||
usage_sharing: None,
|
||||
usage_automation: true,
|
||||
install_id: String::new(),
|
||||
update_check: true,
|
||||
update_checked_at: 0,
|
||||
update_skip: String::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -279,6 +288,8 @@ pub enum Replace {
|
||||
File(String),
|
||||
/// A sample (`file.sample`).
|
||||
Sample(&'static str),
|
||||
/// Restarting to finish installing an update ([`crate::updates`]).
|
||||
Update,
|
||||
}
|
||||
|
||||
impl Replace {
|
||||
@@ -286,6 +297,7 @@ impl Replace {
|
||||
match self {
|
||||
Replace::File(p) => file_name(p),
|
||||
Replace::Sample(n) => fieldcraft_engine::sample::find(n).map_or_else(|| (*n).to_string(), |s| format!("the {} sample", s.label)),
|
||||
Replace::Update => "the update".into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -310,8 +322,10 @@ pub enum Prompt {
|
||||
Delete(crate::menu::DeleteAsk),
|
||||
/// The first run asks once whether to share anonymous usage ([`crate::privacy`]).
|
||||
Consent,
|
||||
/// Help › Settings: the privacy choices ([`crate::privacy`]).
|
||||
/// Help › Settings: the privacy and update choices ([`crate::privacy`]).
|
||||
Settings,
|
||||
/// An update is downloaded and verified: restart to finish it, or later ([`crate::updates`]).
|
||||
Update,
|
||||
/// The last run crashed (its new crash reports, newest first): report it, or not now.
|
||||
Crashed(Vec<fieldcraft_engine::crash::Summary>),
|
||||
/// Help › Report a Bug ([`crate::report`]; the form is [`ModelApp::report`]).
|
||||
@@ -485,7 +499,7 @@ impl ModelApp {
|
||||
}
|
||||
|
||||
/// Whether replacing the model would lose work: unsaved changes made by commands.
|
||||
fn has_unsaved_work(&self) -> bool {
|
||||
pub(crate) fn has_unsaved_work(&self) -> bool {
|
||||
self.session.is_dirty() && !self.session.journal.is_empty()
|
||||
}
|
||||
|
||||
@@ -765,6 +779,7 @@ impl ModelApp {
|
||||
}
|
||||
}
|
||||
Replace::Sample(name) => self.load_sample(name),
|
||||
Replace::Update => self.close_to_update(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -879,7 +894,10 @@ pub fn show(app: &mut ModelApp, ctx: &egui::Context) {
|
||||
Some(Prompt::Unsaved(next)) => {
|
||||
let mut answer = None;
|
||||
crate::frame::window(ctx, "Unsaved changes", crate::frame::Width::Normal).id(egui::Id::new("fc_unsaved")).show(ctx, |ui| {
|
||||
ui.label(format!("Save the changes to {} before opening {}?", app.model_name(), next.name()));
|
||||
ui.label(match next {
|
||||
Replace::Update => format!("Save the changes to {} before restarting to update?", app.model_name()),
|
||||
_ => format!("Save the changes to {} before opening {}?", app.model_name(), next.name()),
|
||||
});
|
||||
ui.label(egui::RichText::new("Without saving, they are lost.").color(t.text_dim));
|
||||
ui.add_space(6.0);
|
||||
ui.horizontal(|ui| {
|
||||
@@ -1044,7 +1062,7 @@ pub fn show(app: &mut ModelApp, ctx: &egui::Context) {
|
||||
}
|
||||
}
|
||||
// Drawn by `crate::report::show` and `crate::privacy::show`.
|
||||
Some(Prompt::Crashed(_) | Prompt::ReportBug | Prompt::Consent | Prompt::Settings) | None => {}
|
||||
Some(Prompt::Crashed(_) | Prompt::ReportBug | Prompt::Consent | Prompt::Settings | Prompt::Update) | None => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user