diff --git a/i18n/en/cosmic_files.ftl b/i18n/en/cosmic_files.ftl index e7579d15..5f22bc15 100644 --- a/i18n/en/cosmic_files.ftl +++ b/i18n/en/cosmic_files.ftl @@ -171,6 +171,8 @@ show-details = Show details settings = Settings settings-tab = Tab settings-show-hidden = Show hidden files +settings-general = General +settings-restore-session = Restore session on start default-view = Default view icon-size-list = Icon size (list) icon-size-grid = Icon size (grid) diff --git a/src/app.rs b/src/app.rs index e47c5fde..c627e69d 100644 --- a/src/app.rs +++ b/src/app.rs @@ -71,7 +71,7 @@ use crate::{ tab::{self, HeadingOptions, ItemMetadata, Location, Tab, HOVER_DURATION}, }; -#[derive(Clone, Debug)] +#[derive(Clone, Copy, Debug, PartialEq)] pub enum Mode { App, Desktop, @@ -297,10 +297,12 @@ pub enum Message { Rename(Option), ReplaceResult(ReplaceResult), RestoreFromTrash(Option), + SaveSession, SearchActivate, SearchClear, SearchInput(String), SearchSubmit, + SessionConfig(crate::config::Session), SystemThemeModeChange(cosmic_theme::ThemeMode), TabActivate(Entity), TabNext, @@ -1127,6 +1129,19 @@ impl App { ) }) .into(), + widget::settings::view_section(fl!("settings-general")) + .add( + widget::settings::item::builder(fl!("settings-restore-session")).toggler( + self.config.session.restore, + move |restore| { + Message::SessionConfig(crate::config::Session { + restore, + ..Default::default() + }) + }, + ), + ) + .into(), ]) .into() } @@ -2134,6 +2149,24 @@ impl Application for App { self.operation(Operation::Restore { paths }); } } + Message::SaveSession => { + if self.config.session.restore && self.mode == Mode::App { + let session = crate::config::Session { + tabs: Some( + self.tab_model + .iter() + .filter_map(|entity| { + self.tab_model + .data::(entity) + .map(|tab| tab.location.clone()) + }) + .collect(), + ), + ..self.config.session + }; + config_set!(session, session); + } + } Message::SearchActivate => { self.search_active = true; return widget::text_input::focus(self.search_id.clone()); @@ -2163,6 +2196,9 @@ impl Application for App { return self.search(); } } + Message::SessionConfig(session) => { + config_set!(session, session); + } Message::SystemThemeModeChange(_theme_mode) => { return self.update_config(); } @@ -2480,6 +2516,7 @@ impl Application for App { if let Some(window_id) = self.window_id_opt.take() { return Command::batch([ window::close(window_id), + Command::perform(async move { message::app(Message::SaveSession) }, |x| x), Command::perform(async move { message::app(Message::MaybeExit) }, |x| x), ]); } diff --git a/src/config.rs b/src/config.rs index e75569b0..a9981b52 100644 --- a/src/config.rs +++ b/src/config.rs @@ -11,7 +11,7 @@ use serde::{Deserialize, Serialize}; use crate::{ app::App, - tab::{HeadingOptions, View}, + tab::{HeadingOptions, Location, View}, }; pub const CONFIG_VERSION: u64 = 1; @@ -97,6 +97,7 @@ pub struct Config { pub app_theme: AppTheme, pub favorites: Vec, pub tab: TabConfig, + pub session: Session, } impl Config { @@ -142,6 +143,7 @@ impl Default for Config { Favorite::Videos, ], tab: TabConfig::default(), + session: Session::default(), } } } @@ -212,3 +214,9 @@ impl IconSizes { percent!(self.grid, ICON_SIZE_GRID) as _ } } + +#[derive(Clone, Debug, Default, PartialEq, Eq, CosmicConfigEntry, Deserialize, Serialize)] +pub struct Session { + pub restore: bool, + pub tabs: Option>, +} diff --git a/src/lib.rs b/src/lib.rs index 37183ca7..df435ccd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -94,22 +94,29 @@ pub fn main() -> Result<(), Box> { localize::localize(); - let (config_handler, config) = Config::load(); + let (config_handler, mut config) = Config::load(); let mut locations = Vec::new(); for arg in env::args().skip(1) { - let location = if &arg == "--trash" { - Location::Trash - } else { - match fs::canonicalize(&arg) { - Ok(absolute) => Location::Path(absolute), + match &*arg { + "--trash" => locations.push(Location::Trash), + // Override session regardless of config + "--no-session" => { + _ = config.session.tabs.take(); + } + path => { + match fs::canonicalize(path) { + Ok(absolute) => locations.push(Location::Path(absolute)), Err(err) => { log::warn!("failed to canonicalize {:?}: {}", arg, err); continue; } } - }; - locations.push(location); + } + } + } + if let Some(session) = config.session.restore.then(|| config.session.tabs.take()).flatten() { + locations.extend(session) } let mut settings = Settings::default(); diff --git a/src/tab.rs b/src/tab.rs index fd78a09d..b2f7276a 100644 --- a/src/tab.rs +++ b/src/tab.rs @@ -771,7 +771,7 @@ pub fn scan_network(uri: &str, mounters: Mounters, sizes: IconSizes) -> Vec