diff --git a/REBRAND.md b/REBRAND.md
new file mode 100644
index 0000000..9ca5dc6
--- /dev/null
+++ b/REBRAND.md
@@ -0,0 +1,48 @@
+# OneCAD Simulation rebrand map (identity layer)
+
+OneCAD Simulation is the OneBSpace fork of FieldCraft (a pure-Rust CAE app: FEA, meshing,
+thermal, LBM CFD, with a WASM web app at `apps/fieldcraft-web`). The rebrand is **source-level**
+for everything the user can see or click; only the compatibility layer keeps upstream names (so
+`.fieldcraft` files, crate names, storage keys and internal identifiers stay upstream-compatible,
+and every upstream sync stays a clean merge). Files tagged `// OneBSpace (OneCAD Simulation):`
+are downstream-only deltas — one tag per edited site, above or beside the change, so the whole
+fork layer can be found with `grep -rn "OneBSpace (OneCAD Simulation)"`.
+
+## Rebranded in source (user-visible)
+
+| Layer | Change |
+|---|---|
+| Web page | `
OneCAD Simulation`, description and social-card meta renamed; upstream's `tangency-labs.github.io/fieldcraft` `og:url`/`og:image`/`twitter:image` dropped; loading, no-JavaScript and could-not-start text say "OneCAD Simulation" (`apps/fieldcraft-web/index.html`) |
+| App bar | upstream's drawn fringe-cube vector mark dropped; a painted `OneCAD Simulation` wordmark (`appbar.rs::APP_NAME`) shows in **every** width variant — the compact bar keeps the name and the quick actions start after the measured wordmark (`bar_layout` gained a `name_w` argument) |
+| Help menu | Samples, navigation help, Crash Reports…, Settings… and the version label `OneCAD Simulation {VERSION}` remain; upstream's `Report a Bug…` (GitHub draft), `Check for Updates` and `Reinstall FieldCraft…` items and their handler branches are removed (`appbar.rs::help_menu`) |
+| Bug/crash reports | fully local: the Report-a-Bug form's `Open GitHub Issue` became a `Copy report` button — the draft (title, fields, session) goes to the clipboard and attachments to the local `bug-reports/` folder; nothing opens a browser, `ISSUE_URL` is never opened (`report.rs::copy_report`); crash questions/headings say "OneCAD Simulation closed unexpectedly / hit an internal error" |
+| Crash messages | the engine's unclean-exit and native-crash messages (rendered in the crash dialog and the copied report) name the fork (`engine/src/crash.rs`) |
+| Command catalogue | `diagnostics.bug_report` and `app.update.check` palette help texts describe the local draft / name the fork (`engine/src/cmd/diagnostics.rs`, `engine/src/cmd/update.rs`) |
+| Updates (desktop-only) | every status line, the notice and the install dialog say "OneCAD Simulation" (`updates.rs`); the web build has no update host, so none of this runs in the browser; "What's new"/release URLs stay desktop-only logic, rebranded text only |
+| Privacy | consent question and dialog title, Settings copy and tooltips say "OneCAD Simulation"; the upstream GitHub `PRIVACY_URL` is no longer rendered as a link nor opened — the privacy note is plain text (`privacy.rs`); the constant is kept for reference |
+| Navigation | the default mouse-mapping preset's label is "OneCAD Simulation" (its `id: "fieldcraft"` stays, preferences depend on it) |
+| Desktop window | window title / `run_native` app name "OneCAD Simulation" (`apps/fieldcraft/src/main.rs`; the `APP_ID` reverse-DNS id stays) |
+| Attachments | the bug-report session attachment is `onecadsim-session.json` (`engine/src/bug_report.rs::SESSION_FILE`); the model attachment keeps the `.fieldcraft` name |
+
+## Stays upstream (compatibility & scale)
+
+- **The `.fieldcraft` file-format extension** (and `model.fieldcraft` attachment naming); crate
+ names and the Cargo workspace layout — untouched, so upstream syncs stay mergeable.
+- **localStorage keys** (`fieldcraft-recovery/`, `fieldcraft-prefs`) and the browser recovery
+ folder layout.
+- **HTML element ids** (`fieldcraft_canvas`, `fieldcraft_loading`) and the trunk tags in
+ `apps/fieldcraft-web/index.html`.
+- **Environment variable names** (`FIELDCRAFT_POSTHOG_KEY`, `FIELDCRAFT_TELEMETRY`,
+ `FIELDCRAFT_CONTROL_PORT`, …). Telemetry logic is untouched: the Odoo build simply does not set
+ `FIELDCRAFT_POSTHOG_KEY`, so the PostHog sender stays inert; no key or host URL is surfaced in
+ the UI.
+- **Internal identifiers**: egui window/id salts (`fc_appbar`, `fc_report_bug`, …), command ids
+ (`diagnostics.bug_report`), the `fieldcraft` nav-preset id, `SESSION_FILE`/`ISSUE_URL` API
+ names, the `fieldcraft-cli` binary name quoted in report text.
+- Desktop-only updater internals (release URLs, package layouts) keep upstream strings —
+ unreachable from the web build.
+
+## Not touched here
+
+`crates/ui-egui/src/files.rs` and `apps/fieldcraft-web/src/{web,main}.rs` plus `odoo/*` are owned
+by other agents in this task train; their user-visible strings are handled there.
diff --git a/apps/fieldcraft/src/main.rs b/apps/fieldcraft/src/main.rs
index b422be8..352ce4f 100644
--- a/apps/fieldcraft/src/main.rs
+++ b/apps/fieldcraft/src/main.rs
@@ -248,7 +248,9 @@ fn main() -> eframe::Result {
crash::phase("window");
let options = eframe::NativeOptions {
viewport: egui::ViewportBuilder::default()
- .with_title("FieldCraft")
+ // OneBSpace (OneCAD Simulation): the window title names the fork (the APP_ID, which
+ // the packaged .desktop entries and the bundle id match, stays upstream).
+ .with_title("OneCAD Simulation")
.with_app_id(APP_ID)
.with_icon(app_icon())
.with_inner_size([1400.0, 900.0])
@@ -265,7 +267,8 @@ fn main() -> eframe::Result {
..Default::default()
};
eframe::run_native(
- "FieldCraft",
+ // OneBSpace (OneCAD Simulation): the app name in the window title.
+ "OneCAD Simulation",
options,
Box::new(move |cc| {
crash::phase("app setup");
diff --git a/crates/engine/src/bug_report.rs b/crates/engine/src/bug_report.rs
index 2b4beeb..2784eea 100644
--- a/crates/engine/src/bug_report.rs
+++ b/crates/engine/src/bug_report.rs
@@ -21,7 +21,9 @@ pub const ISSUE_URL: &str = "https://github.com/tangency-labs/fieldcraft/issues/
/// The longest link a draft opens: GitHub refuses new-issue links much past 8 KB.
pub const MAX_URL: usize = 7000;
/// The session file a draft attaches.
-pub const SESSION_FILE: &str = "fieldcraft-session.json";
+// OneBSpace (OneCAD Simulation): the attachment name carries the fork's mark; the internal API
+// name (`SESSION_FILE`) stays upstream.
+pub const SESSION_FILE: &str = "onecadsim-session.json";
/// The model file a draft attaches.
pub const MODEL_FILE: &str = "model.fieldcraft";
/// Backtrace frames a crash's draft quotes.
@@ -158,8 +160,9 @@ pub fn draft(input: &Input, version: &str) -> Draft {
let crash = input.crash.as_ref();
let mut title = input.title.trim().to_string();
if title.is_empty() {
+ // OneBSpace (OneCAD Simulation): the fork's name in the drafted title.
title = match crash.and_then(|c| c.get("kind")).and_then(Value::as_str) {
- Some("unclean_exit") => "FieldCraft closed unexpectedly".to_string(),
+ Some("unclean_exit") => "OneCAD Simulation closed unexpectedly".to_string(),
Some(_) => "Internal error".to_string(),
None => match input.observed.trim().lines().next().filter(|l| !l.is_empty()) {
Some(line) => format!("Bug: {}", line.chars().take(100).collect::()),
@@ -224,14 +227,16 @@ pub fn draft(input: &Input, version: &str) -> Draft {
} else {
let text = serde_json::to_string_pretty(script).unwrap_or_default();
evidence.push_str(&format!(
- "\nThe session is too long for this form: FieldCraft saved it as `{SESSION_FILE}` and copied it to the clipboard. Attach the file here (drag it in) or paste it.\n"
+ // OneBSpace (OneCAD Simulation): the fork's name in the evidence text.
+ "\nThe session is too long for this form: OneCAD Simulation saved it as `{SESSION_FILE}` and copied it to the clipboard. Attach the file here (drag it in) or paste it.\n"
));
attachments.insert(0, Attachment { name: SESSION_FILE.into(), bytes: text.clone().into_bytes(), what: "the session's commands".into() });
clipboard = Some(text);
}
}
if model.is_some() {
- evidence.push_str(&format!("\nThe model is attached as `{MODEL_FILE}` (drag it in from the folder FieldCraft saved it to).\n"));
+ // OneBSpace (OneCAD Simulation): the fork's name in the evidence text.
+ evidence.push_str(&format!("\nThe model is attached as `{MODEL_FILE}` (drag it in from the folder OneCAD Simulation saved it to).\n"));
}
if url.is_empty() || model.is_some() {
let mut f = fields(evidence.clone());
diff --git a/crates/engine/src/cmd/diagnostics.rs b/crates/engine/src/cmd/diagnostics.rs
index 324c63f..22e2357 100644
--- a/crates/engine/src/cmd/diagnostics.rs
+++ b/crates/engine/src/cmd/diagnostics.rs
@@ -43,7 +43,9 @@ pub const CRASH_REPORTS_DELETE: CommandSpec = CommandSpec {
pub const BUG_REPORT: CommandSpec = CommandSpec {
id: "diagnostics.bug_report",
label: "Report a Bug",
- params: r#"{"title"?: "…", "observed"?: "what happened", "crash"?: "", "share_session"?: false, "include_model"?: false} — drafts a GitHub bug report: the issue link (the bug form filled with the version, the OS, what happened and, for a crash, where), and the files to attach. Only with share_session does it carry the model's commands, and only with include_model as well the model file. Nothing is sent: the desktop app's Help › Report a Bug shows the draft and opens the link when the user asks"#,
+ // OneBSpace (OneCAD Simulation): the draft stays local — no GitHub issue link is opened;
+ // the form's Copy report puts the report on the clipboard and saves attachments to a folder.
+ params: r#"{"title"?: "…", "observed"?: "what happened", "crash"?: "", "share_session"?: false, "include_model"?: false} — drafts a bug report that stays in the workspace: the version, the OS, what happened and, for a crash, where, and the files to attach. Only with share_session does it carry the model's commands, and only with include_model as well the model file. Nothing is sent: the form's Copy report copies the report to the clipboard and saves the attachments to a local folder"#,
form: Some(super::forms::BUG_REPORT),
kind: CommandKind::Session,
requires: &[],
diff --git a/crates/engine/src/cmd/update.rs b/crates/engine/src/cmd/update.rs
index debfd5f..4dec6f1 100644
--- a/crates/engine/src/cmd/update.rs
+++ b/crates/engine/src/cmd/update.rs
@@ -15,7 +15,8 @@ use crate::{CommandKind, CommandSpec, EngineError, Result, Session};
pub const CHECK: CommandSpec = CommandSpec {
id: "app.update.check",
label: "Check for Updates",
- params: r#"{} — asks GitHub Releases for the latest published FieldCraft release and compares it with this version: current, latest, newer, url (its page and release notes), published, signed (whether it can be verified and installed from the app) and asset (the file this install would download; null when it cannot update itself). Reports only: nothing is downloaded or installed. Desktop app and fieldcraft-cli only"#,
+ // OneBSpace (OneCAD Simulation): the fork's name in the palette help text (desktop-only).
+ params: r#"{} — asks GitHub Releases for the latest published OneCAD Simulation release and compares it with this version: current, latest, newer, url (its page and release notes), published, signed (whether it can be verified and installed from the app) and asset (the file this install would download; null when it cannot update itself). Reports only: nothing is downloaded or installed. Desktop app and fieldcraft-cli only"#,
form: Some(&[]),
kind: CommandKind::Session,
requires: &[],
diff --git a/crates/engine/src/crash.rs b/crates/engine/src/crash.rs
index 933cf48..9448cf8 100644
--- a/crates/engine/src/crash.rs
+++ b/crates/engine/src/crash.rs
@@ -493,7 +493,8 @@ fn hook(info: &std::panic::PanicHookInfo<'_>) -> bool {
// Outside any command: what the journal knows has to do.
let extra = from_journal(read_live_journal(state), None);
if let Some(id) = write_report(state, "panic", Some(&p), extra) {
- eprintln!("FieldCraft: internal error; crash report {}", state.dir.join(&id).display());
+ // OneBSpace (OneCAD Simulation): the fork's name on the console.
+ eprintln!("OneCAD Simulation: internal error; crash report {}", state.dir.join(&id).display());
if let Ok(mut j) = state.journal.try_lock() {
j.record(&json!({ "reported": id }));
}
@@ -890,7 +891,9 @@ fn unclean_exit(dir: &Path, build: &Build, journal: &Path) {
let p = match &native {
Some(n) => native_panic(n, &was, &when, &during, &what),
None => Panic {
- message: format!("FieldCraft {was} (started {when}) ended without a clean exit {during}"),
+ // OneBSpace (OneCAD Simulation): the fork's name in the crash message (shown in the
+ // crash question and in the report the user copies).
+ message: format!("OneCAD Simulation {was} (started {when}) ended without a clean exit {during}"),
location: match (&starting, &doing) {
(Some((p, _)), _) => format!("unclean exit during startup: {p}"),
(None, c) => format!("unclean exit in {}", c.as_deref().unwrap_or("(between commands)")),
@@ -958,7 +961,8 @@ fn native_panic(native: &Value, was: &str, when: &str, during: &str, what: &str)
backtrace.push(format!("on thread {t}"));
}
Panic {
- message: format!("FieldCraft {was} (started {when}) crashed with {name} ({code}) in {at} {during}"),
+ // OneBSpace (OneCAD Simulation): the fork's name in the native-crash message.
+ message: format!("OneCAD Simulation {was} (started {when}) crashed with {name} ({code}) in {at} {during}"),
location: format!("native exception in {at}"),
thread: native.get("thread").and_then(Value::as_u64).map_or_else(|| "(unknown)".into(), |t| format!("native thread {t}")),
backtrace,
diff --git a/crates/ui-egui/src/appbar.rs b/crates/ui-egui/src/appbar.rs
index c575dd8..9341c8d 100644
--- a/crates/ui-egui/src/appbar.rs
+++ b/crates/ui-egui/src/appbar.rs
@@ -61,49 +61,17 @@ fn button_style(t: &Tokens) -> IconButtonStyle {
}
}
-/// FieldCraft's mark: the application icon's fringe cube (`assets/app-icon/icon-small.svg`, after
-/// `xtask/src/app_icon.rs`) drawn in code without its tile or streamline: each visible face split
-/// into small cells coloured by the fringe band at the cell's centre, shaded per face.
-fn mark(p: &egui::Painter, c: egui::Pos2) {
- // The cube is 2 units tall on screen (half side 0.5, isometric); draw it 22 points tall.
- const S: f32 = 11.0;
- const N: usize = 8;
- const FRINGE: [(u8, u8, u8); 7] =
- [(0x2c, 0x4f, 0xbf), (0x2f, 0x86, 0xe0), (0x22, 0xbc, 0xd8), (0x3f, 0xc5, 0x84), (0xf0, 0xd1, 0x3a), (0xf2, 0x8a, 0x2b), (0xde, 0x3b, 0x2f)];
- const RADII: [f32; 6] = [1.28, 1.07, 0.87, 0.67, 0.47, 0.27];
- let at = |q: [f32; 3]| c + vec2((q[0] - q[1]) * 0.866 * S, ((q[0] + q[1]) * 0.5 - q[2]) * S);
- // Each face: origin corner, two edge vectors, and how much it is darkened (0 to 1).
- let faces: [([f32; 3], [f32; 3], [f32; 3], f32); 3] = [
- ([-0.5, -0.5, 0.5], [1.0, 0.0, 0.0], [0.0, 1.0, 0.0], 0.0),
- ([-0.5, 0.5, -0.5], [1.0, 0.0, 0.0], [0.0, 0.0, 1.0], 0.12),
- ([0.5, -0.5, -0.5], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0], 0.3),
- ];
- let point = |o: [f32; 3], u: [f32; 3], v: [f32; 3], a: f32, b: f32| [0, 1, 2].map(|k| o[k] + u[k] * a + v[k] * b);
- for (o, u, v, shade) in faces {
- for i in 0..N {
- for j in 0..N {
- let (a0, a1, b0, b1) = (i as f32 / N as f32, (i + 1) as f32 / N as f32, j as f32 / N as f32, (j + 1) as f32 / N as f32);
- let m = point(o, u, v, (a0 + a1) / 2.0, (b0 + b1) / 2.0);
- let r = m.iter().map(|x| (0.5 - x) * (0.5 - x)).sum::().sqrt();
- let band = RADII.iter().filter(|&&rad| r < rad).count();
- let (cr, cg, cb) = FRINGE.get(band).copied().unwrap_or(FRINGE[0]);
- let k = 1.0 - shade;
- let col = Color32::from_rgb((cr as f32 * k) as u8, (cg as f32 * k) as u8, (cb as f32 * k) as u8);
- let quad = vec![at(point(o, u, v, a0, b0)), at(point(o, u, v, a1, b0)), at(point(o, u, v, a1, b1)), at(point(o, u, v, a0, b1))];
- // A hairline in the cell's own colour closes the seams between neighbouring cells.
- p.add(egui::Shape::convex_polygon(quad, col, Stroke::new(0.5, col)));
- }
- }
- }
-}
+// OneBSpace (OneCAD Simulation): upstream's drawn fringe-cube mark (`mark`, after
+// `assets/app-icon/icon-small.svg`) is replaced by a painted text wordmark, so the bar names
+// the fork in every width variant (a narrow bar loses the menus, not the app's own name).
+pub const APP_NAME: &str = "OneCAD Simulation";
/// Where the title bar's parts go.
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct BarLayout {
- /// The mark's centre, and where the app's name starts (none when compact).
+ /// The wordmark's left anchor ("OneCAD Simulation", painted text).
pub mark: egui::Pos2,
- pub name: Option,
- /// File, Save, Undo, Redo: after the mark, at the left.
+ /// File, Save, Undo, Redo: after the wordmark, at the left.
pub quick: [Rect; 4],
/// Solve, then Search, Theme and Help: at the right end, before the version.
pub solve: Rect,
@@ -112,19 +80,23 @@ pub struct BarLayout {
pub tab_room: (f32, f32),
/// The version's right edge.
pub version_right: f32,
- /// Too narrow for labels: no name, and Solve without its word.
+ /// Too narrow for menus: Solve without its word (the wordmark still shows).
pub compact: bool,
}
/// The title bar's layout in `bar`. `traffic_lights`: the macOS window buttons sit over its left
/// end (an integrated title bar out of full screen, where there are none). `captions`: the width
-/// of the custom caption buttons at its right end; `version_w`: the version text's width.
-pub fn bar_layout(bar: Rect, traffic_lights: bool, captions: f32, version_w: f32) -> BarLayout {
+/// of the custom caption buttons at its right end; `version_w`: the version text's width;
+/// `name_w`: the wordmark's width (OneBSpace (OneCAD Simulation): the quick actions start after
+/// the wordmark, in every width variant).
+pub fn bar_layout(bar: Rect, traffic_lights: bool, captions: f32, version_w: f32, name_w: f32) -> BarLayout {
let left = bar.left() + if traffic_lights { crate::titlebar::TRAFFIC_LIGHTS } else { 0.0 };
let compact = bar.right() - left < 760.0;
let cy = bar.center().y;
let button = |x: f32| Rect::from_center_size(pos2(x + BUTTON / 2.0, cy), Vec2::splat(BUTTON));
- let x0 = left + if compact { 44.0 } else { 132.0 };
+ // OneBSpace (OneCAD Simulation): the quick actions start after the wordmark in compact
+ // layouts too (upstream's compact bar dropped the name and started at the bare mark).
+ let x0 = left + 14.0 + name_w + 22.0;
let quick = [0.0, 1.0, 2.0, 3.0].map(|i| button(x0 + i * STRIDE));
let version_right = bar.right() - 12.0 - captions;
let tools_end = version_right - version_w - 14.0;
@@ -132,8 +104,7 @@ pub fn bar_layout(bar: Rect, traffic_lights: bool, captions: f32, version_w: f32
let solve_w = if compact { 30.0 } else { 74.0 };
let solve = Rect::from_min_size(pos2(tools[0].left() - 10.0 - solve_w, cy - 12.0), vec2(solve_w, 24.0));
BarLayout {
- mark: pos2(left + 20.0, cy),
- name: (!compact).then(|| pos2(left + 36.0, cy)),
+ mark: pos2(left + 14.0, cy),
quick,
solve,
tools,
@@ -161,11 +132,11 @@ pub fn app_bar(app: &mut ModelApp, ui: &mut egui::Ui) {
let captions = if app.custom_titlebar { crate::titlebar::WIDTH } else { 0.0 };
let version = format!("v{}", crate::VERSION);
let version_w = ui.painter().layout_no_wrap(version.clone(), FontId::proportional(11.0), t.text_dim).size().x;
- let lay = bar_layout(r, app.integrated_titlebar && !fullscreen(ui.ctx()), captions, version_w);
- mark(ui.painter(), lay.mark);
- if let Some(at) = lay.name {
- ui.painter().text(at, Align2::LEFT_CENTER, "FieldCraft", FontId::proportional(14.0), t.app_bar_text);
- }
+ // OneBSpace (OneCAD Simulation): the wordmark is measured so the quick actions clear it.
+ let name_w = ui.painter().layout_no_wrap(APP_NAME.to_string(), FontId::proportional(14.0), t.app_bar_text).size().x;
+ let lay = bar_layout(r, app.integrated_titlebar && !fullscreen(ui.ctx()), captions, version_w, name_w);
+ // OneBSpace (OneCAD Simulation): painted wordmark instead of the drawn mark + name.
+ ui.painter().text(lay.mark, Align2::LEFT_CENTER, APP_NAME, FontId::proportional(14.0), t.app_bar_text);
let (undo, redo) = app.session.undo_depth();
let busy = app.busy().is_some();
let file_open = app.ui.menu.as_deref() == Some("file");
@@ -336,30 +307,16 @@ fn help_menu(app: &mut ModelApp, ui: &mut egui::Ui) {
ui.label("Left drag orbits (or pans or zooms: the navigation bar), right or middle drag pans, the wheel zooms, F or a double click fits.");
ui.label(format!("S or {} searches every command; the command line at the bottom runs `id {{json}}`.", shortcut("K")));
ui.separator();
- let report = ui
- .button("Report a Bug…")
- .on_hover_text("Draft a GitHub issue with the version, the OS and the last error; nothing is sent until you submit it")
- .clicked();
- let (mut check, mut reinstall) = (false, false);
- if app.updates_available() {
- check =
- ui.button("Check for Updates").on_hover_text("Ask GitHub Releases whether a newer FieldCraft is published (app.update.check)").clicked();
- reinstall = ui
- .button("Reinstall FieldCraft…")
- .on_hover_text("Download this version again, verify it and swap it in, to repair a damaged install")
- .clicked();
- }
+ // OneBSpace (OneCAD Simulation): upstream's "Report a Bug…", "Check for Updates" and
+ // "Reinstall FieldCraft…" items are gone — nothing here reaches GitHub or an update host.
+ // A report is drafted locally ("Report It…" after a crash, Help › Crash Reports) and copied
+ // out by hand; the version label names the fork.
let crashes = ui.button("Crash Reports…").on_hover_text("The crash reports saved on this computer: report, copy or delete them").clicked();
let settings = ui.button("Settings…").on_hover_text("Privacy and updates").clicked();
- ui.label(egui::RichText::new(format!("FieldCraft {}", crate::VERSION)).color(t.text_dim));
- if report {
- app.report_bug(None);
- } else if crashes {
+ // OneBSpace (OneCAD Simulation): the version label carries the fork's name.
+ ui.label(egui::RichText::new(format!("{} {}", APP_NAME, crate::VERSION)).color(t.text_dim));
+ if crashes {
app.open_crash_reports();
- } else if check {
- app.check_for_updates();
- } else if reinstall {
- app.reinstall();
} else if settings {
app.open_settings();
}
@@ -377,13 +334,16 @@ mod tests {
/// at the very left in full screen (where there are none).
#[test]
fn the_title_bar_keeps_solve_right_and_drops_the_traffic_light_inset_in_full_screen() {
+ // OneBSpace (OneCAD Simulation): the layout takes the wordmark's width; a plausible
+ // measured value stands in for the font here.
+ let name_w = 120.0;
let bar = Rect::from_min_size(egui::Pos2::ZERO, vec2(1400.0, HEIGHT));
- let windowed = bar_layout(bar, true, 0.0, 30.0);
- let full = bar_layout(bar, false, 0.0, 30.0);
+ let windowed = bar_layout(bar, true, 0.0, 30.0, name_w);
+ let full = bar_layout(bar, false, 0.0, 30.0, name_w);
assert_eq!(windowed.mark.x - full.mark.x, crate::titlebar::TRAFFIC_LIGHTS);
- assert!(full.mark.x < 30.0 && full.quick[0].left() < 150.0, "{full:?}");
+ assert!(full.mark.x < 30.0 && full.quick[0].left() < 200.0, "{full:?}");
for l in [windowed, full] {
- // Left to right: mark, quick actions, (tab), Solve, search, theme, help, version.
+ // Left to right: wordmark, quick actions, (tab), Solve, search, theme, help, version.
assert!(l.quick.windows(2).all(|w| w[0].right() <= w[1].left()));
assert!(l.quick[3].right() < l.tab_room.0 && l.tab_room.1 < l.solve.left());
assert!(l.solve.right() <= l.tools[0].left() && l.tools.windows(2).all(|w| w[0].right() <= w[1].left()));
@@ -392,10 +352,13 @@ mod tests {
}
// The right group does not move with full screen; custom caption buttons push it left.
assert_eq!(windowed.solve, full.solve);
- let captions = bar_layout(bar, false, crate::titlebar::WIDTH, 30.0);
+ let captions = bar_layout(bar, false, crate::titlebar::WIDTH, 30.0, name_w);
assert!((full.tools[2].right() - captions.tools[2].right() - crate::titlebar::WIDTH).abs() < 0.01);
- // Narrow: compact, still in order.
- let narrow = bar_layout(Rect::from_min_size(egui::Pos2::ZERO, vec2(700.0, HEIGHT)), true, 0.0, 30.0);
- assert!(narrow.compact && narrow.name.is_none() && narrow.quick[3].right() < narrow.solve.left());
+ // Narrow: compact, the wordmark still first and the quick actions after it, in order.
+ let narrow = bar_layout(Rect::from_min_size(egui::Pos2::ZERO, vec2(700.0, HEIGHT)), true, 0.0, 30.0, name_w);
+ assert!(narrow.compact && narrow.quick[3].right() < narrow.solve.left(), "{narrow:?}");
+ // OneBSpace (OneCAD Simulation): every width shows the wordmark, and the quick actions
+ // start after it (they no longer sit on the bare mark in the compact bar).
+ assert!(narrow.quick[0].left() >= narrow.mark.x + name_w, "{narrow:?}");
}
}
diff --git a/crates/ui-egui/src/navigation.rs b/crates/ui-egui/src/navigation.rs
index 2637a9b..bf7397a 100644
--- a/crates/ui-egui/src/navigation.rs
+++ b/crates/ui-egui/src/navigation.rs
@@ -77,7 +77,9 @@ pub const DEFAULT_PRESET: &str = "fieldcraft";
pub const NAV_PRESETS: [NavPreset; 7] = [
NavPreset {
id: DEFAULT_PRESET,
- label: "FieldCraft",
+ // OneBSpace (OneCAD Simulation): the preset's label names the fork (its `id`, which
+ // preferences store, stays upstream).
+ label: "OneCAD Simulation",
help: "Left drag does the navigation bar's mode (orbit, pan or zoom); right, middle or Shift+left drag pans",
reverse_zoom: false,
bindings: &[bind(Left, NavKeys::SHIFT, Pan), bind(Right, NavKeys::NONE, Pan), bind(Middle, NavKeys::NONE, Pan)],
diff --git a/crates/ui-egui/src/privacy.rs b/crates/ui-egui/src/privacy.rs
index 112e19f..ae12c26 100644
--- a/crates/ui-egui/src/privacy.rs
+++ b/crates/ui-egui/src/privacy.rs
@@ -12,10 +12,12 @@ use fieldcraft_engine::usage::{self, Event, Identity, Origin};
use crate::ModelApp;
use crate::files::Prompt;
-/// What is sent, event by event.
+/// What is sent, event by event. (OneBSpace (OneCAD Simulation): upstream's PRIVACY_URL linked
+/// out to github.com/tangency-labs/fieldcraft; the constant stays for reference but the UI no
+/// longer renders it as a link or opens it — nothing here browses anywhere.)
pub const PRIVACY_URL: &str = "https://github.com/tangency-labs/fieldcraft/blob/main/docs/privacy.md";
-/// The question, as the first run asks it.
-pub const QUESTION: &str = "Help improve FieldCraft by sharing anonymous usage: which tools you use, nothing from your models.";
+/// The question, as the first run asks it. (OneBSpace (OneCAD Simulation): fork name.)
+pub const QUESTION: &str = "Help improve OneCAD Simulation by sharing anonymous usage: which tools you use, nothing from your models.";
const DETAIL: &str = "Counted: the commands you run (their names, how long they took, whether they failed), the steps from a design to results, \
the samples you open, and the version, OS and a random id for this install. Never sent: file names or paths, geometry, model \
contents, parameter values or messages.";
@@ -143,14 +145,17 @@ pub fn show(app: &mut ModelApp, ctx: &egui::Context) {
let t = crate::theme::Tokens::get(app.ui.dark);
match app.prompt {
Some(Prompt::Consent) => {
- let (mut share, mut decline, mut link, mut updates) = (false, false, false, None);
- crate::frame::window(ctx, "Help Improve FieldCraft", crate::frame::Width::Normal).id(egui::Id::new("fc_consent")).show(ctx, |ui| {
+ // OneBSpace (OneCAD Simulation): the privacy note is plain text — the upstream
+ // GitHub link (PRIVACY_URL) is not rendered as a link and never opened.
+ let (mut share, mut decline, mut updates) = (false, false, None);
+ // OneBSpace (OneCAD Simulation): the fork's name in the dialog title.
+ crate::frame::window(ctx, "Help Improve OneCAD Simulation", crate::frame::Width::Normal).id(egui::Id::new("fc_consent")).show(ctx, |ui| {
ui.label(QUESTION);
ui.add_space(4.0);
ui.label(RichText::new(DETAIL).color(t.text_dim).size(11.0));
ui.add_space(2.0);
ui.label(RichText::new("You can change this any time in Help › Settings.").color(t.text_dim).size(11.0));
- link = ui.link("What is sent (docs/privacy.md)").on_hover_text(PRIVACY_URL).clicked();
+ ui.label(RichText::new("What is sent: docs/privacy.md in the repository.").color(t.text_dim).size(11.0));
if app.updates_available() {
ui.add_space(4.0);
updates = update_check(ui, &t, app.prefs.update_check);
@@ -161,9 +166,6 @@ pub fn show(app: &mut ModelApp, ctx: &egui::Context) {
decline = ui.button("Don't Share").clicked();
});
});
- if link {
- app.open_link(ctx, PRIVACY_URL);
- }
if let Some(on) = updates {
app.set_update_prefs(on, None);
}
@@ -176,15 +178,20 @@ pub fn show(app: &mut ModelApp, ctx: &egui::Context) {
Some(Prompt::Settings) => {
let available = app.usage_available();
let (mut sharing, mut automation) = (app.prefs.usage_sharing == Some(true), app.prefs.usage_automation);
- let (mut close, mut link, mut updates, mut unskip, mut check) = (false, false, None, false, false);
+ // OneBSpace (OneCAD Simulation): the privacy note is plain text — no link, no
+ // browser. The dialog never opens PRIVACY_URL.
+ let (mut close, mut updates, mut unskip, mut check) = (false, None, false, false);
crate::frame::window(ctx, "Settings", crate::frame::Width::Normal).id(egui::Id::new("fc_settings")).show(ctx, |ui| {
if app.updates_available() {
crate::frame::menu_heading(ui, &t, "UPDATES");
updates = update_check(ui, &t, app.prefs.update_check);
ui.horizontal(|ui| {
- check = ui.button("Check Now").on_hover_text("Help › Check for Updates").clicked();
+ // OneBSpace (OneCAD Simulation): the tooltip no longer points at Help ›
+ // Check for Updates (that menu item was removed with the fork's rebrand).
+ check = ui.button("Check Now").on_hover_text("Ask GitHub Releases for the latest version now").clicked();
if !app.prefs.update_skip.is_empty() {
- ui.label(RichText::new(format!("Skipping FieldCraft {}", app.prefs.update_skip)).color(t.text_dim).size(11.0));
+ // OneBSpace (OneCAD Simulation): the fork's name in the skip note.
+ ui.label(RichText::new(format!("Skipping OneCAD Simulation {}", app.prefs.update_skip)).color(t.text_dim).size(11.0));
unskip = ui.small_button("Offer It Again").clicked();
}
});
@@ -207,11 +214,13 @@ pub fn show(app: &mut ModelApp, ctx: &egui::Context) {
}
ui.label(RichText::new(DETAIL).color(t.text_dim).size(11.0));
ui.label(
- RichText::new("Crash reports and the log stay on this computer; Help › Report a Bug sends only what you submit.")
+ // OneBSpace (OneCAD Simulation): the report flow is local-only now (a draft
+ // to copy), so the note no longer promises a GitHub submission.
+ RichText::new("Crash reports and the log stay on this computer; a report is drafted here and copied out — nothing is sent anywhere.")
.color(t.text_dim)
.size(11.0),
);
- link = ui.link("What is sent (docs/privacy.md)").on_hover_text(PRIVACY_URL).clicked();
+ ui.label(RichText::new("What is sent: docs/privacy.md in the repository.").color(t.text_dim).size(11.0));
ui.add_space(6.0);
close = ui.button("Close").clicked();
});
@@ -224,9 +233,6 @@ pub fn show(app: &mut ModelApp, ctx: &egui::Context) {
if check {
app.check_for_updates();
}
- if link {
- app.open_link(ctx, PRIVACY_URL);
- }
if close || ctx.input(|i| i.key_pressed(egui::Key::Escape)) {
app.prompt = None;
}
@@ -241,11 +247,13 @@ fn update_check(ui: &mut egui::Ui, t: &crate::theme::Tokens, on: bool) -> Option
let changed = ui
.checkbox(&mut checked, "Check for updates automatically")
.on_hover_text(
- "At start-up, at most once a day, FieldCraft asks GitHub Releases for the latest version. Nothing installs until you choose Install.",
+ // OneBSpace (OneCAD Simulation): the fork's name in the tooltip (desktop-only check).
+ "At start-up, at most once a day, OneCAD Simulation asks GitHub Releases for the latest version. Nothing installs until you choose Install.",
)
.changed();
ui.label(
- RichText::new("The check sends only the request (your IP address and the FieldCraft version reach GitHub); off means no check.")
+ // OneBSpace (OneCAD Simulation): the fork's name in the note.
+ RichText::new("The check sends only the request (your IP address and the OneCAD Simulation version reach GitHub); off means no check.")
.color(t.text_dim)
.size(11.0),
);
diff --git a/crates/ui-egui/src/report.rs b/crates/ui-egui/src/report.rs
index 9acbe79..9c062e5 100644
--- a/crates/ui-egui/src/report.rs
+++ b/crates/ui-egui/src/report.rs
@@ -1,13 +1,13 @@
-//! Help › Report a Bug, and the question the window asks after a crash ("FieldCraft closed
-//! unexpectedly — Report it").
+//! Help › Crash Reports, "Report It…" after a crash ("OneCAD Simulation closed unexpectedly —
+//! Report it"), and the Report a Bug form they open.
//!
-//! The form shows exactly what the GitHub issue form will be filled with
-//! ([`fieldcraft_engine::bug_report`]): the version, the OS, what happened (the last error by
-//! default) and, after a crash, where it happened. **Share my session** adds the commands that
-//! built the model, **Include the model file** the model as well. Nothing leaves the computer
-//! until the user clicks **Open GitHub Issue**, which opens the filled form in their browser (they
-//! submit it there, or not); files too big for the link are saved to a folder to attach from, and
-//! a long session is also put on the clipboard.
+// OneBSpace (OneCAD Simulation): upstream opened the filled GitHub issue form in the browser;
+// the fork's report flow is local-only — the form shows exactly what the draft holds
+// ([`fieldcraft_engine::bug_report`]): the version, the OS, what happened (the last error by
+// default) and, after a crash, where it happened. **Share my session** adds the commands that
+// built the model, **Include the model file** the model as well. **Copy report** puts it all on
+// the clipboard (nothing opens, nothing is sent); attachments are saved to a local folder to
+// attach from wherever the user files their reports.
use egui::RichText;
use fieldcraft_engine::bug_report::{self, Draft, Input};
@@ -169,37 +169,29 @@ impl ModelApp {
}
}
- /// Open the draft in the browser: attachments saved to a folder of their own, the session on
- /// the clipboard when it is too long for the link.
- fn send_report(&mut self, ctx: &egui::Context, draft: &Draft) {
- let mut saved = None;
- if !draft.attachments.is_empty() {
+ // OneBSpace (OneCAD Simulation): the report never leaves the workspace — no GitHub issue
+ // form is opened (upstream opened the draft's ISSUE_URL). The draft's text goes to the
+ // clipboard and any attachments stay in the local bug-reports folder to attach by hand.
+ fn copy_report(&mut self, ctx: &egui::Context, draft: &Draft) {
+ let mut text = draft.title.clone();
+ for (k, v) in &draft.fields {
+ if !v.is_empty() {
+ text.push_str(&format!("\n\n{k}:\n{v}"));
+ }
+ }
+ if let Some(session) = &draft.clipboard {
+ text.push_str(&format!("\n\nsession:\n{session}"));
+ }
+ ctx.copy_text(text);
+ let note = if draft.attachments.is_empty() {
+ "Report copied to the clipboard — paste it into your own issue tracker.".to_string()
+ } else {
match bug_report::save_attachments(draft) {
- Ok(dir) => saved = Some(dir),
- Err(e) => {
- self.set_status(format!("Report a Bug: could not save the files to attach: {e}"), true);
- return;
- }
+ Ok(dir) => format!("Report copied to the clipboard: attach the files in {}.", dir.display()),
+ Err(e) => format!("Report copied to the clipboard (the files to attach could not be saved: {e})."),
}
- }
- if let Some(text) = &draft.clipboard {
- ctx.copy_text(text.clone());
- }
- match &self.services.open_url {
- Some(open) => {
- if let Err(e) = open(&draft.url) {
- self.set_status(format!("Report a Bug: could not open the browser: {e}"), true);
- return;
- }
- }
- None => ctx.open_url(egui::OpenUrl::new_tab(draft.url.clone())),
- }
- log::info!("bug report opened in the browser ({} bytes, {} attachment(s))", draft.url.len(), draft.attachments.len());
- let text = match saved {
- Some(dir) => format!("The issue form opened in your browser: attach the files in {} and submit it there.", dir.display()),
- None => "The issue form opened in your browser: review it and submit it there.".to_string(),
};
- self.set_status(text, false);
+ self.set_status(note, false);
self.prompt = None;
self.report = None;
}
@@ -226,10 +218,11 @@ fn size(bytes: usize) -> String {
}
fn kind_label(kind: &str) -> &'static str {
+ // OneBSpace (OneCAD Simulation): the fork's name in the crash headings.
match kind {
- "unclean_exit" => "FieldCraft closed unexpectedly",
+ "unclean_exit" => "OneCAD Simulation closed unexpectedly",
"command_panic" => "A command hit an internal error",
- _ => "FieldCraft hit an internal error",
+ _ => "OneCAD Simulation hit an internal error",
}
}
@@ -245,8 +238,9 @@ pub fn show(app: &mut ModelApp, ctx: &egui::Context) {
let (mut report, mut close) = (false, false);
crate::frame::window(ctx, kind_label(&first.kind), crate::frame::Width::Normal).id(egui::Id::new("fc_crashed")).show(ctx, |ui| {
ui.label(match first.kind.as_str() {
- "unclean_exit" => "FieldCraft closed unexpectedly the last time it ran.",
- _ => "FieldCraft hit an internal error the last time it ran.",
+ // OneBSpace (OneCAD Simulation): the fork's name in the crash question.
+ "unclean_exit" => "OneCAD Simulation closed unexpectedly the last time it ran.",
+ _ => "OneCAD Simulation hit an internal error the last time it ran.",
});
ui.label(RichText::new(&first.message).color(t.text_dim));
if reports.len() > 1 {
@@ -254,8 +248,10 @@ pub fn show(app: &mut ModelApp, ctx: &egui::Context) {
}
ui.add_space(4.0);
ui.label(
+ // OneBSpace (OneCAD Simulation): reporting drafts locally — no GitHub issue
+ // is opened; the user copies the report into their own tracker.
RichText::new(
- "A crash report was saved on this computer. Reporting it opens a GitHub issue you review first; nothing is sent until you submit it.",
+ "A crash report was saved on this computer. Reporting it drafts a report that stays in the workspace: copy it into your own issue tracker; nothing is sent anywhere.",
)
.color(t.text_dim),
);
@@ -285,7 +281,9 @@ pub fn show(app: &mut ModelApp, ctx: &egui::Context) {
ui.label("No crash reports are saved on this computer.");
} else {
ui.label(
- RichText::new("Saved on this computer, newest first. Reporting one opens a GitHub issue you review first; nothing is sent until you submit it.")
+ // OneBSpace (OneCAD Simulation): reporting drafts locally — no GitHub
+ // issue is opened; the report is copied out by hand.
+ RichText::new("Saved on this computer, newest first. Reporting one drafts a report that stays in the workspace: copy it into your own issue tracker.")
.color(t.text_dim),
);
ui.add_space(4.0);
@@ -344,14 +342,14 @@ pub fn show(app: &mut ModelApp, ctx: &egui::Context) {
app.prompt = None;
return;
};
- let (mut send, mut close) = (false, false);
+ let (mut copy, mut close) = (false, false);
let commands = form.input.commands.len();
crate::frame::window(ctx, "Report a Bug", crate::frame::Width::Wide).id(egui::Id::new("fc_report_bug")).show(ctx, |ui| {
ui.label(
- RichText::new(
- "This opens a GitHub issue in your browser, filled in with what is shown below. Nothing is sent until you submit it there.",
- )
- .color(t.text_dim),
+ // OneBSpace (OneCAD Simulation): the report stays in the workspace — it is
+ // copied to the clipboard, never opened as a GitHub issue in the browser.
+ RichText::new("Your report stays in the workspace: copy it and paste it into your own issue tracker. Nothing is sent anywhere.")
+ .color(t.text_dim),
);
if let Some(p) = &form.problem {
ui.label(RichText::new(p).color(t.error));
@@ -386,11 +384,12 @@ pub fn show(app: &mut ModelApp, ctx: &egui::Context) {
let draft = form.draft().clone();
ui.add_space(6.0);
ui.horizontal(|ui| {
- send = ui.button("Open GitHub Issue").clicked();
+ // OneBSpace (OneCAD Simulation): "Copy report" instead of "Open GitHub Issue".
+ copy = ui.button("Copy report").clicked();
close = ui.button("Cancel").clicked();
});
ui.add_space(4.0);
- egui::CollapsingHeader::new("What is sent").id_salt("fc_report_sent").default_open(true).show(ui, |ui| {
+ egui::CollapsingHeader::new("What is in the report").id_salt("fc_report_sent").default_open(true).show(ui, |ui| {
egui::ScrollArea::vertical().max_height(180.0).show(ui, |ui| {
ui.label(RichText::new(format!("Title: {}", draft.title)).monospace().size(11.0));
for (k, v) in &draft.fields {
@@ -403,15 +402,17 @@ pub fn show(app: &mut ModelApp, ctx: &egui::Context) {
ui.label(RichText::new(format!("Attach {} ({}): {}", a.name, size(a.bytes.len()), a.what)).size(11.0).color(t.accent));
}
if draft.clipboard.is_some() {
- ui.label(RichText::new("The session goes on the clipboard too, to paste.").size(11.0).color(t.text_dim));
+ // OneBSpace (OneCAD Simulation): the session is copied with the report.
+ ui.label(RichText::new("The session is copied with the report.").size(11.0).color(t.text_dim));
}
});
});
});
let draft = form.draft().clone();
app.report = Some(form);
- if send {
- app.send_report(ctx, &draft);
+ // OneBSpace (OneCAD Simulation): the copied report never touches the network.
+ if copy {
+ app.copy_report(ctx, &draft);
} else if close || ctx.input(|i| i.key_pressed(egui::Key::Escape)) {
app.prompt = None;
app.report = None;
diff --git a/crates/ui-egui/src/updates.rs b/crates/ui-egui/src/updates.rs
index f55cdac..fa5a868 100644
--- a/crates/ui-egui/src/updates.rs
+++ b/crates/ui-egui/src/updates.rs
@@ -123,9 +123,9 @@ impl ModelApp {
self.set_status(format!("Cannot reinstall: {why}"), true);
return;
}
- u.busy = Some(format!("Downloading FieldCraft {}…", crate::VERSION));
+ u.busy = Some(format!("Downloading OneCAD Simulation {}…", crate::VERSION)); // OneBSpace (OneCAD Simulation): fork name in the status
(u.host.start)(Job::Reinstall);
- self.set_status(format!("Downloading FieldCraft {} to reinstall it…", crate::VERSION), false);
+ self.set_status(format!("Downloading OneCAD Simulation {} to reinstall it…", crate::VERSION), false); // OneBSpace (OneCAD Simulation)
}
/// The notice's Install: download and verify, then ask to restart. A copy that cannot
@@ -133,15 +133,16 @@ impl ModelApp {
pub fn install_update(&mut self, ctx: &egui::Context) {
let Some(u) = &mut self.updates else { return };
let Some(release) = u.available.clone() else { return };
- let blocked = u.host.unsupported.clone().or_else(|| (!release.signed()).then(|| format!("FieldCraft {} is not signed", release.version)));
+ // OneBSpace (OneCAD Simulation): the fork's name in the not-signed status.
+ let blocked = u.host.unsupported.clone().or_else(|| (!release.signed()).then(|| format!("OneCAD Simulation {} is not signed", release.version)));
if let Some(why) = blocked {
self.set_status(format!("{why}: opening the download page"), true);
self.open_link(ctx, &release.url);
return;
}
- u.busy = Some(format!("Downloading FieldCraft {}…", release.version));
+ u.busy = Some(format!("Downloading OneCAD Simulation {}…", release.version)); // OneBSpace (OneCAD Simulation)
(u.host.start)(Job::Stage(release.clone()));
- self.set_status(format!("Downloading FieldCraft {}…", release.version), false);
+ self.set_status(format!("Downloading OneCAD Simulation {}…", release.version), false); // OneBSpace (OneCAD Simulation)
}
/// Skip the offered version: the automatic check no longer offers it.
@@ -178,7 +179,7 @@ impl ModelApp {
&& let Some((s, Finish::Swap(_))) = &u.staged
{
let v = s.version.to_string();
- self.set_status(format!("FieldCraft {v} installs when you quit"), false);
+ self.set_status(format!("OneCAD Simulation {v} installs when you quit"), false); // OneBSpace (OneCAD Simulation)
}
return;
}
@@ -234,14 +235,16 @@ impl ModelApp {
let v = check.latest.version.to_string();
u.available = Some(check.latest);
if manual {
- self.set_status(format!("FieldCraft {v} is available"), false);
+ // OneBSpace (OneCAD Simulation): the fork's name in the status.
+ self.set_status(format!("OneCAD Simulation {v} is available"), false);
}
}
Ok(check) => {
// Nothing newer (or skipped): a notice from an earlier check goes.
u.available = None;
if manual {
- self.set_status(format!("FieldCraft {} is up to date", check.current), false);
+ // OneBSpace (OneCAD Simulation): the fork's name in the status.
+ self.set_status(format!("OneCAD Simulation {} is up to date", check.current), false);
}
}
Err(e) if manual => self.set_status(format!("Could not check for updates: {e}"), true),
@@ -310,7 +313,8 @@ pub fn notice(app: &mut ModelApp, ui: &mut egui::Ui) {
if ui.add(egui::Link::new(RichText::new("Reload to update").size(11.5))).on_hover_text(tip).clicked() {
reload();
}
- ui.label(RichText::new("A new version of FieldCraft is available —").size(11.5).color(t.text));
+ // OneBSpace (OneCAD Simulation): the fork's name in the status-bar notice.
+ ui.label(RichText::new("A new version of OneCAD Simulation is available —").size(11.5).color(t.text));
ui.separator();
return;
}
@@ -328,7 +332,8 @@ pub fn notice(app: &mut ModelApp, ui: &mut egui::Ui) {
let install = ui.add(egui::Link::new(small("Install"))).on_hover_text("Download, verify and install it; you choose when to restart").clicked();
ui.label(small("·").color(t.text_dim));
let notes = ui.add(egui::Link::new(small("What's new"))).on_hover_text(release.url.as_str()).clicked();
- ui.label(small(&format!("FieldCraft {} is available —", release.version)).color(t.text));
+ // OneBSpace (OneCAD Simulation): the fork's name in the status-bar notice.
+ ui.label(small(&format!("OneCAD Simulation {} is available —", release.version)).color(t.text));
ui.separator();
if notes {
app.open_link(ui.ctx(), &release.url);
@@ -353,12 +358,13 @@ pub fn show(app: &mut ModelApp, ctx: &egui::Context) {
};
let reinstall = staged.version.to_string() == crate::VERSION;
let (mut restart, mut later, mut open) = (false, false, false);
- crate::frame::window(ctx, "Update FieldCraft", crate::frame::Width::Normal).id(egui::Id::new("fc_update")).show(ctx, |ui| match &finish {
+ // OneBSpace (OneCAD Simulation): the fork's name in the window title.
+ crate::frame::window(ctx, "Update OneCAD Simulation", crate::frame::Width::Normal).id(egui::Id::new("fc_update")).show(ctx, |ui| match &finish {
Finish::Swap(_) => {
ui.label(if reinstall {
- format!("FieldCraft {} was downloaded again and verified. Restart to reinstall it?", staged.version)
+ format!("OneCAD Simulation {} was downloaded again and verified. Restart to reinstall it?", staged.version)
} else {
- format!("FieldCraft {} is downloaded and verified. Restart now to finish installing it?", staged.version)
+ format!("OneCAD Simulation {} is downloaded and verified. Restart now to finish installing it?", staged.version)
});
ui.label(
RichText::new(format!("It replaces {}. Unsaved changes are saved or asked about first.", staged.install.describe()))
@@ -368,11 +374,11 @@ pub fn show(app: &mut ModelApp, ctx: &egui::Context) {
ui.add_space(6.0);
ui.horizontal(|ui| {
restart = ui.button("Restart Now").clicked();
- later = ui.button("Later").on_hover_text("It installs when you quit FieldCraft").clicked();
+ later = ui.button("Later").on_hover_text("It installs when you quit OneCAD Simulation").clicked(); // OneBSpace (OneCAD Simulation)
});
}
Finish::Package { file, command } => {
- ui.label(format!("FieldCraft {} is downloaded and verified:", staged.version));
+ ui.label(format!("OneCAD Simulation {} is downloaded and verified:", staged.version)); // OneBSpace (OneCAD Simulation)
ui.label(RichText::new(file.display().to_string()).monospace().size(11.0));
ui.label("Install it with your system's package manager:");
let mut text = command.clone();
@@ -516,7 +522,7 @@ mod tests {
tx.send(Event::Checked { manual: true, result: Ok(Check { current: current.clone(), latest: release(crate::VERSION) }) }).unwrap();
a.poll_updates(&ctx);
- assert_eq!(a.status.as_ref().map(|s| s.text.clone()), Some(format!("FieldCraft {} is up to date", crate::VERSION)));
+ assert_eq!(a.status.as_ref().map(|s| s.text.clone()), Some(format!("OneCAD Simulation {} is up to date", crate::VERSION))); // OneBSpace (OneCAD Simulation)
assert_eq!(a.update_offered(), None, "the earlier offer goes");
tx.send(Event::Checked { manual: false, result: Err("offline".into()) }).unwrap();
a.status = None;