parent
60743ed251
commit
21eac9324f
5 changed files with 58 additions and 105 deletions
79
src/app.rs
79
src/app.rs
|
|
@ -166,9 +166,7 @@ impl Action {
|
|||
Action::OpenTerminal => Message::OpenTerminal(entity_opt),
|
||||
Action::OpenWith => Message::ToggleContextPage(ContextPage::OpenWith),
|
||||
Action::Paste => Message::Paste(entity_opt),
|
||||
Action::Preview => {
|
||||
Message::ToggleContextPage(ContextPage::Preview(entity_opt, PreviewKind::Selected))
|
||||
}
|
||||
Action::Preview => Message::ToggleShowDetails,
|
||||
Action::Rename => Message::Rename(entity_opt),
|
||||
Action::RestoreFromTrash => Message::RestoreFromTrash(entity_opt),
|
||||
Action::SearchActivate => Message::SearchActivate,
|
||||
|
|
@ -288,7 +286,6 @@ pub enum Message {
|
|||
PendingComplete(u64),
|
||||
PendingError(u64, String),
|
||||
PendingProgress(u64, f32),
|
||||
Preview(Entity, PreviewKind, time::Duration),
|
||||
RescanTrash,
|
||||
Rename(Option<Entity>),
|
||||
ReplaceResult(ReplaceResult),
|
||||
|
|
@ -308,6 +305,7 @@ pub enum Message {
|
|||
TabRescan(Entity, Location, Vec<tab::Item>, Option<PathBuf>),
|
||||
TabView(Option<Entity>, tab::View),
|
||||
ToggleContextPage(ContextPage),
|
||||
ToggleShowDetails,
|
||||
ToggleFoldersFirst,
|
||||
Undo(usize),
|
||||
UndoTrash(widget::ToastId, Arc<[PathBuf]>),
|
||||
|
|
@ -473,7 +471,6 @@ pub struct App {
|
|||
pending_operations: BTreeMap<u64, (Operation, f32)>,
|
||||
complete_operations: BTreeMap<u64, Operation>,
|
||||
failed_operations: BTreeMap<u64, (Operation, String)>,
|
||||
preview_opt: Option<(Entity, PreviewKind, time::Instant)>,
|
||||
search_active: bool,
|
||||
search_id: widget::Id,
|
||||
search_input: String,
|
||||
|
|
@ -1063,7 +1060,9 @@ impl Application for App {
|
|||
fn init(mut core: Core, flags: Self::Flags) -> (Self, Command<Self::Message>) {
|
||||
core.window.context_is_overlay = false;
|
||||
match flags.mode {
|
||||
Mode::App => {}
|
||||
Mode::App => {
|
||||
core.window.show_context = flags.config.show_details;
|
||||
}
|
||||
Mode::Desktop => {
|
||||
core.window.content_container = false;
|
||||
core.window.show_window_menu = false;
|
||||
|
|
@ -1086,7 +1085,7 @@ impl Application for App {
|
|||
config: flags.config,
|
||||
mode: flags.mode,
|
||||
app_themes,
|
||||
context_page: ContextPage::Settings,
|
||||
context_page: ContextPage::Preview(None, PreviewKind::Selected),
|
||||
dialog_pages: VecDeque::new(),
|
||||
dialog_text_input: widget::Id::unique(),
|
||||
key_binds: key_binds(),
|
||||
|
|
@ -1101,7 +1100,6 @@ impl Application for App {
|
|||
pending_operations: BTreeMap::new(),
|
||||
complete_operations: BTreeMap::new(),
|
||||
failed_operations: BTreeMap::new(),
|
||||
preview_opt: None,
|
||||
search_active: false,
|
||||
search_id: widget::Id::unique(),
|
||||
search_input: String::new(),
|
||||
|
|
@ -1250,6 +1248,19 @@ impl Application for App {
|
|||
Some(Message::WindowClose)
|
||||
}
|
||||
|
||||
fn on_context_drawer(&mut self) -> Command<Self::Message> {
|
||||
match self.context_page {
|
||||
ContextPage::Preview(_, _) => {
|
||||
// Persist state of preview page
|
||||
if self.core.window.show_context != self.config.show_details {
|
||||
return self.update(Message::ToggleShowDetails);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
Command::none()
|
||||
}
|
||||
|
||||
fn on_escape(&mut self) -> Command<Self::Message> {
|
||||
let entity = self.tab_model.active();
|
||||
|
||||
|
|
@ -1360,8 +1371,10 @@ impl Application for App {
|
|||
Message::Config(config) => {
|
||||
if config != self.config {
|
||||
log::info!("update config");
|
||||
//TODO: update syntax theme by clearing tabs, only if needed
|
||||
// Show details is preserved for existing instances
|
||||
let show_details = self.config.show_details;
|
||||
self.config = config;
|
||||
self.config.show_details = show_details;
|
||||
return self.update_config();
|
||||
}
|
||||
}
|
||||
|
|
@ -1933,17 +1946,6 @@ impl Application for App {
|
|||
}
|
||||
return self.update_notification();
|
||||
}
|
||||
Message::Preview(entity, kind, timeout) => {
|
||||
if self
|
||||
.preview_opt
|
||||
.as_ref()
|
||||
.is_some_and(|(e, k, i)| *e == entity && *k == kind && i.elapsed() > timeout)
|
||||
{
|
||||
self.context_page = ContextPage::Preview(Some(entity), kind);
|
||||
self.set_show_context(true);
|
||||
self.set_context_title(self.context_page.title());
|
||||
}
|
||||
}
|
||||
Message::RescanTrash => {
|
||||
// Update trash icon if empty/full
|
||||
let maybe_entity = self.nav_model.iter().find(|&entity| {
|
||||
|
|
@ -2152,6 +2154,16 @@ impl Application for App {
|
|||
return self.update_config();
|
||||
}
|
||||
}
|
||||
Message::ToggleShowDetails => {
|
||||
let show_details = !self.config.show_details;
|
||||
//TODO: move to update_config?
|
||||
if show_details {
|
||||
self.context_page = ContextPage::Preview(None, PreviewKind::Selected);
|
||||
self.core.window.show_context = true;
|
||||
}
|
||||
config_set!(show_details, show_details);
|
||||
return self.update_config();
|
||||
}
|
||||
Message::ToggleFoldersFirst => {
|
||||
let mut config = self.config.tab;
|
||||
config.folders_first = !config.folders_first;
|
||||
|
|
@ -2273,22 +2285,10 @@ impl Application for App {
|
|||
log::error!("failed to get current executable path: {}", err);
|
||||
}
|
||||
},
|
||||
tab::Command::Preview(kind, mut timeout) => {
|
||||
self.preview_opt = Some((entity, kind.clone(), Instant::now()));
|
||||
if self.core.window.show_context {
|
||||
// If the context window is already open, immediately show the preview
|
||||
timeout = time::Duration::new(0, 0)
|
||||
};
|
||||
commands.push(Command::perform(
|
||||
async move {
|
||||
tokio::time::sleep(timeout).await;
|
||||
message::app(Message::Preview(entity, kind, timeout))
|
||||
},
|
||||
|x| x,
|
||||
));
|
||||
}
|
||||
tab::Command::PreviewCancel => {
|
||||
self.preview_opt = None;
|
||||
tab::Command::Preview(kind) => {
|
||||
self.context_page = ContextPage::Preview(Some(entity), kind);
|
||||
self.set_show_context(true);
|
||||
self.set_context_title(self.context_page.title());
|
||||
}
|
||||
tab::Command::WindowDrag => {
|
||||
commands.push(window::drag(self.main_window_id()));
|
||||
|
|
@ -3182,7 +3182,12 @@ impl Application for App {
|
|||
}
|
||||
|
||||
fn header_start(&self) -> Vec<Element<Self::Message>> {
|
||||
vec![menu::menu_bar(self.tab_model.active_data::<Tab>(), &self.key_binds).into()]
|
||||
vec![menu::menu_bar(
|
||||
self.tab_model.active_data::<Tab>(),
|
||||
&self.config,
|
||||
&self.key_binds,
|
||||
)
|
||||
.into()]
|
||||
}
|
||||
|
||||
fn header_end(&self) -> Vec<Element<Self::Message>> {
|
||||
|
|
|
|||
|
|
@ -9,10 +9,7 @@ use cosmic::{
|
|||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
app::App,
|
||||
tab::{HeadingOptions, View},
|
||||
};
|
||||
use crate::{app::App, tab::View};
|
||||
|
||||
pub const CONFIG_VERSION: u64 = 1;
|
||||
|
||||
|
|
@ -96,6 +93,7 @@ impl Favorite {
|
|||
pub struct Config {
|
||||
pub app_theme: AppTheme,
|
||||
pub favorites: Vec<Favorite>,
|
||||
pub show_details: bool,
|
||||
pub tab: TabConfig,
|
||||
}
|
||||
|
||||
|
|
@ -141,6 +139,7 @@ impl Default for Config {
|
|||
Favorite::Pictures,
|
||||
Favorite::Videos,
|
||||
],
|
||||
show_details: false,
|
||||
tab: TabConfig::default(),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -315,7 +315,6 @@ enum Message {
|
|||
NotifyEvents(Vec<DebouncedEvent>),
|
||||
NotifyWatcher(WatcherWrapper),
|
||||
Open,
|
||||
Preview(PreviewKind, time::Duration),
|
||||
Save(bool),
|
||||
SearchActivate,
|
||||
SearchClear,
|
||||
|
|
@ -378,7 +377,6 @@ struct App {
|
|||
mounters: Mounters,
|
||||
mounter_items: HashMap<MounterKey, MounterItems>,
|
||||
nav_model: segmented_button::SingleSelectModel,
|
||||
preview_opt: Option<(PreviewKind, time::Instant)>,
|
||||
result_opt: Option<DialogResult>,
|
||||
search_active: bool,
|
||||
search_id: widget::Id,
|
||||
|
|
@ -683,6 +681,7 @@ impl Application for App {
|
|||
core.window.show_close = false;
|
||||
core.window.show_maximize = false;
|
||||
core.window.show_minimize = false;
|
||||
core.window.show_context = true;
|
||||
|
||||
let title = flags.kind.title();
|
||||
let accept_label = flags.kind.accept_label();
|
||||
|
|
@ -711,7 +710,7 @@ impl Application for App {
|
|||
title,
|
||||
accept_label,
|
||||
choices: Vec::new(),
|
||||
context_page: ContextPage::Settings,
|
||||
context_page: ContextPage::Preview(None, PreviewKind::Selected),
|
||||
dialog_pages: VecDeque::new(),
|
||||
dialog_text_input: widget::Id::unique(),
|
||||
filters: Vec::new(),
|
||||
|
|
@ -721,7 +720,6 @@ impl Application for App {
|
|||
mounters: mounters(),
|
||||
mounter_items: HashMap::new(),
|
||||
nav_model: segmented_button::ModelBuilder::default().build(),
|
||||
preview_opt: None,
|
||||
result_opt: None,
|
||||
search_active: false,
|
||||
search_id: widget::Id::unique(),
|
||||
|
|
@ -1233,17 +1231,6 @@ impl Application for App {
|
|||
}
|
||||
}
|
||||
}
|
||||
Message::Preview(kind, timeout) => {
|
||||
if self
|
||||
.preview_opt
|
||||
.as_ref()
|
||||
.is_some_and(|(k, i)| *k == kind && i.elapsed() > timeout)
|
||||
{
|
||||
self.context_page = ContextPage::Preview(None, kind);
|
||||
self.set_show_context(true);
|
||||
self.set_context_title(self.context_page.title());
|
||||
}
|
||||
}
|
||||
Message::Save(replace) => {
|
||||
if let DialogKind::SaveFile { filename } = &self.flags.kind {
|
||||
if !filename.is_empty() {
|
||||
|
|
@ -1341,22 +1328,10 @@ impl Application for App {
|
|||
commands.push(self.update(Message::Open));
|
||||
}
|
||||
}
|
||||
tab::Command::Preview(kind, mut timeout) => {
|
||||
self.preview_opt = Some((kind.clone(), time::Instant::now()));
|
||||
if self.core.window.show_context {
|
||||
// If the context window is already open, immediately show the preview
|
||||
timeout = time::Duration::new(0, 0)
|
||||
};
|
||||
commands.push(Command::perform(
|
||||
async move {
|
||||
tokio::time::sleep(timeout).await;
|
||||
message::app(Message::Preview(kind, timeout))
|
||||
},
|
||||
|x| x,
|
||||
));
|
||||
}
|
||||
tab::Command::PreviewCancel => {
|
||||
self.preview_opt = None;
|
||||
tab::Command::Preview(kind) => {
|
||||
self.context_page = ContextPage::Preview(None, kind);
|
||||
self.set_show_context(true);
|
||||
self.set_context_title(self.context_page.title());
|
||||
}
|
||||
tab::Command::WindowDrag => {
|
||||
commands.push(window::drag(self.main_window_id()));
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ use std::collections::HashMap;
|
|||
|
||||
use crate::{
|
||||
app::{Action, Message},
|
||||
config::Config,
|
||||
fl,
|
||||
tab::{self, HeadingOptions, Location, LocationMenuAction, Tab},
|
||||
};
|
||||
|
|
@ -349,6 +350,7 @@ pub fn dialog_menu<'a>(
|
|||
|
||||
pub fn menu_bar<'a>(
|
||||
tab_opt: Option<&Tab>,
|
||||
config: &Config,
|
||||
key_binds: &HashMap<KeyBind, Action>,
|
||||
) -> Element<'a, Message> {
|
||||
let sort_item = |label, sort, dir| {
|
||||
|
|
@ -459,7 +461,7 @@ pub fn menu_bar<'a>(
|
|||
tab_opt.map_or(false, |tab| tab.config.folders_first),
|
||||
Action::ToggleFoldersFirst,
|
||||
),
|
||||
menu::Item::Button(fl!("show-details"), Action::Preview),
|
||||
menu::Item::CheckBox(fl!("show-details"), config.show_details, Action::Preview),
|
||||
menu::Item::Divider,
|
||||
menu_button_optional(fl!("gallery-preview"), Action::Gallery, selected > 0),
|
||||
menu::Item::Divider,
|
||||
|
|
|
|||
36
src/tab.rs
36
src/tab.rs
|
|
@ -821,8 +821,7 @@ pub enum Command {
|
|||
OpenFile(PathBuf),
|
||||
OpenInNewTab(PathBuf),
|
||||
OpenInNewWindow(PathBuf),
|
||||
Preview(PreviewKind, Duration),
|
||||
PreviewCancel,
|
||||
Preview(PreviewKind),
|
||||
WindowDrag,
|
||||
WindowToggleMaximize,
|
||||
}
|
||||
|
|
@ -1750,7 +1749,6 @@ impl Tab {
|
|||
let mut history_i_opt = None;
|
||||
let mod_ctrl = modifiers.contains(Modifiers::CTRL) && self.mode.multiple();
|
||||
let mod_shift = modifiers.contains(Modifiers::SHIFT) && self.mode.multiple();
|
||||
let last_select_focus = self.select_focus;
|
||||
match message {
|
||||
Message::AddNetworkDrive => {
|
||||
commands.push(Command::AddNetworkDrive);
|
||||
|
|
@ -1804,9 +1802,6 @@ impl Tab {
|
|||
} else {
|
||||
log::warn!("no item for click index {:?}", click_i_opt);
|
||||
}
|
||||
|
||||
// Cancel any preview timers
|
||||
commands.push(Command::PreviewCancel);
|
||||
}
|
||||
Message::Click(click_i_opt) => {
|
||||
self.selected_clicked = false;
|
||||
|
|
@ -1988,11 +1983,9 @@ impl Tab {
|
|||
//TODO: blocking code, run in command
|
||||
match item_from_path(&path, IconSizes::default()) {
|
||||
Ok(item) => {
|
||||
// Show preview instantly
|
||||
commands.push(Command::Preview(
|
||||
PreviewKind::Custom(PreviewItem(item)),
|
||||
Duration::new(0, 0),
|
||||
));
|
||||
commands.push(Command::Preview(PreviewKind::Custom(
|
||||
PreviewItem(item),
|
||||
)));
|
||||
}
|
||||
Err(err) => {
|
||||
log::warn!("failed to get item from path {:?}: {}", path, err);
|
||||
|
|
@ -2442,9 +2435,6 @@ impl Tab {
|
|||
|x| x,
|
||||
)));
|
||||
}
|
||||
|
||||
// Clear preview timer
|
||||
commands.push(Command::PreviewCancel);
|
||||
}
|
||||
Message::DndLeave(loc) => {
|
||||
if Some(&loc) == self.dnd_hovered.as_ref().map(|(l, _)| l) {
|
||||
|
|
@ -2459,24 +2449,6 @@ impl Tab {
|
|||
}
|
||||
}
|
||||
|
||||
// Update preview timer
|
||||
//TODO: make this configurable
|
||||
if last_select_focus != self.select_focus {
|
||||
if let Some(index) = self.select_focus {
|
||||
if let Some(ref items) = self.items_opt {
|
||||
if let Some(item) = items.get(index) {
|
||||
if let Some(location) = item.location_opt.clone() {
|
||||
// Show preview after double click timeout
|
||||
commands.push(Command::Preview(
|
||||
PreviewKind::Location(location),
|
||||
DOUBLE_CLICK_DURATION,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Scroll to top if needed
|
||||
if self.scroll_opt.is_none() {
|
||||
let offset = AbsoluteOffset { x: 0.0, y: 0.0 };
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue