forked from 1b-agent/opencadstudio-upstream
feat(app): add fixed Start tab with welcome page and recent documents
A pinned "Start" tab now lives at index 0. It cannot be closed, opens on launch, and replaces the model-space viewport with a welcome page — similar to Thunderbird's first-run screen. - Boot opens with only the Start tab; Drawing1 is no longer auto-spawned. - The Properties left panel becomes a Recent Documents rail on the Start tab. Recents persist to disk (%APPDATA%/H7CAD/recent.txt on Windows, $XDG_CONFIG_HOME/H7CAD/recent.txt on Linux, ~/Library/Application Support/H7CAD/recent.txt on macOS), up to 20 entries, saved on every open and rehydrated at boot. Each row opens or removes the file in place. - The Support ribbon group (Donate / Report / About / Changelog) is retired; the same actions surface on the welcome page instead. The Donate button is the primary call-to-action — solid #B03020 brand fill with a soft brand-tinted ambient glow halo behind the action row (Thunderbird-style coloured glow against the neutral page). - Drawing-only overlays (mouse-area, viewcube, navbar, dynamic input, selection markers) are suppressed on the Start tab so its clicks don't trigger CAD commands. OpenFile's "current_is_empty" check refuses to replace the Start tab, and TabClose ignores requests on it. Co-Authored-By: Claude Opus 4.7 <[email protected]>
This commit is contained in:
1 parent
3fb23ae31b
commit
35acdb2dc8
10 files changed
+515
-72
No files matched your search
+61
-1
@@ -92,7 +92,20 @@ impl AppMenu {
|
||||
pub fn push_recent(&mut self, path: PathBuf) {
|
||||
self.recent.retain(|r| r != &path);
|
||||
self.recent.insert(0, path);
|
||||
self.recent.truncate(10);
|
||||
self.recent.truncate(20);
|
||||
// Best-effort persist; silent on failure (read-only home, full disk).
|
||||
let _ = save_recents(&self.recent);
|
||||
}
|
||||
|
||||
/// Drop a path from the recents list (manual removal from Start page).
|
||||
pub fn remove_recent(&mut self, path: &std::path::Path) {
|
||||
self.recent.retain(|r| r.as_path() != path);
|
||||
let _ = save_recents(&self.recent);
|
||||
}
|
||||
|
||||
/// Rehydrate the recents list from disk. Call once at app boot.
|
||||
pub fn load_persistent_recents(&mut self) {
|
||||
self.recent = load_recents();
|
||||
}
|
||||
|
||||
pub fn toggle(&mut self) {
|
||||
@@ -484,3 +497,50 @@ const EXIT_BTN: Color = Color {
|
||||
b: 0.10,
|
||||
a: 1.0,
|
||||
};
|
||||
|
||||
// ── Recent-files persistence ─────────────────────────────────────────────
|
||||
//
|
||||
// Plain-text format, one path per line, newest first. Lives next to other
|
||||
// per-user config so we don't pull in a TOML/JSON crate just for this.
|
||||
|
||||
fn recents_file_path() -> Option<PathBuf> {
|
||||
let base: PathBuf = if cfg!(target_os = "windows") {
|
||||
std::env::var_os("APPDATA").map(PathBuf::from)?
|
||||
} else if cfg!(target_os = "macos") {
|
||||
let home = std::env::var_os("HOME")?;
|
||||
let mut p = PathBuf::from(home);
|
||||
p.push("Library");
|
||||
p.push("Application Support");
|
||||
p
|
||||
} else if let Some(d) = std::env::var_os("XDG_CONFIG_HOME") {
|
||||
PathBuf::from(d)
|
||||
} else {
|
||||
let home = std::env::var_os("HOME")?;
|
||||
let mut p = PathBuf::from(home);
|
||||
p.push(".config");
|
||||
p
|
||||
};
|
||||
let mut p = base;
|
||||
p.push("H7CAD");
|
||||
Some(p.join("recent.txt"))
|
||||
}
|
||||
|
||||
fn save_recents(list: &[PathBuf]) -> std::io::Result<()> {
|
||||
let Some(path) = recents_file_path() else { return Ok(()); };
|
||||
if let Some(dir) = path.parent() { std::fs::create_dir_all(dir)?; }
|
||||
let body: String = list
|
||||
.iter()
|
||||
.map(|p| p.to_string_lossy().into_owned())
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n");
|
||||
std::fs::write(path, body)
|
||||
}
|
||||
|
||||
fn load_recents() -> Vec<PathBuf> {
|
||||
let Some(path) = recents_file_path() else { return vec![]; };
|
||||
let Ok(body) = std::fs::read_to_string(path) else { return vec![]; };
|
||||
body.lines()
|
||||
.filter(|l| !l.trim().is_empty())
|
||||
.map(PathBuf::from)
|
||||
.collect()
|
||||
}
|
||||
Reference in new issue
Block a user