fix(start): complete Start page workflow
Track Save As paths, persist the selected section, and size tabbed panels from their actual available width. Refs #443
This commit is contained in:
parent
77ea43fb96
commit
658aa4a4a5
5 changed files with 61 additions and 19 deletions
|
|
@ -20,6 +20,8 @@ pub struct AppConfig {
|
|||
pub settings: UserSettings,
|
||||
/// Recent-files list + retained count.
|
||||
pub recent: RecentConfig,
|
||||
/// Last selected section on the tabbed Start page.
|
||||
pub start: StartConfig,
|
||||
/// Which status-bar pills the user has hidden.
|
||||
pub statusbar: StatusBarConfig,
|
||||
/// Ribbon collapse density.
|
||||
|
|
@ -34,6 +36,7 @@ impl Default for AppConfig {
|
|||
Self {
|
||||
settings: UserSettings::default(),
|
||||
recent: RecentConfig::default(),
|
||||
start: StartConfig::default(),
|
||||
statusbar: StatusBarConfig::default(),
|
||||
ribbon: RibbonConfig::default(),
|
||||
plot: PlotDialogState::default(),
|
||||
|
|
@ -59,6 +62,12 @@ impl Default for RecentConfig {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Serialize, Deserialize, Default)]
|
||||
#[serde(default)]
|
||||
pub struct StartConfig {
|
||||
pub section: super::StartSection,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Serialize, Deserialize, Default)]
|
||||
#[serde(default)]
|
||||
pub struct RibbonConfig {
|
||||
|
|
|
|||
|
|
@ -211,7 +211,9 @@ struct AddSelectedRestore {
|
|||
}
|
||||
|
||||
/// Which Start-page section a narrow (tabbed) Start page is showing.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Default, Debug)]
|
||||
#[derive(
|
||||
Clone, Copy, PartialEq, Eq, Default, Debug, serde::Serialize, serde::Deserialize,
|
||||
)]
|
||||
pub enum StartSection {
|
||||
Recent,
|
||||
Videos,
|
||||
|
|
|
|||
|
|
@ -292,6 +292,9 @@ impl OpenCADStudio {
|
|||
.collect(),
|
||||
limit: self.recent_limit,
|
||||
},
|
||||
start: crate::app::config::StartConfig {
|
||||
section: self.start_section,
|
||||
},
|
||||
statusbar: self.statusbar_config.clone(),
|
||||
ribbon: crate::app::config::RibbonConfig {
|
||||
collapse: self.ribbon.collapse_mode(),
|
||||
|
|
@ -317,6 +320,7 @@ impl OpenCADStudio {
|
|||
self.recent_limit_input = self.recent_limit.to_string();
|
||||
// Thumbnails are decoded by a background task queued at boot
|
||||
// (`refresh_recent_thumbs`) — never here on the boot path.
|
||||
self.start_section = cfg.start.section;
|
||||
self.statusbar_config = cfg.statusbar;
|
||||
self.ribbon.set_collapse_mode(cfg.ribbon.collapse);
|
||||
self.plot_dialog = cfg.plot;
|
||||
|
|
@ -952,9 +956,14 @@ pub(super) fn on_open_file(&mut self) -> Task<Message> {
|
|||
self.tabs[i].current_path = Some(path.clone());
|
||||
self.tabs[i].dirty = false;
|
||||
let _ = std::fs::remove_file(path.with_extension("sv$"));
|
||||
let recent = self.push_recent(path.clone());
|
||||
if self.save_dialog_for_unsaved {
|
||||
return self.update(Message::UnsavedPickedSavePath(Some(path)));
|
||||
return Task::batch([
|
||||
recent,
|
||||
self.update(Message::UnsavedPickedSavePath(Some(path))),
|
||||
]);
|
||||
}
|
||||
return recent;
|
||||
}
|
||||
Err(e) => self.command_line.push_error(&format!("Save failed: {e}")),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -224,6 +224,7 @@ impl OpenCADStudio {
|
|||
|
||||
Message::StartSectionSelect(section) => {
|
||||
self.start_section = section;
|
||||
self.save_config();
|
||||
Task::none()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -115,18 +115,21 @@ impl OpenCADStudio {
|
|||
// viewport draws the layout's own geometry (white sheet + entities +
|
||||
// borders) and the floating content viewports blit on top.
|
||||
let viewport_3d: Element<'_, Message> = if tab.is_start {
|
||||
start_page_view(
|
||||
&self.patrons,
|
||||
&self.videos,
|
||||
self.videos_loading,
|
||||
&self.video_thumbs,
|
||||
&self.recent_files,
|
||||
&self.recent_thumbs,
|
||||
self.recent_limit,
|
||||
&self.recent_limit_input,
|
||||
self.win_size.0,
|
||||
self.start_section,
|
||||
)
|
||||
responsive(|size| {
|
||||
start_page_view(
|
||||
&self.patrons,
|
||||
&self.videos,
|
||||
self.videos_loading,
|
||||
&self.video_thumbs,
|
||||
&self.recent_files,
|
||||
&self.recent_thumbs,
|
||||
self.recent_limit,
|
||||
&self.recent_limit_input,
|
||||
size.width,
|
||||
self.start_section,
|
||||
)
|
||||
})
|
||||
.into()
|
||||
} else if is_paper {
|
||||
shader(ViewportPane::model(
|
||||
&tab.scene,
|
||||
|
|
@ -2504,7 +2507,17 @@ pub(super) fn start_page_view<'a>(
|
|||
let fits_all = avail
|
||||
>= recent_w + sup_w + 2.0 * 16.0 + welcome_min + 2.0 * (videos_w + 16.0);
|
||||
|
||||
let recent = recent_files_panel(recents, thumbs, recent_limit, recent_limit_input);
|
||||
let recent = recent_files_panel(
|
||||
recents,
|
||||
thumbs,
|
||||
recent_limit,
|
||||
recent_limit_input,
|
||||
if fits_all {
|
||||
iced::Length::Fixed(recent_w)
|
||||
} else {
|
||||
iced::Length::Fill
|
||||
},
|
||||
);
|
||||
let welcome = container(content).width(Fill).height(Fill);
|
||||
|
||||
// Tutorial-videos rail: the official playlist, fetched at boot (cached on
|
||||
|
|
@ -2593,7 +2606,11 @@ pub(super) fn start_page_view<'a>(
|
|||
Space::new().height(iced::Length::Fixed(12.0)),
|
||||
playlist_btn,
|
||||
])
|
||||
.width(iced::Length::Fixed(videos_w))
|
||||
.width(if fits_all {
|
||||
iced::Length::Fixed(videos_w)
|
||||
} else {
|
||||
iced::Length::Fill
|
||||
})
|
||||
.height(Fill)
|
||||
.padding(16)
|
||||
.style(|_: &Theme| container::Style {
|
||||
|
|
@ -2672,7 +2689,11 @@ pub(super) fn start_page_view<'a>(
|
|||
Space::new().height(iced::Length::Fixed(12.0)),
|
||||
support_btn,
|
||||
])
|
||||
.width(iced::Length::Fixed(240.0))
|
||||
.width(if fits_all {
|
||||
iced::Length::Fixed(sup_w)
|
||||
} else {
|
||||
iced::Length::Fill
|
||||
})
|
||||
.height(Fill)
|
||||
.padding(20)
|
||||
.style(|_: &Theme| container::Style {
|
||||
|
|
@ -2804,6 +2825,7 @@ pub(super) fn recent_files_panel<'a>(
|
|||
>,
|
||||
limit: usize,
|
||||
limit_input: &'a str,
|
||||
width: iced::Length,
|
||||
) -> Element<'a, Message> {
|
||||
// Card chrome matches the Supporters rail (the canonical start-page card).
|
||||
const PANEL_BG: Color = Color {
|
||||
|
|
@ -2993,7 +3015,7 @@ pub(super) fn recent_files_panel<'a>(
|
|||
]
|
||||
.width(Fill),
|
||||
)
|
||||
.width(iced::Length::Fixed(280.0))
|
||||
.width(width)
|
||||
.height(Fill)
|
||||
.padding(20)
|
||||
.style(|_: &Theme| container::Style {
|
||||
|
|
@ -3007,4 +3029,3 @@ pub(super) fn recent_files_panel<'a>(
|
|||
})
|
||||
.into()
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue