forked from 1b-agent/opencadstudio-upstream
feat(app): first-launch prompt to set Open CAD Studio as default for .dwg/.dxf
On the first launch that hasn't answered it yet, the app shows a small
dialog offering to become the default handler for .dwg and .dxf files.
The choice is persisted (default_assoc_prompted) so the prompt never
reappears.
The platform plumbing lives in io/file_association.rs:
* Windows — opens the OS's own per-app default-programs dialog via
IApplicationAssociationRegistrationUI::LaunchAdvancedAssociationUI,
passing the "Open CAD Studio" RegisteredApplications name the MSI
registers. Modern Windows guards the actual default behind a
UserChoice hash, so this is the supported consent path.
* Linux — xdg-mime default against the installed .desktop file, whose
MimeType entries already cover image/vnd.dwg and image/vnd.dxf.
* macOS — LSSetDefaultRoleHandlerForContentType binds the DWG/DXF UTIs
declared in Info.plist to the app bundle id.
The work runs on a dedicated thread (the Windows dialog is modal) with
the result delivered back through a oneshot channel and surfaced in the
command line.
https://claude.ai/code/session_01DFVSKgViFaxEjZD2KsTdtt
This commit is contained in:
7 files changed
+457
-3
No files matched your search
+8
-1
@@ -70,6 +70,10 @@ pub struct UserSettings {
|
||||
pub otrack: bool,
|
||||
/// Active snap modes, in `SNAP_ORDER`.
|
||||
pub snap_modes: Vec<SnapType>,
|
||||
/// Whether the one-time "make Open CAD Studio the default for .dwg/.dxf?"
|
||||
/// prompt has already been shown. Set once the user answers (either way),
|
||||
/// so we never nag again on subsequent launches.
|
||||
pub default_assoc_prompted: bool,
|
||||
}
|
||||
|
||||
impl Default for UserSettings {
|
||||
@@ -91,6 +95,7 @@ impl Default for UserSettings {
|
||||
SnapType::Intersection,
|
||||
SnapType::Nearest,
|
||||
],
|
||||
default_assoc_prompted: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -124,6 +129,7 @@ impl UserSettings {
|
||||
"grid" => s.show_grid = val == "1",
|
||||
"osnap" => s.snap_enabled = val == "1",
|
||||
"otrack" => s.otrack = val == "1",
|
||||
"default_assoc_prompted" => s.default_assoc_prompted = val == "1",
|
||||
"snap_modes" => {
|
||||
let modes: Vec<SnapType> =
|
||||
val.split(',').filter_map(|t| snap_from_id(t.trim())).collect();
|
||||
@@ -149,7 +155,7 @@ impl UserSettings {
|
||||
.collect::<Vec<_>>()
|
||||
.join(",");
|
||||
let body = format!(
|
||||
"dyn={}\northo={}\npolar={}\npolar_increment_deg={}\ngrid={}\nosnap={}\notrack={}\nsnap_modes={}\n",
|
||||
"dyn={}\northo={}\npolar={}\npolar_increment_deg={}\ngrid={}\nosnap={}\notrack={}\ndefault_assoc_prompted={}\nsnap_modes={}\n",
|
||||
b(self.dyn_input),
|
||||
b(self.ortho),
|
||||
b(self.polar),
|
||||
@@ -157,6 +163,7 @@ impl UserSettings {
|
||||
b(self.show_grid),
|
||||
b(self.snap_enabled),
|
||||
b(self.otrack),
|
||||
b(self.default_assoc_prompted),
|
||||
modes,
|
||||
);
|
||||
let _ = std::fs::write(path, body);
|
||||
|
||||
Reference in new issue
Block a user