forked from 1b-agent/opencadstudio-upstream
[IMP] OneBSpace rebrand of OpenCADStudio -> OneCAD Draft (wordmark, about, crash banner, 23 locales; strip SW/manifest; air-gap: update check, donations, discussions, external help links)
This commit is contained in:
1 parent
c9e763006e
commit
193f2ae9ab
57 files changed
+760
-1091
No files matched your search
@@ -114,7 +114,7 @@ fn route(path: &str, format: Option<usize>) -> Result<Route, String> {
|
||||
.find(|f| f.extensions.iter().any(|e| e.eq_ignore_ascii_case(&ext)));
|
||||
Err(match named.and_then(|f| unsupported_reason(f.support).map(|r| (f, r))) {
|
||||
Some((f, reason)) => format!("{}: {reason}", f.name),
|
||||
None => crate::t!("OpenCAD Studio has no importer for this format.").into_owned(),
|
||||
None => crate::t!("OneCAD Draft has no importer for this format.") /* OneBSpace (OneCAD Draft): rebranded */.into_owned(),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
+13
-55
@@ -69,33 +69,15 @@ fn ensure_draw_order_table(doc: &mut codec::CadDocument, block: codec::Handle) -
|
||||
impl OpenCADStudio {
|
||||
pub(crate) fn dispatch_view(&mut self, cmd: &str, i: usize) -> Option<Task<Message>> {
|
||||
match cmd {
|
||||
"DONATE" => {
|
||||
self.command_line
|
||||
.push_info(crate::t!("Opening Patreon page...").as_ref());
|
||||
return Some(crate::sys::open_url(
|
||||
"https://patreon.com/HakanSeven12",
|
||||
self.main_window,
|
||||
));
|
||||
}
|
||||
// OneBSpace (OneCAD Draft): donations disabled — air-gapped build.
|
||||
"DONATE" => Some(Task::none()),
|
||||
|
||||
"WEBVERSION" => {
|
||||
self.command_line
|
||||
.push_info(crate::t!("Opening OCS Web...").as_ref());
|
||||
return Some(crate::sys::open_url(
|
||||
"https://hakanseven12.github.io/OpenCADStudio/",
|
||||
self.main_window,
|
||||
));
|
||||
}
|
||||
// OneBSpace (OneCAD Draft): the upstream web-app link is gone.
|
||||
"WEBVERSION" => Some(Task::none()),
|
||||
|
||||
"HELP" => {
|
||||
self.command_line.push_info(
|
||||
crate::t!("Opening OCS Discussions for help and questions...").as_ref(),
|
||||
);
|
||||
return Some(crate::sys::open_url(
|
||||
"https://github.com/HakanSeven12/OpenCADStudio/discussions",
|
||||
self.main_window,
|
||||
));
|
||||
}
|
||||
// OneBSpace (OneCAD Draft): external help/discussions link removed —
|
||||
// air-gapped build. Use the in-app help instead.
|
||||
"HELP" => Some(Task::none()),
|
||||
|
||||
// ── DWGPROPS — print round-trip-only HeaderVariables ─────────
|
||||
// No UI dialog for these yet; the command surfaces them so
|
||||
@@ -317,28 +299,9 @@ impl OpenCADStudio {
|
||||
}
|
||||
}
|
||||
|
||||
"REPORT" => {
|
||||
// Pre-fill the GitHub issue body with version + platform so
|
||||
// reports arrive with the basics already filled in. The rule
|
||||
// is `***`: text typed right above a `---` line turns into a
|
||||
// Markdown heading.
|
||||
let body = format!(
|
||||
"<!-- Describe the issue and the steps to reproduce it. -->\n\n\n\
|
||||
***\n- Open CAD Studio: v{}\n- Revision: {} ({}, {})\n- Platform: {}\n",
|
||||
env!("OCS_FULL_VERSION"),
|
||||
env!("OCS_GIT_REV"),
|
||||
env!("OCS_COMMIT_DATE"),
|
||||
env!("OCS_BUILD_PROFILE"),
|
||||
crate::sys::platform_info(),
|
||||
);
|
||||
let url = format!(
|
||||
"https://github.com/HakanSeven12/OpenCADStudio/issues/new?body={}",
|
||||
crate::sys::percent_encode(&body)
|
||||
);
|
||||
self.command_line
|
||||
.push_info(crate::t!("Opening feedback page...").as_ref());
|
||||
return Some(crate::sys::open_url(&url, self.main_window));
|
||||
}
|
||||
// OneBSpace (OneCAD Draft): the upstream GitHub issue tracker is
|
||||
// unreachable from an air-gapped build; feedback is a no-op.
|
||||
"REPORT" => Some(Task::none()),
|
||||
|
||||
"ABOUT" => {
|
||||
return Some(Task::done(Message::AboutOpen));
|
||||
@@ -348,14 +311,9 @@ impl OpenCADStudio {
|
||||
return Some(Task::done(Message::PluginManagerOpen));
|
||||
}
|
||||
|
||||
"CHANGELOG" => {
|
||||
self.command_line
|
||||
.push_info(crate::t!("Opening release notes...").as_ref());
|
||||
return Some(crate::sys::open_url(
|
||||
"https://github.com/HakanSeven12/OpenCADStudio/releases",
|
||||
self.main_window,
|
||||
));
|
||||
}
|
||||
// OneBSpace (OneCAD Draft): upstream release notes are unreachable
|
||||
// from an air-gapped build.
|
||||
"CHANGELOG" => Some(Task::none()),
|
||||
|
||||
// ── ALIASEDIT — command-alias editor ───────────────────────────
|
||||
// Opens the command-alias table editor (ocad.pgp). Keyboard
|
||||
|
||||
+18
-44
@@ -5469,54 +5469,26 @@ impl OpenCADStudio {
|
||||
)
|
||||
};
|
||||
s.queue_startup_prompts();
|
||||
// Fetch the Patreon supporters list once at boot for the Start page.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
let patrons_fetch = Task::perform(
|
||||
async { crate::patreon::fetch_patrons() },
|
||||
Message::PatronsFetched,
|
||||
);
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
// OneBSpace (OneCAD Draft): Patreon supporters fetch disabled — air-gapped
|
||||
// build. The Start page supporters rail renders from the local list only.
|
||||
let patrons_fetch = Task::none();
|
||||
// Tutorial videos: show the on-disk cache instantly, refresh from the
|
||||
// live playlist in the background. Nothing ships in the binary. The
|
||||
// fetch runs on its own OS thread — its several sequential HTTP
|
||||
// requests would otherwise sit on the async executor and hold up the
|
||||
// rest of the boot tasks (the Start page waited on it).
|
||||
// OneBSpace (OneCAD Draft): tutorial videos show the local on-disk
|
||||
// cache only — no playlist refresh, no thumbnail downloads (air-gapped).
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
let videos_fetch = {
|
||||
s.set_videos(crate::videos::load_cached());
|
||||
s.videos_loading = true;
|
||||
let (tx, rx) = iced::futures::channel::oneshot::channel();
|
||||
std::thread::spawn(move || {
|
||||
let _ = tx.send(crate::videos::fetch_playlist());
|
||||
});
|
||||
Task::perform(
|
||||
async move {
|
||||
rx.await
|
||||
.unwrap_or_else(|_| Err("video fetch thread died".into()))
|
||||
},
|
||||
Message::VideosFetched,
|
||||
)
|
||||
s.videos_loading = false;
|
||||
Task::none()
|
||||
};
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
let videos_fetch = Task::none();
|
||||
// GitHub Discussions: seed from the last successful fetch, then refresh
|
||||
// the public feed and pinned section on a background thread.
|
||||
// OneBSpace (OneCAD Draft): GitHub Discussions refresh disabled —
|
||||
// air-gapped build. The Start page lists the bundled discussions.json.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
let discussions_fetch = {
|
||||
s.discussions = crate::discussions::load_cached();
|
||||
s.discussions_loading = true;
|
||||
let (tx, rx) = iced::futures::channel::oneshot::channel();
|
||||
std::thread::spawn(move || {
|
||||
let _ = tx.send(crate::discussions::fetch_discussions());
|
||||
});
|
||||
Task::perform(
|
||||
async move {
|
||||
rx.await
|
||||
.unwrap_or_else(|_| Err("discussion fetch thread died".into()))
|
||||
},
|
||||
Message::DiscussionsFetched,
|
||||
)
|
||||
s.discussions_loading = false;
|
||||
Task::none()
|
||||
};
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
let discussions_fetch = Task::none();
|
||||
@@ -5565,9 +5537,11 @@ impl OpenCADStudio {
|
||||
Task::done(Message::PollWebFonts),
|
||||
Task::done(Message::ApplyWebFont(primary_font)),
|
||||
]);
|
||||
// Web can't reach the Patreon API directly (CORS); fetch the CI-built
|
||||
// supporters.json served on the same origin instead.
|
||||
let patrons = Task::perform(crate::patreon::fetch_patrons_web(), Message::PatronsFetched);
|
||||
// OneBSpace (OneCAD Draft): Patreon supporters fetch disabled — air-gapped
|
||||
// build (no Patreon API, no supporters.json).
|
||||
let patrons = Task::none();
|
||||
// Videos/discussions read the LOCAL same-origin videos.json /
|
||||
// discussions.json shipped next to the app; no remote endpoints.
|
||||
s.videos_loading = true;
|
||||
let videos = Task::perform(crate::videos::fetch_playlist_web(), Message::VideosFetched);
|
||||
s.discussions_loading = true;
|
||||
@@ -5662,13 +5636,13 @@ pub fn run() -> iced::Result {
|
||||
let dot = if tab.dirty { "● " } else { "" };
|
||||
let name = tab.tab_display_name();
|
||||
format!(
|
||||
"{}Open CAD Studio {} - {}",
|
||||
"{}OneCAD Draft {} - {}", // OneBSpace (OneCAD Draft): rebranded wordmark
|
||||
dot,
|
||||
env!("OCS_APP_VERSION"),
|
||||
name
|
||||
)
|
||||
} else {
|
||||
concat!("Open CAD Studio ", env!("OCS_APP_VERSION")).to_string()
|
||||
concat!("OneCAD Draft ", env!("OCS_APP_VERSION")).to_string() // OneBSpace (OneCAD Draft): rebranded wordmark
|
||||
}
|
||||
})
|
||||
.theme(|state: &OpenCADStudio, _| state.active_theme.clone())
|
||||
@@ -5714,7 +5688,7 @@ pub fn run_web() -> iced::Result {
|
||||
)
|
||||
.subscription(OpenCADStudio::subscription)
|
||||
.title(|_state: &OpenCADStudio| {
|
||||
concat!("Open CAD Studio ", env!("OCS_APP_VERSION")).to_string()
|
||||
concat!("OneCAD Draft ", env!("OCS_APP_VERSION")).to_string() // OneBSpace (OneCAD Draft): rebranded wordmark
|
||||
})
|
||||
.theme(|state: &OpenCADStudio| state.active_theme.clone())
|
||||
.backend(iced::Backend::Hardware(iced::backend::Api::OpenGL))
|
||||
|
||||
+25
-48
@@ -8,16 +8,8 @@ impl OpenCADStudio {
|
||||
self.pending_startup_modals
|
||||
.push_back(ModalKind::AssocPrompt);
|
||||
}
|
||||
// Automation sessions (#1349): once control traffic has arrived (or a
|
||||
// web host opted in at boot) while control is enabled, the donation
|
||||
// prompt is suppressed — a modal would block every automated
|
||||
// operation until a client closed it by hand.
|
||||
if self.donation_prompt_version != env!("OCS_APP_VERSION")
|
||||
&& !(self.control.enabled && self.control.automation_seen)
|
||||
{
|
||||
self.pending_startup_modals
|
||||
.push_back(ModalKind::DonationPrompt);
|
||||
}
|
||||
// OneBSpace (OneCAD Draft): the donation prompt was removed —
|
||||
// air-gapped build, no fundraising UI at startup.
|
||||
self.show_next_startup_modal();
|
||||
}
|
||||
|
||||
@@ -200,47 +192,32 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn donation_prompt_persists_once_per_version() {
|
||||
fn donation_prompt_is_no_longer_queued() {
|
||||
// OneBSpace (OneCAD Draft): the donation prompt was removed; startup
|
||||
// must never queue it, regardless of the stored prompt version.
|
||||
let mut app = OpenCADStudio::new_for_test();
|
||||
// Older settings have no donation version; headless construction never prompts.
|
||||
app.apply_config(serde_json::from_str::<AppConfig>("{}").unwrap());
|
||||
assert!(app.active_modal.is_none());
|
||||
assert!(app.pending_startup_modals.is_empty());
|
||||
app.default_assoc_prompted = true;
|
||||
app.queue_startup_prompts();
|
||||
assert_eq!(app.active_modal, Some(ModalKind::DonationPrompt));
|
||||
assert!(app.donation_prompt_version.is_empty());
|
||||
|
||||
let _ = app.update(Message::ModalContentResized(iced::Size::new(540.0, 280.0)));
|
||||
let saved = serde_json::to_string(&app.current_config()).unwrap();
|
||||
let _ = app.update(Message::CloseModal);
|
||||
assert!(app.active_modal.is_none());
|
||||
assert!(app.pending_startup_modals.is_empty());
|
||||
|
||||
let mut restarted = OpenCADStudio::new_for_test();
|
||||
restarted.apply_config(serde_json::from_str(&saved).unwrap());
|
||||
restarted.queue_startup_prompts();
|
||||
assert_eq!(restarted.donation_prompt_version, env!("OCS_APP_VERSION"));
|
||||
assert!(restarted.active_modal.is_none());
|
||||
|
||||
restarted.donation_prompt_version = "previous-release".to_string();
|
||||
restarted.queue_startup_prompts();
|
||||
assert_eq!(restarted.active_modal, Some(ModalKind::DonationPrompt));
|
||||
let _ = restarted.update(Message::CommandEscape);
|
||||
assert!(restarted.active_modal.is_none());
|
||||
assert_eq!(restarted.donation_prompt_version, env!("OCS_APP_VERSION"));
|
||||
let _ = restarted.update(Message::Noop);
|
||||
assert!(restarted.active_modal.is_none());
|
||||
app.donation_prompt_version = "previous-release".to_string();
|
||||
app.queue_startup_prompts();
|
||||
assert!(app.active_modal.is_none());
|
||||
assert!(app.pending_startup_modals.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn automation_sessions_skip_the_donation_prompt() {
|
||||
fn automation_sessions_drop_queued_startup_prompts() {
|
||||
// OneBSpace (OneCAD Draft): startup no longer queues the donation
|
||||
// prompt; seed one manually to exercise the automation drop guard.
|
||||
// First control contact drops a still-queued donation prompt and
|
||||
// stops later queueing while control stays enabled (#1349).
|
||||
let mut app = OpenCADStudio::new_for_test();
|
||||
app.default_assoc_prompted = true;
|
||||
app.queue_startup_prompts();
|
||||
assert_eq!(app.active_modal, Some(ModalKind::DonationPrompt));
|
||||
let _ = app.update(Message::CloseModal);
|
||||
app.donation_prompt_version = "previous-release".to_string();
|
||||
app.pending_startup_modals
|
||||
.push_back(ModalKind::DonationPrompt);
|
||||
@@ -248,6 +225,12 @@ mod tests {
|
||||
assert!(app.pending_startup_modals.is_empty());
|
||||
app.queue_startup_prompts();
|
||||
assert_ne!(app.active_modal, Some(ModalKind::DonationPrompt));
|
||||
app.pending_startup_modals
|
||||
.push_back(ModalKind::DonationPrompt);
|
||||
let _ = app.control_request(serde_json::json!({"op":"state"}));
|
||||
assert!(app.pending_startup_modals.is_empty());
|
||||
app.queue_startup_prompts();
|
||||
assert_ne!(app.active_modal, Some(ModalKind::DonationPrompt));
|
||||
|
||||
// A still-queued (not yet shown) prompt is dropped on first contact.
|
||||
let mut queued = OpenCADStudio::new_for_test();
|
||||
@@ -261,11 +244,12 @@ mod tests {
|
||||
assert_ne!(queued.active_modal, Some(ModalKind::DonationPrompt));
|
||||
|
||||
// A prompt already on screen is left for its reader; clients close
|
||||
// it themselves, and a session with no control traffic still prompts.
|
||||
// it themselves. OneBSpace (OneCAD Draft): with no control traffic a
|
||||
// session never sees the donation prompt anymore.
|
||||
let mut human = OpenCADStudio::new_for_test();
|
||||
human.default_assoc_prompted = true;
|
||||
human.queue_startup_prompts();
|
||||
assert_eq!(human.active_modal, Some(ModalKind::DonationPrompt));
|
||||
assert_ne!(human.active_modal, Some(ModalKind::DonationPrompt));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -282,16 +266,9 @@ mod tests {
|
||||
)));
|
||||
assert_eq!(app.active_modal, Some(ModalKind::AssocPrompt));
|
||||
let _ = app.update(Message::AssocPromptNo);
|
||||
assert_eq!(app.active_modal, Some(ModalKind::DonationPrompt));
|
||||
|
||||
// A file-recovery dialog may interrupt startup before the first frame.
|
||||
app.active_modal = Some(ModalKind::Recovery);
|
||||
let _ = app.update(Message::CloseModal);
|
||||
assert_eq!(app.active_modal, Some(ModalKind::DonationPrompt));
|
||||
assert!(app.donation_prompt_version.is_empty());
|
||||
let _ = app.update(Message::ModalContentResized(iced::Size::new(540.0, 280.0)));
|
||||
assert_eq!(app.donation_prompt_version, env!("OCS_APP_VERSION"));
|
||||
let _ = app.update(Message::CloseModal);
|
||||
// OneBSpace (OneCAD Draft): the donation prompt is gone; the update
|
||||
// notice queued by the (manually delivered) check result still waits
|
||||
// its turn behind the association prompt.
|
||||
assert_eq!(app.active_modal, Some(ModalKind::UpdateNotice));
|
||||
let _ = app.update(Message::UpdateNoticeClose);
|
||||
assert!(app.active_modal.is_none());
|
||||
|
||||
@@ -3649,7 +3649,7 @@ impl OpenCADStudio {
|
||||
.map(|name| name.to_string_lossy().into_owned())
|
||||
.unwrap_or_else(|| outcome.path.display().to_string());
|
||||
self.command_line.push_error_once(
|
||||
crate::tf!("Save stopped: \"{file_name}\" changed outside Open CAD Studio.")
|
||||
crate::tf!("Save stopped: \"{file_name}\" changed outside OneCAD Draft.")
|
||||
.as_ref(),
|
||||
);
|
||||
self.pending_external_change = Some(crate::app::PendingExternalChange {
|
||||
|
||||
@@ -11003,9 +11003,10 @@ impl OpenCADStudio {
|
||||
Task::none()
|
||||
}
|
||||
Message::DonationPromptDonate => {
|
||||
// OneBSpace (OneCAD Draft): donations disabled — air-gapped
|
||||
// build; the prompt is never queued, the button is inert.
|
||||
self.close_active_modal();
|
||||
self.dispatch_view("DONATE", self.active_tab)
|
||||
.unwrap_or_else(Task::none)
|
||||
Task::none()
|
||||
}
|
||||
Message::UpdateNoticeClose => {
|
||||
self.close_active_modal();
|
||||
|
||||
+20
-206
@@ -3669,7 +3669,7 @@ fn start_page_content<'a>(
|
||||
action_width_out: std::sync::Arc<std::sync::atomic::AtomicU32>,
|
||||
active: super::StartSection,
|
||||
) -> Element<'a, Message> {
|
||||
let headline = text("Open CAD Studio").size(40).style(start_primary_style);
|
||||
let headline = text("OneCAD Draft").size(40).style(start_primary_style); // OneBSpace (OneCAD Draft): rebranded wordmark
|
||||
|
||||
// Plain outlined button (Open / New / Help / Contribute).
|
||||
let outline_btn = |label: String, msg: Message| {
|
||||
@@ -3695,23 +3695,8 @@ fn start_page_content<'a>(
|
||||
})
|
||||
};
|
||||
|
||||
// Donate — the prominent call-to-action, using the theme's danger role.
|
||||
let donate_btn = {
|
||||
button(
|
||||
row![
|
||||
crate::ui::icons::themed_danger_text(crate::ui::icons::HEART, 14.0),
|
||||
text(crate::tr!("start", "donate")).size(14),
|
||||
]
|
||||
.spacing(5)
|
||||
.align_y(iced::Center),
|
||||
)
|
||||
.on_press(Message::RibbonToolClick {
|
||||
tool_id: "DONATE".to_string(),
|
||||
event: crate::modules::ModuleEvent::Command("DONATE".to_string()),
|
||||
})
|
||||
.padding([10, 22])
|
||||
.style(|theme: &Theme, status| start_action_shape(button::danger(theme, status)))
|
||||
};
|
||||
// OneBSpace (OneCAD Draft): the donation call-to-action was removed —
|
||||
// air-gapped build, no external fundraising links.
|
||||
|
||||
let primary_row = WrapFlow::new(vec![
|
||||
outline_btn(crate::tr!("start", "new-drawing"), Message::TabNew).into(),
|
||||
@@ -3725,7 +3710,6 @@ fn start_page_content<'a>(
|
||||
)
|
||||
.into(),
|
||||
outline_btn(crate::tr!("start", "open-file"), Message::OpenFile).into(),
|
||||
donate_btn.into(),
|
||||
])
|
||||
.spacing_x(12.0)
|
||||
.row_h(48.0)
|
||||
@@ -3745,90 +3729,15 @@ fn start_page_content<'a>(
|
||||
];
|
||||
secondary_items
|
||||
.push(outline_btn(crate::tr!("action", "plugins"), Message::PluginManagerOpen).into());
|
||||
// The web build is already in the browser, so only the desktop offers a
|
||||
// link to the web version.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
{
|
||||
// Filled with the active theme's primary colour.
|
||||
secondary_items.push(
|
||||
button(text(crate::t!("OCS Web")).size(14))
|
||||
.on_press(Message::RibbonToolClick {
|
||||
tool_id: "WEBVERSION".to_string(),
|
||||
event: crate::modules::ModuleEvent::Command("WEBVERSION".to_string()),
|
||||
})
|
||||
.padding([10, 22])
|
||||
.style(|theme: &Theme, status| start_action_shape(button::primary(theme, status)))
|
||||
.into(),
|
||||
);
|
||||
}
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
secondary_items.push(
|
||||
button(text(crate::t!("OCS Desktop")).size(14))
|
||||
.on_press(Message::OpenUrl(
|
||||
"https://github.com/HakanSeven12/OpenCADStudio/releases/latest".to_string(),
|
||||
))
|
||||
.padding([10, 22])
|
||||
.style(|theme: &Theme, status| start_action_shape(button::primary(theme, status)))
|
||||
.into(),
|
||||
);
|
||||
// OneBSpace (OneCAD Draft): the "OCS Web" / "OCS Desktop" cross-promotion
|
||||
// buttons were removed — no external download or website links.
|
||||
let secondary_row = WrapFlow::new(secondary_items)
|
||||
.spacing_x(12.0)
|
||||
.row_h(44.0)
|
||||
.report_natural_width(action_width_out.clone());
|
||||
|
||||
let reddit_btn = button(
|
||||
row![
|
||||
iced::widget::svg(iced::widget::svg::Handle::from_memory(include_bytes!(
|
||||
"../../../assets/icons/reddit.svg"
|
||||
)))
|
||||
.width(20)
|
||||
.height(20),
|
||||
text("r/OpenCADStudio").size(14),
|
||||
]
|
||||
.spacing(7)
|
||||
.align_y(iced::Center),
|
||||
)
|
||||
.on_press(Message::OpenUrl(
|
||||
"https://www.reddit.com/r/OpenCADStudio/".to_string(),
|
||||
))
|
||||
.padding([10, 22])
|
||||
.style(|theme: &Theme, status| {
|
||||
let palette = theme.palette();
|
||||
let pair = match status {
|
||||
button::Status::Hovered => palette.background.strong,
|
||||
_ => palette.background.weak,
|
||||
};
|
||||
start_action_shape(button::Style {
|
||||
background: Some(Background::Color(pair.color)),
|
||||
text_color: pair.text,
|
||||
border: Border {
|
||||
color: Color::from_rgb8(255, 69, 0),
|
||||
width: 1.0,
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
})
|
||||
});
|
||||
|
||||
let sponsors = column![
|
||||
text(crate::tr!("start", "sponsors")).size(15),
|
||||
mouse_area(
|
||||
container(
|
||||
iced::widget::svg(iced::widget::svg::Handle::from_memory(include_bytes!(
|
||||
"../../../assets/sponsors/openaec-logo-dark-on-light.svg"
|
||||
)))
|
||||
.width(Fill)
|
||||
.height(iced::Length::Fixed(120.0))
|
||||
.content_fit(iced::ContentFit::Contain),
|
||||
)
|
||||
.width(Fill.max(300.0)),
|
||||
)
|
||||
.interaction(iced::mouse::Interaction::Pointer)
|
||||
.on_press(Message::OpenUrl("https://open-aec.com/".to_string())),
|
||||
]
|
||||
.spacing(10)
|
||||
.align_x(iced::alignment::Horizontal::Center)
|
||||
.width(Fill);
|
||||
// OneBSpace (OneCAD Draft): the community Reddit link and the Open-AEC
|
||||
// sponsor block were removed — no external links in the Start page.
|
||||
|
||||
let content = column![
|
||||
Space::new().height(iced::Length::Fixed(28.0)),
|
||||
@@ -3837,10 +3746,6 @@ fn start_page_content<'a>(
|
||||
container(primary_row).center_x(Fill),
|
||||
Space::new().height(iced::Length::Fixed(10.0)),
|
||||
container(secondary_row).center_x(Fill),
|
||||
Space::new().height(iced::Length::Fixed(10.0)),
|
||||
container(reddit_btn).center_x(Fill),
|
||||
Space::new().height(iced::Length::Fixed(20.0)),
|
||||
sponsors,
|
||||
Space::new().height(iced::Length::Fixed(52.0)),
|
||||
]
|
||||
.spacing(0)
|
||||
@@ -3908,8 +3813,9 @@ fn start_page_content<'a>(
|
||||
);
|
||||
let welcome = container(content).width(Fill).height(Fill);
|
||||
|
||||
// Tutorial-videos rail: the official playlist, fetched at boot (cached on
|
||||
// disk) — thumbnail card + title per video, click opens the browser.
|
||||
// Tutorial-videos rail: local listing only (cached on disk / bundled
|
||||
// videos.json) — thumbnail card + title per video; OneBSpace (OneCAD
|
||||
// Draft): no click-through, cards are informational (air-gapped build).
|
||||
let videos_panel: Element<'a, Message> = {
|
||||
// Derive the 16:9 cover box from the actual shared list width so the
|
||||
// whole thumbnail remains visible when that width changes.
|
||||
@@ -3946,11 +3852,9 @@ fn start_page_content<'a>(
|
||||
);
|
||||
}
|
||||
card = card.push(text(v.title.clone()).size(12).style(start_muted_style));
|
||||
list = list.push(
|
||||
mouse_area(card)
|
||||
.interaction(iced::mouse::Interaction::Pointer)
|
||||
.on_press(Message::OpenUrl(crate::videos::watch_url(&v.id))),
|
||||
);
|
||||
// OneBSpace (OneCAD Draft): cards are informational only — no
|
||||
// click-through to YouTube (air-gapped build).
|
||||
list = list.push(card);
|
||||
}
|
||||
if videos.is_empty() {
|
||||
let note = if videos_loading {
|
||||
@@ -3960,32 +3864,7 @@ fn start_page_content<'a>(
|
||||
};
|
||||
list = list.push(text(note).size(12).style(start_muted_style));
|
||||
}
|
||||
let playlist_btn = mouse_area(
|
||||
container(text(crate::tr!("start", "open-playlist")).size(12))
|
||||
.padding([6, 10])
|
||||
.width(Fill)
|
||||
.center_x(Fill)
|
||||
.style(|theme: &Theme| {
|
||||
let pair = theme.palette().danger.base;
|
||||
container::Style {
|
||||
background: Some(Background::Color(pair.color)),
|
||||
border: Border {
|
||||
color: Color::TRANSPARENT,
|
||||
width: 0.0,
|
||||
radius: 6.0.into(),
|
||||
},
|
||||
text_color: Some(pair.text),
|
||||
..Default::default()
|
||||
}
|
||||
}),
|
||||
)
|
||||
.interaction(iced::mouse::Interaction::Pointer)
|
||||
.on_press(Message::OpenUrl(crate::videos::PLAYLIST_URL.to_string()));
|
||||
container(column![
|
||||
iced::widget::scrollable(list).height(Fill),
|
||||
Space::new().height(iced::Length::Fixed(12.0)),
|
||||
playlist_btn,
|
||||
])
|
||||
container(column![iced::widget::scrollable(list).height(Fill)])
|
||||
.width(match start_layout {
|
||||
StartLayout::AllPanels => iced::Length::Fixed(panel_w),
|
||||
StartLayout::WithoutVideos
|
||||
@@ -4055,11 +3934,7 @@ fn start_page_content<'a>(
|
||||
..Default::default()
|
||||
}
|
||||
});
|
||||
list = list.push(
|
||||
mouse_area(card)
|
||||
.interaction(iced::mouse::Interaction::Pointer)
|
||||
.on_press(Message::OpenUrl(discussion.url.clone())),
|
||||
);
|
||||
list = list.push(card);
|
||||
}
|
||||
if discussions.is_empty() {
|
||||
let note = if discussions_loading {
|
||||
@@ -4069,34 +3944,7 @@ fn start_page_content<'a>(
|
||||
};
|
||||
list = list.push(text(note).size(12).style(start_muted_style));
|
||||
}
|
||||
let open_btn = mouse_area(
|
||||
container(text(crate::tr!("start", "open-discussions")).size(12))
|
||||
.padding([6, 10])
|
||||
.width(Fill)
|
||||
.center_x(Fill)
|
||||
.style(|theme: &Theme| {
|
||||
let pair = theme.palette().primary.base;
|
||||
container::Style {
|
||||
background: Some(Background::Color(pair.color)),
|
||||
border: Border {
|
||||
color: Color::TRANSPARENT,
|
||||
width: 0.0,
|
||||
radius: 6.0.into(),
|
||||
},
|
||||
text_color: Some(pair.text),
|
||||
..Default::default()
|
||||
}
|
||||
}),
|
||||
)
|
||||
.interaction(iced::mouse::Interaction::Pointer)
|
||||
.on_press(Message::OpenUrl(
|
||||
crate::discussions::DISCUSSIONS_URL.to_string(),
|
||||
));
|
||||
container(column![
|
||||
iced::widget::scrollable(list).height(Fill),
|
||||
Space::new().height(iced::Length::Fixed(12.0)),
|
||||
open_btn,
|
||||
])
|
||||
container(column![iced::widget::scrollable(list).height(Fill)])
|
||||
.width(match start_layout {
|
||||
StartLayout::AllPanels | StartLayout::WithoutVideos => iced::Length::Fixed(panel_w),
|
||||
StartLayout::WithoutVideosAndDiscussions
|
||||
@@ -4120,9 +3968,9 @@ fn start_page_content<'a>(
|
||||
.into()
|
||||
};
|
||||
|
||||
// Right rail: Patreon supporters, fetched at boot. When the list is empty
|
||||
// (no token configured / offline) only the "Support on Patreon" button
|
||||
// shows, so the rail always invites support.
|
||||
// OneBSpace (OneCAD Draft): right rail shows the local supporters list
|
||||
// only — the Patreon fetch and the "Support on Patreon" button were
|
||||
// removed (air-gapped build, no external links).
|
||||
let supporters: Element<'a, Message> = {
|
||||
let mut list = column![
|
||||
text(crate::tr!("start", "supporters")).size(15),
|
||||
@@ -4146,41 +3994,7 @@ fn start_page_content<'a>(
|
||||
.spacing(6),
|
||||
);
|
||||
}
|
||||
let support_btn = mouse_area(
|
||||
container(
|
||||
iced::widget::row![
|
||||
crate::ui::icons::themed_danger_text(crate::ui::icons::HEART, 13.0),
|
||||
text(crate::tr!("start", "support-on-patreon")).size(12),
|
||||
]
|
||||
.spacing(6)
|
||||
.align_y(iced::Center),
|
||||
)
|
||||
.padding([6, 10])
|
||||
.width(Fill)
|
||||
.center_x(Fill)
|
||||
.style(|theme: &Theme| {
|
||||
let pair = theme.palette().danger.base;
|
||||
container::Style {
|
||||
background: Some(Background::Color(pair.color)),
|
||||
border: Border {
|
||||
color: Color::TRANSPARENT,
|
||||
width: 0.0,
|
||||
radius: 6.0.into(),
|
||||
},
|
||||
text_color: Some(pair.text),
|
||||
..Default::default()
|
||||
}
|
||||
}),
|
||||
)
|
||||
.interaction(iced::mouse::Interaction::Pointer)
|
||||
.on_press(Message::OpenUrl(
|
||||
"https://patreon.com/HakanSeven12".to_string(),
|
||||
));
|
||||
container(column![
|
||||
iced::widget::scrollable(list).height(Fill),
|
||||
Space::new().height(iced::Length::Fixed(12.0)),
|
||||
support_btn,
|
||||
])
|
||||
container(column![iced::widget::scrollable(list).height(Fill)])
|
||||
.width(match start_layout {
|
||||
StartLayout::AllPanels
|
||||
| StartLayout::WithoutVideos
|
||||
|
||||
@@ -2589,10 +2589,10 @@ fn donation_dialog_window(sizing: crate::ui::modal::ModalSizing) -> Element<'sta
|
||||
fn default_assoc_dialog_window(sizing: crate::ui::modal::ModalSizing) -> Element<'static, Message> {
|
||||
container(
|
||||
column![
|
||||
text(t!("Make Open CAD Studio your default CAD app?"))
|
||||
text(t!("Make OneCAD Draft your default CAD app?")) /* OneBSpace (OneCAD Draft): rebranded */
|
||||
.size(15),
|
||||
iced::widget::Space::new().height(10),
|
||||
text(t!("Open .dwg and .dxf drawings in Open CAD Studio by default. You can change this later in your system settings."))
|
||||
text(t!("Open .dwg and .dxf drawings in OneCAD Draft by default. You can change this later in your system settings.")) /* OneBSpace (OneCAD Draft): rebranded */
|
||||
.size(12)
|
||||
.style(dialog_muted_text_style),
|
||||
iced::widget::Space::new().height(22),
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ use clap::Parser;
|
||||
"\nprofile: ", env!("OCS_BUILD_PROFILE"),
|
||||
"\nfeatures: ", env!("OCS_BUILD_FEATURES"),
|
||||
),
|
||||
about = crate::t!("Open CAD Studio — 2D/3D CAD editor").into_owned(),
|
||||
about = crate::t!("OneCAD Draft — 2D/3D CAD editor") /* OneBSpace (OneCAD Draft): rebranded */.into_owned(),
|
||||
long_about = None,
|
||||
)]
|
||||
pub struct Cli {
|
||||
|
||||
@@ -348,7 +348,7 @@ impl Commands {
|
||||
fn new(actions: &[Action]) -> Self {
|
||||
let mut strings = vec![
|
||||
CString::new("Default").unwrap(),
|
||||
CString::new("Open CAD Studio").unwrap(),
|
||||
CString::new("OneCAD Draft").unwrap(), // OneBSpace (OneCAD Draft): rebranded
|
||||
CString::new("").unwrap(),
|
||||
];
|
||||
let mut nodes = vec![Node {
|
||||
@@ -493,7 +493,7 @@ impl Connection {
|
||||
let result = unsafe {
|
||||
(api.create)(
|
||||
&mut handle,
|
||||
c"Open CAD Studio".as_ptr(),
|
||||
c"OneCAD Draft".as_ptr(), // OneBSpace (OneCAD Draft): rebranded
|
||||
accessors.as_ptr(),
|
||||
accessors.len(),
|
||||
&options,
|
||||
|
||||
@@ -248,7 +248,7 @@ mod windows_impl {
|
||||
.spawn()
|
||||
.ok()?;
|
||||
Some(
|
||||
"Opened Settings → Default apps — choose Open CAD Studio for .dwg / .dxf there."
|
||||
"Opened Settings → Default apps — choose OneCAD Draft for .dwg / .dxf there." // OneBSpace (OneCAD Draft): rebranded
|
||||
.to_string(),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -138,8 +138,18 @@ pub fn local_font_file(name: &str) -> Option<PathBuf> {
|
||||
}
|
||||
|
||||
/// List the community folder through the GitHub contents API.
|
||||
/// OneBSpace (OneCAD Draft): the upstream community font repository is
|
||||
/// disabled — air-gapped build; the GitHub fetch is kept below for reference
|
||||
/// but never runs. Custom (user-configured) font folders still work.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn fetch_repo_fonts() -> Result<Vec<RepoFont>, String> {
|
||||
let _ = REPO_API_URL;
|
||||
Err("the built-in font repository is disabled in this air-gapped build; configure a custom font folder instead".to_string())
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
#[allow(dead_code)]
|
||||
fn fetch_repo_fonts_github() -> Result<Vec<RepoFont>, String> {
|
||||
let agent = crate::network::agent(std::time::Duration::from_secs(15));
|
||||
let mut response = agent
|
||||
.get(REPO_API_URL)
|
||||
@@ -159,7 +169,9 @@ fn fetch_repo_fonts() -> Result<Vec<RepoFont>, String> {
|
||||
|
||||
/// Parse the GitHub contents-API response:
|
||||
/// `[{"name":"romans.shx","download_url":"https://…"}, …]`.
|
||||
/// OneBSpace (OneCAD Draft): only used by the disabled GitHub fetch + tests.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
#[allow(dead_code)]
|
||||
fn parse_contents(body: &str) -> Result<Vec<RepoFont>, String> {
|
||||
let value: serde_json::Value =
|
||||
serde_json::from_str(body).map_err(|e| format!("Unexpected font listing: {e}"))?;
|
||||
|
||||
+3
-3
@@ -211,7 +211,7 @@ pub fn build_step(meshes: &[&MeshModel]) -> Option<String> {
|
||||
let msb_id = alloc();
|
||||
writeln!(
|
||||
data,
|
||||
"#{} = MANIFOLD_SOLID_BREP('OpenCADStudio_Solid',#{});",
|
||||
"#{} = MANIFOLD_SOLID_BREP('OneCAD_Draft_Solid',#{});",
|
||||
msb_id, shell_id
|
||||
)
|
||||
.ok();
|
||||
@@ -229,7 +229,7 @@ pub fn build_step(meshes: &[&MeshModel]) -> Option<String> {
|
||||
writeln!(data, "#{} = GEOMETRIC_REPRESENTATION_CONTEXT(3);", gc_id).ok();
|
||||
writeln!(
|
||||
data,
|
||||
"#{sr_id} = SHAPE_REPRESENTATION('OpenCADStudio_Shape',(#{}),#{gc_id});",
|
||||
"#{sr_id} = SHAPE_REPRESENTATION('OneCAD_Draft_Shape',(#{}),#{gc_id});",
|
||||
msb_id
|
||||
)
|
||||
.ok();
|
||||
@@ -239,7 +239,7 @@ pub fn build_step(meshes: &[&MeshModel]) -> Option<String> {
|
||||
let file = format!(
|
||||
"ISO-10303-21;\n\
|
||||
HEADER;\n\
|
||||
FILE_DESCRIPTION(('Open CAD Studio STEP export'),'2;1');\n\
|
||||
FILE_DESCRIPTION(('OneCAD Draft STEP export'),'2;1');\n\
|
||||
FILE_NAME('{ts}','','',(''),'',' ',' ');\n\
|
||||
FILE_SCHEMA(('CONFIG_CONTROL_DESIGN'));\n\
|
||||
ENDSEC;\n\
|
||||
|
||||
+13
-5
@@ -1,12 +1,17 @@
|
||||
// Check for a newer published native release.
|
||||
/// Check for a newer published native release.
|
||||
/// OneBSpace (OneCAD Draft): update check disabled — air-gapped build. The
|
||||
/// upstream GitHub-releases probe below is kept for reference but never runs;
|
||||
/// no network call is ever made from this module.
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
#[allow(dead_code)]
|
||||
const RELEASES_API: &str =
|
||||
"https://api.github.com/repos/HakanSeven12/OpenCADStudio/releases/latest";
|
||||
pub const RELEASES_PAGE: &str = "https://github.com/HakanSeven12/OpenCADStudio/releases/latest";
|
||||
|
||||
/// Give release assets time to propagate before offering an update.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
#[allow(dead_code)]
|
||||
const MIN_RELEASE_AGE_SECS: u64 = 60 * 60;
|
||||
|
||||
/// What `check_for_update` reports when a newer release exists.
|
||||
@@ -21,14 +26,14 @@ pub struct UpdateInfo {
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub async fn check_for_update() -> Option<UpdateInfo> {
|
||||
std::thread::spawn(fetch_latest_if_outdated)
|
||||
.join()
|
||||
.ok()
|
||||
.flatten()
|
||||
// OneBSpace (OneCAD Draft): update check disabled — air-gapped build.
|
||||
// Earliest return: no thread is spawned, no HTTP request is made.
|
||||
None
|
||||
}
|
||||
|
||||
/// On wasm there is no background thread or blocking HTTP client; the web build
|
||||
/// skips the self-update check (the page is always served fresh).
|
||||
/// OneBSpace (OneCAD Draft): disabled on every platform — air-gapped build.
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
#[allow(dead_code)]
|
||||
pub async fn check_for_update() -> Option<UpdateInfo> {
|
||||
@@ -36,6 +41,7 @@ pub async fn check_for_update() -> Option<UpdateInfo> {
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
#[allow(dead_code)]
|
||||
fn fetch_latest_if_outdated() -> Option<UpdateInfo> {
|
||||
let agent = crate::network::agent(std::time::Duration::from_secs(5));
|
||||
let body = agent
|
||||
@@ -110,6 +116,7 @@ fn fetch_latest_if_outdated() -> Option<UpdateInfo> {
|
||||
/// Only handles the fixed `YYYY-MM-DDTHH:MM:SSZ` format the GitHub API
|
||||
/// emits; returns `None` for anything else.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
#[allow(dead_code)]
|
||||
fn parse_iso8601_utc(s: &str) -> Option<u64> {
|
||||
let b = s.as_bytes();
|
||||
if b.len() != 20
|
||||
@@ -155,6 +162,7 @@ fn parse_iso8601_utc(s: &str) -> Option<u64> {
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
#[allow(dead_code)]
|
||||
fn is_newer(latest: &str, installed: &str) -> bool {
|
||||
let parse = |version: &str| {
|
||||
let version = version.trim_start_matches('v');
|
||||
|
||||
+12
-12
@@ -71,7 +71,7 @@ pub(super) fn message_attribute(source: &str) -> Option<(&'static str, &'static
|
||||
"Download available" => Some(("modal", "missing-fonts-download-available")),
|
||||
"Skip" => Some(("modal", "missing-fonts-skip")),
|
||||
"Missing fonts" => Some(("modal", "missing-fonts-title")),
|
||||
"This drawing uses fonts that are not installed on this machine. OpenCADStudio can download any redistributable fonts that exist in the selected repository; unavailable fonts will keep using a substitute." => Some(("modal", "missing-fonts-description")),
|
||||
"This drawing uses fonts that are not installed on this machine. OneCAD Draft can download any redistributable fonts that exist in the selected repository; unavailable fonts will keep using a substitute." => Some(("modal", "missing-fonts-description")),
|
||||
"Font source — leave empty for the community repository, or point at any folder (e.g. your company's font server):" => Some(("modal", "missing-fonts-source")),
|
||||
"https://server/fonts or a GitHub raw folder" => Some(("modal", "missing-fonts-source-placeholder")),
|
||||
"Coincident" => Some(("common", "parametric-coincident")),
|
||||
@@ -89,7 +89,7 @@ pub(super) fn message_attribute(source: &str) -> Option<(&'static str, &'static
|
||||
"No sketch open" => Some(("ui", "window-no-sketch-open")),
|
||||
"Bodies ({})" => Some(("ui", "window-bodies")),
|
||||
"No solids yet" => Some(("ui", "window-no-solids-yet")),
|
||||
"Saved immediately. Changes take effect the next time Open CAD Studio starts." => Some(("ui", "window-saved-immediately-changes-take-effect-the-next-t")),
|
||||
"Saved immediately. Changes take effect the next time OneCAD Draft starts." => Some(("ui", "window-saved-immediately-changes-take-effect-the-next-t")),
|
||||
"This session" => Some(("ui", "window-this-session")),
|
||||
"Driver" => Some(("ui", "window-driver")),
|
||||
"Backend" => Some(("ui", "window-backend")),
|
||||
@@ -109,7 +109,7 @@ pub(super) fn message_attribute(source: &str) -> Option<(&'static str, &'static
|
||||
"Connection details" => Some(("ui", "window-connection-details")),
|
||||
"{:.1}% a notch" => Some(("ui", "window-1-a-notch")),
|
||||
"The slider covers the system variable's {} to {}; the field takes up to {} for a faster wheel." => Some(("ui", "window-the-slider-covers-the-system-variable-s-to-the-f")),
|
||||
"Bundled with Open CAD Studio" => Some(("ui", "window-bundled-with-open-cad-studio")),
|
||||
"Bundled with OneCAD Draft" => Some(("ui", "window-bundled-with-open-cad-studio")), /* OneBSpace (OneCAD Draft): literal rebranded, ftl key unchanged */
|
||||
"How the Reference Manager works on web" => Some(("ui", "window-how-the-reference-manager-works-on-web")),
|
||||
"This panel lists the drawing's references read-only: status, type, size, date and saved path, plus the Details pane. Select rows to inspect them; List and Tree switch the presentation." => Some(("ui", "window-this-panel-lists-the-drawing-s-references-read-o")),
|
||||
"Attach, Refresh and Change Path stay disabled here: the web build has no filesystem access and no native file pickers, so references can be neither added, reloaded nor repathed — and previews stay unavailable. Nested references are read-only on every platform, and relative paths need the drawing saved first." => Some(("ui", "window-attach-refresh-and-change-path-stay-disabled-her")),
|
||||
@@ -608,7 +608,7 @@ pub(super) fn message_attribute(source: &str) -> Option<(&'static str, &'static
|
||||
"<none>" => Some(("plot", "none")),
|
||||
"<previous>" => Some(("plot", "previous")),
|
||||
"= {v}" => Some(("inquiry", "v")),
|
||||
"A newer Open CAD Studio version is published on GitHub." => Some(("ui", "a-newer-open-cad-studio-version-is-published-o")),
|
||||
"A newer OneCAD Draft version is published on GitHub." => Some(("ui", "a-newer-open-cad-studio-version-is-published-o")),
|
||||
"AC Version" => Some(("properties", "ac-version")),
|
||||
"ACI Color Index" => Some(("styles", "aci-color-index")),
|
||||
"ACI:" => Some(("styles", "aci")),
|
||||
@@ -2204,7 +2204,7 @@ pub(super) fn message_attribute(source: &str) -> Option<(&'static str, &'static
|
||||
"Major axis vector Z" => Some(("properties", "major-axis-vector-z")),
|
||||
"Major radius" => Some(("properties", "major-radius")),
|
||||
"Make Current" => Some(("layers", "make-current")),
|
||||
"Make Open CAD Studio your default CAD app?" => Some(("modal", "make-open-cad-studio-your-default-cad-app")),
|
||||
"Make OneCAD Draft your default CAD app?" => Some(("modal", "make-open-cad-studio-your-default-cad-app")), /* OneBSpace (OneCAD Draft): literal rebranded, ftl key unchanged */
|
||||
"Manage" => Some(("common", "manage")),
|
||||
"Manage..." => Some(("ui", "manage-menu-period-title-case")),
|
||||
"Manage…" => Some(("ui", "manage-picker-title-case")),
|
||||
@@ -2414,8 +2414,8 @@ pub(super) fn message_attribute(source: &str) -> Option<(&'static str, &'static
|
||||
"Opacity" => Some(("properties", "opacity")),
|
||||
"Opacity Map" => Some(("properties", "opacity-map")),
|
||||
"Open" => Some(("common", "open")),
|
||||
"Open .dwg and .dxf drawings in Open CAD Studio by default. You can change this later in your system settings." => Some(("modal", "open-dwg-and-dxf-drawings-in-open-cad-studio-b")),
|
||||
"Open CAD Studio could not trust the certificate presented for the plugin registry. Check your system certificate and proxy settings, then retry." => Some(("plugins", "open-cad-studio-could-not-trust-the-certificat")),
|
||||
"Open .dwg and .dxf drawings in OneCAD Draft by default. You can change this later in your system settings." => Some(("modal", "open-dwg-and-dxf-drawings-in-open-cad-studio-b")), /* OneBSpace (OneCAD Draft): literal rebranded, ftl key unchanged */
|
||||
"OneCAD Draft could not trust the certificate presented for the plugin registry. Check your system certificate and proxy settings, then retry." => Some(("plugins", "open-cad-studio-could-not-trust-the-certificat")),
|
||||
"Open CAD Studio plugins are native packages and cannot run inside a browser. Download the desktop app to browse, install, and use plugins." => Some(("plugins", "open-cad-studio-plugins-are-native-packages-an")),
|
||||
"Open CAD Studio ready." => Some(("file", "open-cad-studio-ready")),
|
||||
"Open DWG/DXF: not yet implemented." => Some(("common", "open-dwg-dxf-not-yet-implemented")),
|
||||
@@ -3024,7 +3024,7 @@ pub(super) fn message_attribute(source: &str) -> Option<(&'static str, &'static
|
||||
"Save failed: {error}" => Some(("file", "save-failed-error")),
|
||||
"Save failed: {e}" => Some(("file", "save-failed-e")),
|
||||
"Save in source version" => Some(("common", "save-in-source-version")),
|
||||
"Save stopped: \"{file_name}\" changed outside Open CAD Studio." => Some(("file", "save-stopped-file-name-changed-outside-open-ca")),
|
||||
"Save stopped: \"{file_name}\" changed outside OneCAD Draft." => Some(("file", "save-stopped-file-name-changed-outside-open-ca")),
|
||||
"Save the drawing before copying its file path." => Some(("common", "save-the-drawing-before-copying-its-file-path")),
|
||||
"Save the drawing before opening its file location." => Some(("common", "save-the-drawing-before-opening-its-file-locat")),
|
||||
"Save to PDF file…" => Some(("plot", "save-to-pdf-file")),
|
||||
@@ -3477,7 +3477,7 @@ pub(super) fn message_attribute(source: &str) -> Option<(&'static str, &'static
|
||||
"Unavailable" => Some(("plugins", "unavailable")),
|
||||
"Supported" => Some(("dgn-import", "supported")),
|
||||
"By extension" => Some(("dgn-import", "by-extension")),
|
||||
"OpenCAD Studio has no importer for this format." => Some(("dgn-import", "no-importer")),
|
||||
"OneCAD Draft has no importer for this format." => Some(("dgn-import", "no-importer")), /* OneBSpace (OneCAD Draft): literal rebranded, ftl key unchanged */
|
||||
"Recent:" => Some(("dgn-import", "recent")),
|
||||
"2D / Underlay" => Some(("dgn-import", "group-2d")),
|
||||
"3D Model" => Some(("dgn-import", "group-3d")),
|
||||
@@ -4510,7 +4510,7 @@ pub(super) fn message_attribute(source: &str) -> Option<(&'static str, &'static
|
||||
"Include matching objects" => Some(("common", "include-matching-objects")),
|
||||
"Exclude matching objects" => Some(("common", "exclude-matching-objects")),
|
||||
"Append result to current selection" => Some(("common", "append-result-to-current-selection")),
|
||||
"Open CAD Studio — 2D/3D CAD editor" => Some(("common", "open-cad-studio-2d-3d-cad-editor")),
|
||||
"OneCAD Draft — 2D/3D CAD editor" => Some(("common", "open-cad-studio-2d-3d-cad-editor")), /* OneBSpace (OneCAD Draft): literal rebranded, ftl key unchanged */
|
||||
"CAD files to open at startup (.dwg / .dxf)." => Some(("common", "cad-files-to-open-at-startup-dwg-dxf")),
|
||||
"Start with a new empty drawing." => Some(("common", "start-with-a-new-empty-drawing")),
|
||||
"Start a new editor process." => Some(("common", "start-a-new-editor-process")),
|
||||
@@ -4987,7 +4987,7 @@ pub(super) fn message_attribute(source: &str) -> Option<(&'static str, &'static
|
||||
"Base minor radius" => Some(("common", "base-minor-radius")),
|
||||
"Top major radius" => Some(("common", "top-major-radius")),
|
||||
"Top minor radius" => Some(("common", "top-minor-radius")),
|
||||
"OpenCADStudio renderer error — copy this into a bug report:" => Some(("common", "opencadstudio-renderer-error-copy-this-into-a-bug-report")),
|
||||
"OneCAD Draft renderer error — copy this into a bug report:" => Some(("common", "opencadstudio-renderer-error-copy-this-into-a-bug-report")), // OneBSpace (OneCAD Draft): literal rebranded, ftl key unchanged,
|
||||
"Dismiss" => Some(("common", "dismiss")),
|
||||
"?" => Some(("common", "value-8a8de8")),
|
||||
"Select Color..." => Some(("common", "select-color-8dddf1")),
|
||||
@@ -5070,7 +5070,7 @@ pub(super) fn message_attribute(source: &str) -> Option<(&'static str, &'static
|
||||
"Translate from" => Some(("common", "translate-from")),
|
||||
"Translate to" => Some(("common", "translate-to")),
|
||||
"%{n} mapping(s)" => Some(("common", "mapping-s")),
|
||||
"Open .dwg and .dxf files with Open CAD Studio" => Some(("common", "open-dwg-and-dxf-files-with-open-cad-studio")),
|
||||
"Open .dwg and .dxf files with OneCAD Draft" => Some(("common", "open-dwg-and-dxf-files-with-open-cad-studio")), /* OneBSpace (OneCAD Draft): literal rebranded, ftl key unchanged */
|
||||
"Also installs the application and file-type icons the desktop shows." => Some(("common", "also-installs-the-application-and-file-type-icons-the-desktop-shows")),
|
||||
"Model Space Appearance" => Some(("common", "model-space-appearance")),
|
||||
"Restore Defaults" => Some(("common", "restore-defaults")),
|
||||
|
||||
+1
-1
@@ -944,7 +944,7 @@ fn sessions(launch_if_none: bool) -> Result<Vec<Value>, String> {
|
||||
if claimed {
|
||||
release_startup_lock(&directory);
|
||||
}
|
||||
return Err(format!("OpenCADStudio exited while starting ({status})"));
|
||||
return Err(format!("OneCAD Draft exited while starting ({status})" /* OneBSpace (OneCAD Draft): rebranded */));
|
||||
}
|
||||
}
|
||||
thread::sleep(Duration::from_millis(200));
|
||||
|
||||
+3
-3
@@ -21,9 +21,9 @@ const USD_RATES_URL: &str = "https://api.frankfurter.dev/v2/rates?base=USD";
|
||||
/// To add a supporter, add a `("Display name", usd_cents)` line below. The
|
||||
/// amount is in **USD cents**: a $25 donation is `2500`; convert other
|
||||
/// currencies to USD before adding them.
|
||||
const MANUAL_SUPPORTERS: &[(&str, i64)] = &[
|
||||
("Stefano", 10_500), // $105
|
||||
];
|
||||
/// OneBSpace (OneCAD Draft): the upstream hand-maintained supporter list was
|
||||
/// cleared; the fetch functions are never called in the air-gapped build.
|
||||
const MANUAL_SUPPORTERS: &[(&str, i64)] = &[];
|
||||
|
||||
/// Append the hand-maintained [`MANUAL_SUPPORTERS`] to `patrons` and sort the
|
||||
/// combined list by amount (highest first, then alphabetically). Both the
|
||||
|
||||
@@ -20,7 +20,16 @@ pub(crate) const REGISTRY_URL: &str =
|
||||
"https://raw.githubusercontent.com/HakanSeven12/OpenCADStudio/main/plugins/registry.json";
|
||||
|
||||
/// Fetch the curated plugin registry (`plugins/registry.json`).
|
||||
/// OneBSpace (OneCAD Draft): the curated upstream marketplace registry is
|
||||
/// disabled — air-gapped build; the GitHub fetch is kept below for reference
|
||||
/// but never runs. Locally installed / user-added repositories still work.
|
||||
pub fn fetch_registry() -> Result<Vec<RegistryEntry>, String> {
|
||||
let _ = REGISTRY_URL;
|
||||
Ok(Vec::new())
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn fetch_registry_github() -> Result<Vec<RegistryEntry>, String> {
|
||||
let body = download_string(REGISTRY_URL)?;
|
||||
let json: serde_json::Value = serde_json::from_str(&body).map_err(|e| e.to_string())?;
|
||||
let arr = json.as_array().ok_or("registry is not a JSON array")?;
|
||||
|
||||
+3
-3
@@ -1122,7 +1122,7 @@ pub mod crash_log {
|
||||
// boundaries still place the fault.
|
||||
let backtrace = std::backtrace::Backtrace::force_capture();
|
||||
[
|
||||
format!("Open CAD Studio {} crash report", env!("OCS_APP_VERSION")),
|
||||
format!("OneCAD Draft {} crash report", env!("OCS_APP_VERSION")), // OneBSpace (OneCAD Draft): rebranded wordmark
|
||||
format!("when: {when} (unix seconds)"),
|
||||
format!("os: {} {}", std::env::consts::OS, std::env::consts::ARCH),
|
||||
format!("gpu backend: {backend}"),
|
||||
@@ -1198,7 +1198,7 @@ pub mod crash_log {
|
||||
#[test]
|
||||
fn a_report_names_the_message_and_the_line() {
|
||||
let text = super::report_from("a deliberate test panic", "src/sys.rs:1:2", 42);
|
||||
assert!(text.starts_with("Open CAD Studio "), "{text}");
|
||||
assert!(text.starts_with("OneCAD Draft "), "{text}");
|
||||
assert!(text.contains("panic: a deliberate test panic"), "{text}");
|
||||
assert!(text.contains("at: src/sys.rs:1:2"), "{text}");
|
||||
assert!(text.contains("when: 42 (unix seconds)"), "{text}");
|
||||
@@ -1347,7 +1347,7 @@ pub mod web_diag {
|
||||
for (id, label) in [
|
||||
(
|
||||
"ocs-err-title",
|
||||
crate::t!("OpenCADStudio renderer error — copy this into a bug report:"),
|
||||
crate::t!("OneCAD Draft renderer error — copy this into a bug report:"), // OneBSpace (OneCAD Draft): rebranded
|
||||
),
|
||||
("ocs-err-copy", crate::t!("Copy")),
|
||||
("ocs-err-dismiss", crate::t!("Dismiss")),
|
||||
|
||||
@@ -111,7 +111,7 @@ pub(crate) fn report() -> String {
|
||||
let sys = system_info();
|
||||
#[allow(unused_mut)]
|
||||
let mut out = format!(
|
||||
"Open CAD Studio v{}\nRevision: {}\nCommit date: {}\nProfile: {}\nFeatures: {}\n\n\
|
||||
"OneCAD Draft v{}\nRevision: {}\nCommit date: {}\nProfile: {}\nFeatures: {}\n\n\
|
||||
[System]\nOS: {} ({} {})\nCPU: {}\nLogical processors: {}\nRAM: {} total, {} available\n",
|
||||
env!("OCS_FULL_VERSION"),
|
||||
env!("OCS_GIT_REV"),
|
||||
@@ -195,7 +195,7 @@ pub fn view_window(sizing: crate::ui::modal::ModalSizing) -> Element<'static, Me
|
||||
row![
|
||||
logo,
|
||||
column![
|
||||
text("Open CAD Studio").size(28).style(primary_style),
|
||||
text("OneCAD Draft").size(28).style(primary_style), // OneBSpace (OneCAD Draft): rebranded wordmark
|
||||
text(t!("CAD application for Architecture & Engineering"))
|
||||
.size(11)
|
||||
.style(muted_style),
|
||||
|
||||
@@ -238,7 +238,7 @@ fn badge<'a>(support: Support) -> Element<'a, Message> {
|
||||
pub fn unsupported_reason(support: Support) -> Option<std::borrow::Cow<'static, str>> {
|
||||
match support {
|
||||
Support::Yes | Support::ByExtension => None,
|
||||
Support::No => Some(t!("OpenCAD Studio has no importer for this format.")),
|
||||
Support::No => Some(t!("OneCAD Draft has no importer for this format.")) /* OneBSpace (OneCAD Draft): rebranded */,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ pub fn view_window<'a>(
|
||||
column![
|
||||
text(crate::t!("Missing fonts")).size(20),
|
||||
text(crate::t!(
|
||||
"This drawing uses fonts that are not installed on this machine. OpenCADStudio can download any redistributable fonts that exist in the selected repository; unavailable fonts will keep using a substitute."
|
||||
"This drawing uses fonts that are not installed on this machine. OneCAD Draft can download any redistributable fonts that exist in the selected repository; unavailable fonts will keep using a substitute."
|
||||
))
|
||||
.size(11)
|
||||
.style(muted_style),
|
||||
|
||||
@@ -456,7 +456,7 @@ pub fn view_window<'a>(
|
||||
iced::widget::checkbox(file_assoc_enabled)
|
||||
.on_toggle(Message::FileAssocChanged)
|
||||
.size(15),
|
||||
text(crate::t!("Open .dwg and .dxf files with Open CAD Studio")).size(12),
|
||||
text(crate::t!("Open .dwg and .dxf files with OneCAD Draft")) /* OneBSpace (OneCAD Draft): rebranded */.size(12),
|
||||
]
|
||||
.spacing(8)
|
||||
.align_y(iced::Center),
|
||||
|
||||
@@ -39,7 +39,7 @@ pub(crate) fn view(prefs: GraphicsPrefs, active: ActiveGpu) -> Element<'static,
|
||||
text(crate::t!("Graphics")).size(15),
|
||||
Space::new().height(6),
|
||||
text(crate::t!(
|
||||
"Saved immediately. Changes take effect the next time Open CAD Studio starts."
|
||||
"Saved immediately. Changes take effect the next time OneCAD Draft starts."
|
||||
))
|
||||
.size(11)
|
||||
.width(Fill),
|
||||
|
||||
@@ -124,7 +124,7 @@ pub(crate) fn view(
|
||||
let detail = match status {
|
||||
Status::Unavailable(reason) => reason,
|
||||
Status::Unsupported => "This version supports SpaceMouse through 3DxWare on Windows. Other platforms do not yet have a device adapter.".into(),
|
||||
Status::Disconnected => "3DxWare is running. Connect a SpaceMouse; Open CAD Studio reconnects automatically.".into(),
|
||||
Status::Disconnected => "3DxWare is running. Connect a SpaceMouse; OneCAD Draft reconnects automatically.".into(),
|
||||
_ => "Uses the installed 3DxWare driver. Navigation pauses while a dialog is open. Your selected navigation mode is saved across drawings and sessions.".into(),
|
||||
};
|
||||
content = content.push(text(crate::t!(&detail).into_owned()).size(11).width(Fill));
|
||||
|
||||
@@ -38,10 +38,8 @@ pub struct MarketView<'a> {
|
||||
pub status: &'a str,
|
||||
}
|
||||
|
||||
/// Latest desktop builds, used by the browser-only plugin notice.
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
pub const DESKTOP_DOWNLOAD_URL: &str =
|
||||
"https://github.com/HakanSeven12/OpenCADStudio/releases/latest";
|
||||
// OneBSpace (OneCAD Draft): the upstream desktop-download link was removed —
|
||||
// the browser-only plugin notice no longer links anywhere external.
|
||||
|
||||
// Register the command names for autocomplete. On the web they open a desktop
|
||||
// download notice instead of the native marketplace.
|
||||
@@ -308,7 +306,7 @@ fn external_card<'a>(
|
||||
}
|
||||
if p.bundled {
|
||||
actions = actions.push(
|
||||
text(t!("Bundled with Open CAD Studio"))
|
||||
text(t!("Bundled with OneCAD Draft")) /* OneBSpace (OneCAD Draft): rebranded */
|
||||
.size(11)
|
||||
.style(muted_style),
|
||||
);
|
||||
@@ -477,7 +475,7 @@ fn registry_error_message(error: &str) -> (Cow<'static, str>, Cow<'static, str>)
|
||||
(
|
||||
t!("Unable to verify the server certificate"),
|
||||
t!(
|
||||
"Open CAD Studio could not trust the certificate presented for the plugin registry. Check your system certificate and proxy settings, then retry."
|
||||
"OneCAD Draft could not trust the certificate presented for the plugin registry. Check your system certificate and proxy settings, then retry."
|
||||
),
|
||||
)
|
||||
} else if error.contains("timed out") || error.contains("timeout") {
|
||||
@@ -915,14 +913,8 @@ pub fn view_window<'a>(
|
||||
/// Browser replacement for the native Plugin Manager.
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
pub fn view_web_notice<'a>() -> Element<'a, Message> {
|
||||
let download = button(text(t!("Download desktop app")).size(13))
|
||||
.on_press(Message::OpenUrl(DESKTOP_DOWNLOAD_URL.to_string()))
|
||||
.padding([9, 18])
|
||||
.style(|theme: &Theme, status| {
|
||||
let mut style = button::primary(theme, status);
|
||||
style.text_color = iced::Color::WHITE;
|
||||
style
|
||||
});
|
||||
// OneBSpace (OneCAD Draft): the "Download desktop app" button was removed —
|
||||
// no external download links in the air-gapped embedded build.
|
||||
|
||||
let icon = container(crate::ui::icons::themed_primary(
|
||||
crate::ui::icons::GEAR,
|
||||
@@ -946,14 +938,13 @@ pub fn view_web_notice<'a>() -> Element<'a, Message> {
|
||||
.width(Length::Fit)
|
||||
.align_x(iced::alignment::Horizontal::Center),
|
||||
text(t!(
|
||||
"Open CAD Studio plugins are native packages and cannot run inside a browser. Download the desktop app to browse, install, and use plugins."
|
||||
"OneCAD Draft plugins are native packages and cannot run inside a browser. Use the desktop build to browse, install, and use plugins." // OneBSpace (OneCAD Draft): rebranded, no external download link
|
||||
))
|
||||
.size(13)
|
||||
.width(Length::Fit)
|
||||
.align_x(iced::alignment::Horizontal::Center)
|
||||
.style(muted_style),
|
||||
Space::new().height(4),
|
||||
download,
|
||||
]
|
||||
.spacing(10)
|
||||
.align_x(iced::alignment::Horizontal::Center)
|
||||
|
||||
@@ -136,7 +136,7 @@ pub fn view_window<'a>(
|
||||
.size(20)
|
||||
.style(primary_style),
|
||||
text(t!(
|
||||
"A newer Open CAD Studio version is published on GitHub."
|
||||
"A newer OneCAD Draft version is published on GitHub."
|
||||
))
|
||||
.size(11)
|
||||
.style(muted_style),
|
||||
|
||||
@@ -6,13 +6,11 @@
|
||||
|
||||
use crate::app::Message;
|
||||
use crate::ui::style::common::muted_style;
|
||||
use crate::ui::style::form::dialog_button;
|
||||
use iced::widget::{column, container, row, text, Space};
|
||||
use iced::{Background, Element, Fill, Length, Theme};
|
||||
|
||||
/// GitHub issues page linked from the help window, so web users can report
|
||||
/// missing or broken behavior where it will be seen.
|
||||
pub const XREF_ISSUES_URL: &str = "https://github.com/HakanSeven12/OpenCADStudio/issues";
|
||||
// OneBSpace (OneCAD Draft): the GitHub issues link was removed — air-gapped
|
||||
// build keeps help text only, with no external links.
|
||||
|
||||
pub fn view_window(sizing: crate::ui::modal::ModalSizing) -> Element<'static, Message> {
|
||||
// Fixed window width: paragraphs wrap against this instead of the
|
||||
@@ -34,21 +32,10 @@ pub fn view_window(sizing: crate::ui::modal::ModalSizing) -> Element<'static, Me
|
||||
)
|
||||
.into_owned(),
|
||||
);
|
||||
let report_hint = para(
|
||||
crate::t!(
|
||||
"Hit something broken or missing? Report it on the GitHub issues page so it can be fixed."
|
||||
)
|
||||
.into_owned(),
|
||||
);
|
||||
|
||||
let report_button = dialog_button(
|
||||
crate::t!("Report an issue"),
|
||||
Message::OpenUrl(XREF_ISSUES_URL.to_string()),
|
||||
true,
|
||||
);
|
||||
let close_button = dialog_button(crate::t!("Close"), Message::CloseModal, false);
|
||||
let close_button = crate::ui::style::form::dialog_button(crate::t!("Close"), Message::CloseModal, false);
|
||||
let action_row: Element<'static, Message> =
|
||||
row![Space::new().width(Fill), report_button, close_button,]
|
||||
row![Space::new().width(Fill), close_button,]
|
||||
.spacing(8)
|
||||
.align_y(iced::Center)
|
||||
.into();
|
||||
@@ -61,7 +48,6 @@ pub fn view_window(sizing: crate::ui::modal::ModalSizing) -> Element<'static, Me
|
||||
intro,
|
||||
list,
|
||||
limits,
|
||||
report_hint,
|
||||
Space::new().height(4),
|
||||
action_row,
|
||||
]
|
||||
@@ -78,12 +64,3 @@ pub fn view_window(sizing: crate::ui::modal::ModalSizing) -> Element<'static, Me
|
||||
})
|
||||
.into()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn issues_url_points_at_github_issues() {
|
||||
assert!(super::XREF_ISSUES_URL.starts_with("https://github.com/"));
|
||||
assert!(super::XREF_ISSUES_URL.contains("/issues"));
|
||||
}
|
||||
}
|
||||
+3
-9
@@ -212,16 +212,10 @@ pub async fn fetch_playlist_web() -> Result<Vec<VideoEntry>, String> {
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
async fn fetch_thumbnail_web(id: String) -> Result<Vec<u8>, String> {
|
||||
// OneBSpace (OneCAD Draft): only the LOCAL same-origin thumbnail cache is
|
||||
// read; the YouTube image-CDN fallback was removed — air-gapped build.
|
||||
let local = format!("video_thumbs/{id}.jpg");
|
||||
match fetch_thumbnail_url(&local).await {
|
||||
Ok(bytes) => Ok(bytes),
|
||||
Err(_) => {
|
||||
// Local development uses the checked-in JSON snapshot without
|
||||
// binary thumbnails. YouTube's image CDN explicitly permits CORS,
|
||||
// so it is a safe fallback; deployed Pages builds use local files.
|
||||
fetch_thumbnail_url(&format!("https://i.ytimg.com/vi/{id}/mqdefault.jpg")).await
|
||||
}
|
||||
}
|
||||
fetch_thumbnail_url(&local).await
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
|
||||
Reference in new issue
Block a user