Skip to content

Commit

Permalink
Optionally restore last session on start
Browse files Browse the repository at this point in the history
Closes: #534

This patch adds a config option to restore closed sessions on start. So,
if a user had three tabs opened, all three tabs would be restored when
Files is launched again.
  • Loading branch information
joshuamegnauth54 committed Oct 7, 2024
1 parent e997bbb commit 4f537ea
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 36 deletions.
4 changes: 4 additions & 0 deletions i18n/en/cosmic_files.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,10 @@ match-desktop = Match desktop
dark = Dark
light = Light
### Session
session = Session
restore-session = Restore previous session on start
# Context menu
add-to-sidebar = Add to sidebar
compress = Compress
Expand Down
93 changes: 68 additions & 25 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ use wayland_client::{protocol::wl_output::WlOutput, Proxy};

use crate::{
clipboard::{ClipboardCopy, ClipboardKind, ClipboardPaste},
config::{AppTheme, Config, DesktopConfig, Favorite, IconSizes, TabConfig},
config::{AppTheme, Config, DesktopConfig, Favorite, IconSizes, SessionConfig, TabConfig},
desktop_dir, fl, home_dir,
key_bind::key_binds,
localize::LANGUAGE_SORTER,
Expand All @@ -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,
Expand Down Expand Up @@ -305,10 +305,12 @@ pub enum Message {
Rename(Option<Entity>),
ReplaceResult(ReplaceResult),
RestoreFromTrash(Option<Entity>),
SaveSession,
SearchActivate,
SearchClear,
SearchInput(String),
SearchSubmit,
SessionConfig(SessionConfig),
SystemThemeModeChange(cosmic_theme::ThemeMode),
TabActivate(Entity),
TabNext,
Expand Down Expand Up @@ -1140,27 +1142,43 @@ impl App {

fn settings(&self) -> Element<Message> {
// TODO: Should dialog be updated here too?
widget::settings::view_column(vec![widget::settings::section()
.title(fl!("appearance"))
.add({
let app_theme_selected = match self.config.app_theme {
AppTheme::Dark => 1,
AppTheme::Light => 2,
AppTheme::System => 0,
};
widget::settings::item::builder(fl!("theme")).control(widget::dropdown(
&self.app_themes,
Some(app_theme_selected),
move |index| {
Message::AppTheme(match index {
1 => AppTheme::Dark,
2 => AppTheme::Light,
_ => AppTheme::System,
})
},
))
})
.into()])
widget::settings::view_column(vec![
widget::settings::section()
.title(fl!("appearance"))
.add({
let app_theme_selected = match self.config.app_theme {
AppTheme::Dark => 1,
AppTheme::Light => 2,
AppTheme::System => 0,
};
widget::settings::item::builder(fl!("theme")).control(widget::dropdown(
&self.app_themes,
Some(app_theme_selected),
move |index| {
Message::AppTheme(match index {
1 => AppTheme::Dark,
2 => AppTheme::Light,
_ => AppTheme::System,
})
},
))
})
.into(),
widget::settings::section()
.title(fl!("session"))
.add(
widget::settings::item::builder(fl!("restore-session")).toggler(
self.config.session.restore,
move |restore| {
Message::SessionConfig(SessionConfig {
restore,
..Default::default()
})
},
),
)
.into(),
])
.into()
}
}
Expand Down Expand Up @@ -2326,6 +2344,24 @@ impl Application for App {
self.operation(Operation::Restore { paths });
}
}
Message::SaveSession => {
if self.config.session.restore && self.mode == Mode::App {
let session = SessionConfig {
tabs: Some(
self.tab_model
.iter()
.filter_map(|entity| {
self.tab_model
.data::<Tab>(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());
Expand Down Expand Up @@ -2355,6 +2391,9 @@ impl Application for App {
return self.search();
}
}
Message::SessionConfig(session) => {
config_set!(session, session);
}
Message::SystemThemeModeChange(_theme_mode) => {
return self.update_config();
}
Expand Down Expand Up @@ -2429,9 +2468,12 @@ impl Application for App {
// Remove item
self.tab_model.remove(entity);

// If that was the last tab, close window
// If that was the last tab, close window and serialize empty session if necessary
if self.tab_model.iter().next().is_none() {
return window::close(window::Id::MAIN);
return Command::batch([
self.update(Message::SaveSession),
window::close(window::Id::MAIN),
]);
}

return Command::batch([self.update_title(), self.update_watcher()]);
Expand Down Expand Up @@ -2695,6 +2737,7 @@ impl Application for App {
if let Some(window_id) = self.window_id_opt.take() {
return Command::batch([
window::close(window_id),
self.update(Message::SaveSession),
Command::perform(async move { message::app(Message::MaybeExit) }, |x| x),
]);
}
Expand Down
13 changes: 12 additions & 1 deletion src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ use cosmic::{
};
use serde::{Deserialize, Serialize};

use crate::{app::App, tab::View};
use crate::{
app::App,
tab::{Location, View},
};

pub const CONFIG_VERSION: u64 = 1;

Expand Down Expand Up @@ -97,6 +100,7 @@ pub struct Config {
pub favorites: Vec<Favorite>,
pub show_details: bool,
pub tab: TabConfig,
pub session: SessionConfig,
}

impl Config {
Expand Down Expand Up @@ -144,6 +148,7 @@ impl Default for Config {
],
show_details: false,
tab: TabConfig::default(),
session: SessionConfig::default(),
}
}
}
Expand Down Expand Up @@ -229,3 +234,9 @@ impl IconSizes {
percent!(self.grid, ICON_SIZE_GRID) as _
}
}

#[derive(Clone, Debug, Default, PartialEq, Eq, CosmicConfigEntry, Deserialize, Serialize)]
pub struct SessionConfig {
pub restore: bool,
pub tabs: Option<Vec<Location>>,
}
21 changes: 12 additions & 9 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,22 +96,25 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {

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();
Expand Down
2 changes: 1 addition & 1 deletion src/tab.rs
Original file line number Diff line number Diff line change
Expand Up @@ -885,7 +885,7 @@ pub fn scan_desktop(
items
}

#[derive(Clone, Debug, Eq, PartialEq)]
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
pub enum Location {
Desktop(PathBuf, String),
Network(String, String),
Expand Down

0 comments on commit 4f537ea

Please sign in to comment.