mirror of
https://github.com/storytold/cadcraft.git
synced 2026-10-30 05:46:50 -06:00
Update prompt shows the app icon and accent color instead of a letter (#2479)
UPDATE_APP (native builds; craft-update is a native-only dependency) carries our 128 px icon and accent (#3ea6e8, its colour in ArtCraft Launcher). The updater, the self-update helper and craft-update's startup prompt all get them through crate::UPDATE_APP; the prompt draws the icon, the accent and "by ArtCraft" (craft-update's default developer). craft-update is pinned to storytold/craft-libs main at 1065653e7 (#434). Clippy fixes for Rust 1.99 in untouched code (same logic): - crates/constraints/src/auto.rs - crates/engine/src/audit.rs - crates/engine/src/cmd/inquiry.rs - crates/engine/src/mtext_edit.rs - crates/geom/src/nurbs.rs - crates/io/src/dxf_raw.rs - crates/io/src/dxf_read/document.rs - crates/render/src/text.rs - crates/ui-egui/src/cmdline.rs - xtask/src/layers.rs
This commit is contained in:
Generated
+2
-1
@@ -1191,13 +1191,14 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "craft-update"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/storytold/craft-libs?rev=92d392cff132eaf53e13afff77f38b5c11b73aa0#92d392cff132eaf53e13afff77f38b5c11b73aa0"
|
||||
source = "git+https://github.com/storytold/craft-libs?rev=1065653e75854e9c17e1ff563acdd344c1b185f0#1065653e75854e9c17e1ff563acdd344c1b185f0"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"dunce",
|
||||
"egui",
|
||||
"flate2",
|
||||
"getrandom 0.3.4",
|
||||
"image",
|
||||
"log",
|
||||
"plist",
|
||||
"semver",
|
||||
|
||||
+2
-1
@@ -65,7 +65,8 @@ eframe = { version = "0.37", default-features = false }
|
||||
egui-wgpu = "0.37"
|
||||
# Monotonic time on native and web (performance.now on wasm).
|
||||
web-time = "1.1"
|
||||
craft-update = { git = "https://github.com/storytold/craft-libs", version = "=0.1.0", rev = "92d392cff132eaf53e13afff77f38b5c11b73aa0", features = ["egui"] }
|
||||
# craft-update with storytold/craft-libs#434: the update prompt shows the app's icon, accent and developer.
|
||||
craft-update = { git = "https://github.com/storytold/craft-libs", version = "=0.1.0", rev = "1065653e75854e9c17e1ff563acdd344c1b185f0", features = ["egui"] }
|
||||
rfd = "0.17"
|
||||
arboard = { version = "3.6", default-features = false }
|
||||
|
||||
|
||||
@@ -218,7 +218,7 @@ fn main() -> eframe::Result {
|
||||
let logger = logging::install();
|
||||
// The update helper relaunches this binary after a self-update; it runs and exits here.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
if let Some(done) = craft_update::self_update::finish(&craft_update::suite::CADCRAFT, &std::env::args_os().skip(1).collect::<Vec<_>>()) {
|
||||
if let Some(done) = craft_update::self_update::finish(&cadcraft_ui_egui::UPDATE_APP, &std::env::args_os().skip(1).collect::<Vec<_>>()) {
|
||||
if let Err(e) = done {
|
||||
eprintln!("CADCraft update helper failed: {e}");
|
||||
std::process::exit(1);
|
||||
|
||||
@@ -52,15 +52,11 @@ fn collect(d: &Drawing, handles: &[Handle]) -> Geo {
|
||||
g.curves.push((GeomRef::whole(h), ga.center, a.radius));
|
||||
}
|
||||
}
|
||||
EntityKind::Circle(c) => {
|
||||
if c.center.is_finite() && c.radius.is_finite() {
|
||||
g.curves.push((GeomRef::whole(h), c.center.xy(), c.radius));
|
||||
}
|
||||
EntityKind::Circle(c) if c.center.is_finite() && c.radius.is_finite() => {
|
||||
g.curves.push((GeomRef::whole(h), c.center.xy(), c.radius));
|
||||
}
|
||||
EntityKind::Point(p) => {
|
||||
if p.p.is_finite() {
|
||||
g.points.push((GeomRef::whole(h), p.p.xy()));
|
||||
}
|
||||
EntityKind::Point(p) if p.p.is_finite() => {
|
||||
g.points.push((GeomRef::whole(h), p.p.xy()));
|
||||
}
|
||||
EntityKind::LwPolyline(p) => {
|
||||
let n = p.vertices.len();
|
||||
|
||||
@@ -460,17 +460,13 @@ fn references(d: &mut Drawing, out: &mut Vec<Issue>) {
|
||||
m.style = "Standard".into();
|
||||
}
|
||||
}
|
||||
EntityKind::Table(t) => {
|
||||
if !has_name(&d.table_styles, &t.style, |s| &s.name) {
|
||||
note("table style", &t.style);
|
||||
t.style = "Standard".into();
|
||||
}
|
||||
EntityKind::Table(t) if !has_name(&d.table_styles, &t.style, |s| &s.name) => {
|
||||
note("table style", &t.style);
|
||||
t.style = "Standard".into();
|
||||
}
|
||||
EntityKind::Leader(l) => {
|
||||
if !ok_dim(d, &l.style) {
|
||||
note("dimension style", &l.style);
|
||||
l.style = "Standard".into();
|
||||
}
|
||||
EntityKind::Leader(l) if !ok_dim(d, &l.style) => {
|
||||
note("dimension style", &l.style);
|
||||
l.style = "Standard".into();
|
||||
}
|
||||
EntityKind::Dimension(dim) => {
|
||||
if !ok_dim(d, &dim.style) {
|
||||
|
||||
@@ -840,11 +840,9 @@ impl Interactive for DistM {
|
||||
let model = model_points(&self.sources);
|
||||
s.echo(format!("Distance = {}", fmt_d(s, path_len(model.as_deref().unwrap_or(pts), &self.bulges))));
|
||||
}
|
||||
Input::Keyword(k) if k == "Undo" => {
|
||||
if pts.len() > 1 {
|
||||
self.arcs.undo(pts, &mut self.bulges);
|
||||
self.sources.pop();
|
||||
}
|
||||
Input::Keyword(k) if k == "Undo" && pts.len() > 1 => {
|
||||
self.arcs.undo(pts, &mut self.bulges);
|
||||
self.sources.pop();
|
||||
}
|
||||
Input::Keyword(k) if k == "Length" => self.length = true,
|
||||
Input::Keyword(k) if k == "Total" => return self.total(s, false),
|
||||
@@ -852,10 +850,8 @@ impl Interactive for DistM {
|
||||
self.arcs.close(pts, &mut self.bulges)?;
|
||||
return self.total(s, true);
|
||||
}
|
||||
Input::Keyword(k) => {
|
||||
if !self.arcs.keyword(&k, pts) {
|
||||
s.echo(format!("{k}: not available yet"));
|
||||
}
|
||||
Input::Keyword(k) if !self.arcs.keyword(&k, pts) => {
|
||||
s.echo(format!("{k}: not available yet"));
|
||||
}
|
||||
Input::Enter => return self.total(s, false),
|
||||
_ => {}
|
||||
|
||||
@@ -136,11 +136,9 @@ impl Formatted {
|
||||
i += 2;
|
||||
match code {
|
||||
None => {}
|
||||
Some('P') => {
|
||||
if f.paras.len() < MAX_PARAS {
|
||||
f.push_char('\n', &cur);
|
||||
f.paras.push(props.clone());
|
||||
}
|
||||
Some('P') if f.paras.len() < MAX_PARAS => {
|
||||
f.push_char('\n', &cur);
|
||||
f.paras.push(props.clone());
|
||||
}
|
||||
Some(c @ ('\\' | '{' | '}')) => f.push_char(c, &cur),
|
||||
Some('L') => cur.underline = true,
|
||||
|
||||
@@ -487,7 +487,7 @@ impl Spline {
|
||||
|
||||
/// Arc length between parameters `a` and `b` (adaptive Gauss–Legendre over each knot span).
|
||||
pub fn length_between(&self, a: f64, b: f64) -> f64 {
|
||||
if !self.is_valid() || !(a.is_finite() && b.is_finite()) {
|
||||
if !(self.is_valid() && a.is_finite() && b.is_finite()) {
|
||||
return 0.0;
|
||||
}
|
||||
let (lo, hi) = self.domain();
|
||||
|
||||
@@ -135,10 +135,8 @@ fn head(tags: &[Tag]) -> Head {
|
||||
h.has_reactors |= group.as_deref() == Some("ACAD_REACTORS");
|
||||
}
|
||||
(_, Some("ACAD_REACTORS")) => h.reactors.push(norm(&t.str())),
|
||||
(_, Some("ACAD_XDICTIONARY")) => {
|
||||
if h.xdict.is_none() {
|
||||
h.xdict = Some(norm(&t.str()));
|
||||
}
|
||||
(_, Some("ACAD_XDICTIONARY")) if h.xdict.is_none() => {
|
||||
h.xdict = Some(norm(&t.str()));
|
||||
}
|
||||
(_, Some(_)) => {}
|
||||
(5 | 105, None) if h.handle.is_none() => h.handle = Some(norm(&t.str())),
|
||||
|
||||
@@ -35,13 +35,11 @@ pub(super) fn parse_entities(
|
||||
extra = more;
|
||||
kindent = Some((c, k));
|
||||
}
|
||||
"INSERT" => {
|
||||
if t.i(66) == Some(1) {
|
||||
let ins_layer = kindent.as_ref().map(|(c, _)| c.layer.clone()).unwrap_or_default();
|
||||
let attribs = insert_attribs(recs, &mut i, &ins_layer);
|
||||
if let Some((_, EntityKind::Insert(ins))) = kindent.as_mut() {
|
||||
ins.attribs = attribs;
|
||||
}
|
||||
"INSERT" if t.i(66) == Some(1) => {
|
||||
let ins_layer = kindent.as_ref().map(|(c, _)| c.layer.clone()).unwrap_or_default();
|
||||
let attribs = insert_attribs(recs, &mut i, &ins_layer);
|
||||
if let Some((_, EntityKind::Insert(ins))) = kindent.as_mut() {
|
||||
ins.attribs = attribs;
|
||||
}
|
||||
}
|
||||
// A VERTEX or ATTRIB with no POLYLINE or INSERT before it; a stray SEQEND holds nothing.
|
||||
|
||||
@@ -77,7 +77,7 @@ pub(super) fn mesh(g: &TextGlyph, xf: Mat3, pixel: f64) -> Arc<Mesh> {
|
||||
let contours = ttf::glyph_contours(&g.face, g.gid);
|
||||
let points = contours.iter().map(Vec::len).try_fold(0usize, usize::checked_add);
|
||||
// Font data is untrusted; don't hand unbounded or invalid paths to the tessellator.
|
||||
if !points.is_some_and(|n| n <= MAX_POINTS) || contours.iter().flatten().any(|p| !p.is_finite() || p.x.abs().max(p.y.abs()) > 1.0e6) {
|
||||
if points.is_none_or(|n| n > MAX_POINTS) || contours.iter().flatten().any(|p| !p.is_finite() || p.x.abs().max(p.y.abs()) > 1.0e6) {
|
||||
return Arc::new(Mesh { contours: Arc::default(), triangles: Vec::new() });
|
||||
}
|
||||
let contours = match detail {
|
||||
|
||||
@@ -379,13 +379,11 @@ pub fn keyboard(app: &mut CadApp, ctx: &egui::Context) {
|
||||
app.cmd.buffer.pop();
|
||||
}
|
||||
}
|
||||
Key::ArrowUp if !modifiers.any() => {
|
||||
if !app.cmd.history.is_empty() {
|
||||
let n = app.cmd.history.len();
|
||||
let pos = app.cmd.history_pos.map(|p| p.saturating_sub(1)).unwrap_or(n - 1);
|
||||
app.cmd.history_pos = Some(pos);
|
||||
app.cmd.buffer = app.cmd.history.get(pos).cloned().unwrap_or_default();
|
||||
}
|
||||
Key::ArrowUp if !modifiers.any() && !app.cmd.history.is_empty() => {
|
||||
let n = app.cmd.history.len();
|
||||
let pos = app.cmd.history_pos.map(|p| p.saturating_sub(1)).unwrap_or(n - 1);
|
||||
app.cmd.history_pos = Some(pos);
|
||||
app.cmd.buffer = app.cmd.history.get(pos).cloned().unwrap_or_default();
|
||||
}
|
||||
Key::ArrowDown if !modifiers.any() => {
|
||||
if !options_key(app, 1)
|
||||
|
||||
@@ -8,6 +8,15 @@
|
||||
#![deny(clippy::unwrap_used, clippy::expect_used, clippy::panic, clippy::unimplemented, clippy::todo, clippy::unreachable)]
|
||||
#![forbid(unsafe_code)]
|
||||
|
||||
/// CADCraft as craft-update knows it, with its 128 px icon and accent colour: the update
|
||||
/// prompt shows both, and an AppImage's menu entry gets the icon.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub const UPDATE_APP: craft_update::app::App = craft_update::app::App {
|
||||
icon_png: Some(include_bytes!("../../../assets/app-icon/hicolor/128x128/apps/ai.storyteller.cadcraft.png")),
|
||||
accent: Some([0x3e, 0xa6, 0xe8]),
|
||||
..craft_update::suite::CADCRAFT
|
||||
};
|
||||
|
||||
pub mod aliasdlg;
|
||||
pub mod animation;
|
||||
pub mod autosave;
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
//! Updates… (desktop only; the web build is always the latest). The flow itself is
|
||||
//! `craft_update::updater::Updater`.
|
||||
|
||||
use craft_update::suite::CADCRAFT;
|
||||
use craft_update::updater::{Action, Status, Updater};
|
||||
|
||||
use crate::CadApp;
|
||||
@@ -21,7 +20,7 @@ pub struct Runtime {
|
||||
|
||||
impl Default for Runtime {
|
||||
fn default() -> Self {
|
||||
Self { updater: Updater::new(&CADCRAFT, VERSION), enabled: false, check_requested: false }
|
||||
Self { updater: Updater::new(&crate::UPDATE_APP, VERSION), enabled: false, check_requested: false }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-4
@@ -167,10 +167,8 @@ pub fn check(crates: &[Crate]) -> Vec<Violation> {
|
||||
match classify(&d.name) {
|
||||
// Unregistered deps are reported on their own entry.
|
||||
None => {}
|
||||
Some(Class::Testkit) => {
|
||||
if d.kind != DepKind::Dev {
|
||||
out.push(Violation::TestkitAsNormalDep { krate: c.name.clone() });
|
||||
}
|
||||
Some(Class::Testkit) if d.kind != DepKind::Dev => {
|
||||
out.push(Violation::TestkitAsNormalDep { krate: c.name.clone() });
|
||||
}
|
||||
Some(dc) => {
|
||||
let to = dc.layer().unwrap_or(u8::MAX);
|
||||
|
||||
Reference in New Issue
Block a user