Restore tab scroll position, fixes #1115
This commit is contained in:
parent
5e0645d1c2
commit
fb74be9a70
4 changed files with 43 additions and 17 deletions
46
src/app.rs
46
src/app.rs
|
|
@ -26,6 +26,7 @@ use cosmic::{
|
||||||
futures::{self, SinkExt},
|
futures::{self, SinkExt},
|
||||||
keyboard::{Event as KeyEvent, Key, Modifiers},
|
keyboard::{Event as KeyEvent, Key, Modifiers},
|
||||||
stream,
|
stream,
|
||||||
|
widget::scrollable,
|
||||||
window::{self, Event as WindowEvent, Id as WindowId},
|
window::{self, Event as WindowEvent, Id as WindowId},
|
||||||
Alignment, Event, Length, Point, Rectangle, Size, Subscription,
|
Alignment, Event, Length, Point, Rectangle, Size, Subscription,
|
||||||
},
|
},
|
||||||
|
|
@ -664,6 +665,7 @@ pub struct App {
|
||||||
progress_operations: BTreeSet<u64>,
|
progress_operations: BTreeSet<u64>,
|
||||||
complete_operations: BTreeMap<u64, Operation>,
|
complete_operations: BTreeMap<u64, Operation>,
|
||||||
failed_operations: BTreeMap<u64, (Operation, Controller, String)>,
|
failed_operations: BTreeMap<u64, (Operation, Controller, String)>,
|
||||||
|
scrollable_id: widget::Id,
|
||||||
search_id: widget::Id,
|
search_id: widget::Id,
|
||||||
size: Option<Size>,
|
size: Option<Size>,
|
||||||
#[cfg(all(feature = "wayland", feature = "desktop-applet"))]
|
#[cfg(all(feature = "wayland", feature = "desktop-applet"))]
|
||||||
|
|
@ -959,6 +961,7 @@ impl App {
|
||||||
location: Location,
|
location: Location,
|
||||||
activate: bool,
|
activate: bool,
|
||||||
selection_paths: Option<Vec<PathBuf>>,
|
selection_paths: Option<Vec<PathBuf>>,
|
||||||
|
scrollable_id: widget::Id,
|
||||||
window_id: Option<window::Id>,
|
window_id: Option<window::Id>,
|
||||||
) -> (Entity, Task<Message>) {
|
) -> (Entity, Task<Message>) {
|
||||||
#[cfg(feature = "gvfs")]
|
#[cfg(feature = "gvfs")]
|
||||||
|
|
@ -1002,6 +1005,7 @@ impl App {
|
||||||
self.config.tab,
|
self.config.tab,
|
||||||
self.config.thumb_cfg,
|
self.config.thumb_cfg,
|
||||||
Some(&self.state.sort_names),
|
Some(&self.state.sort_names),
|
||||||
|
scrollable_id,
|
||||||
window_id,
|
window_id,
|
||||||
);
|
);
|
||||||
tab.mode = match self.mode {
|
tab.mode = match self.mode {
|
||||||
|
|
@ -1041,8 +1045,14 @@ impl App {
|
||||||
activate: bool,
|
activate: bool,
|
||||||
selection_paths: Option<Vec<PathBuf>>,
|
selection_paths: Option<Vec<PathBuf>>,
|
||||||
) -> Task<Message> {
|
) -> Task<Message> {
|
||||||
self.open_tab_entity(location, activate, selection_paths, None)
|
self.open_tab_entity(
|
||||||
.1
|
location,
|
||||||
|
activate,
|
||||||
|
selection_paths,
|
||||||
|
self.scrollable_id.clone(),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.1
|
||||||
}
|
}
|
||||||
|
|
||||||
// This wrapper ensures that local folders use trash and remote folders permanently delete with a dialog
|
// This wrapper ensures that local folders use trash and remote folders permanently delete with a dialog
|
||||||
|
|
@ -2144,6 +2154,7 @@ impl Application for App {
|
||||||
progress_operations: BTreeSet::new(),
|
progress_operations: BTreeSet::new(),
|
||||||
complete_operations: BTreeMap::new(),
|
complete_operations: BTreeMap::new(),
|
||||||
failed_operations: BTreeMap::new(),
|
failed_operations: BTreeMap::new(),
|
||||||
|
scrollable_id: widget::Id::unique(),
|
||||||
search_id: widget::Id::unique(),
|
search_id: widget::Id::unique(),
|
||||||
size: None,
|
size: None,
|
||||||
#[cfg(all(feature = "wayland", feature = "desktop-applet"))]
|
#[cfg(all(feature = "wayland", feature = "desktop-applet"))]
|
||||||
|
|
@ -3742,6 +3753,12 @@ impl Application for App {
|
||||||
// Activate new tab
|
// Activate new tab
|
||||||
self.tab_model.activate(entity);
|
self.tab_model.activate(entity);
|
||||||
if let Some(tab) = self.tab_model.data::<Tab>(entity) {
|
if let Some(tab) = self.tab_model.data::<Tab>(entity) {
|
||||||
|
{
|
||||||
|
//Restore scroll
|
||||||
|
//TODO: why do scrollers with different IDs get the same scroll position?
|
||||||
|
let scroll = tab.scroll_opt.unwrap_or_default();
|
||||||
|
tasks.push(scrollable::scroll_to(tab.scrollable_id.clone(), scroll));
|
||||||
|
}
|
||||||
self.activate_nav_model_location(&tab.location.clone());
|
self.activate_nav_model_location(&tab.location.clone());
|
||||||
}
|
}
|
||||||
tasks.push(self.update_title());
|
tasks.push(self.update_title());
|
||||||
|
|
@ -3781,6 +3798,8 @@ impl Application for App {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Message::TabClose(entity_opt) => {
|
Message::TabClose(entity_opt) => {
|
||||||
|
let mut tasks = Vec::with_capacity(3);
|
||||||
|
|
||||||
let entity = entity_opt.unwrap_or_else(|| self.tab_model.active());
|
let entity = entity_opt.unwrap_or_else(|| self.tab_model.active());
|
||||||
|
|
||||||
// Activate closest item
|
// Activate closest item
|
||||||
|
|
@ -3791,12 +3810,8 @@ impl Application for App {
|
||||||
position + 1
|
position + 1
|
||||||
};
|
};
|
||||||
|
|
||||||
if self.tab_model.activate_position(new_position) {
|
if let Some(new_entity) = self.tab_model.entity_at(new_position) {
|
||||||
if let Some(new_entity) = self.tab_model.entity_at(new_position) {
|
tasks.push(self.update(Message::TabActivate(new_entity)));
|
||||||
if let Some(tab) = self.tab_model.data::<Tab>(new_entity) {
|
|
||||||
self.activate_nav_model_location(&tab.location.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3806,11 +3821,13 @@ impl Application for App {
|
||||||
// If that was the last tab, close window
|
// If that was the last tab, close window
|
||||||
if self.tab_model.iter().next().is_none() {
|
if self.tab_model.iter().next().is_none() {
|
||||||
if let Some(window_id) = self.core.main_window_id() {
|
if let Some(window_id) = self.core.main_window_id() {
|
||||||
return window::close(window_id);
|
tasks.push(window::close(window_id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Task::batch([self.update_title(), self.update_watcher()]);
|
tasks.push(self.update_watcher());
|
||||||
|
|
||||||
|
return Task::batch(tasks);
|
||||||
}
|
}
|
||||||
Message::TabConfig(config) => {
|
Message::TabConfig(config) => {
|
||||||
if config != self.config.tab {
|
if config != self.config.tab {
|
||||||
|
|
@ -4567,6 +4584,7 @@ impl Application for App {
|
||||||
Location::Desktop(crate::desktop_dir(), display, self.config.desktop),
|
Location::Desktop(crate::desktop_dir(), display, self.config.desktop),
|
||||||
false,
|
false,
|
||||||
None,
|
None,
|
||||||
|
widget::Id::unique(),
|
||||||
Some(surface_id),
|
Some(surface_id),
|
||||||
);
|
);
|
||||||
self.windows.insert(surface_id, WindowKind::Desktop(entity));
|
self.windows.insert(surface_id, WindowKind::Desktop(entity));
|
||||||
|
|
@ -6378,7 +6396,13 @@ pub(crate) mod test_utils {
|
||||||
// New tab with items
|
// New tab with items
|
||||||
let location = Location::Path(path.to_owned());
|
let location = Location::Path(path.to_owned());
|
||||||
let (parent_item_opt, items) = location.scan(IconSizes::default());
|
let (parent_item_opt, items) = location.scan(IconSizes::default());
|
||||||
let mut tab = Tab::new(location, TabConfig::default(), ThumbCfg::default(), None);
|
let mut tab = Tab::new(
|
||||||
|
location,
|
||||||
|
TabConfig::default(),
|
||||||
|
ThumbCfg::default(),
|
||||||
|
widget::Id::unique(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
tab.parent_item_opt = parent_item_opt;
|
tab.parent_item_opt = parent_item_opt;
|
||||||
tab.set_items(items);
|
tab.set_items(items);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ use std::{
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
app::{Action, ContextPage, Message as AppMessage, PreviewItem, PreviewKind},
|
app::{Action, ContextPage, Message as AppMessage, PreviewItem, PreviewKind},
|
||||||
config::{Config, DialogConfig, Favorite, TabConfig, ThumbCfg, TimeConfig, TIME_CONFIG_ID},
|
config::{Config, DialogConfig, Favorite, ThumbCfg, TimeConfig, TIME_CONFIG_ID},
|
||||||
fl, home_dir,
|
fl, home_dir,
|
||||||
key_bind::key_binds,
|
key_bind::key_binds,
|
||||||
localize::LANGUAGE_SORTER,
|
localize::LANGUAGE_SORTER,
|
||||||
|
|
@ -950,6 +950,7 @@ impl Application for App {
|
||||||
flags.config.dialog_tab(),
|
flags.config.dialog_tab(),
|
||||||
ThumbCfg::default(),
|
ThumbCfg::default(),
|
||||||
None,
|
None,
|
||||||
|
widget::Id::unique(),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
tab.mode = tab::Mode::Dialog(flags.kind.clone());
|
tab.mode = tab::Mode::Dialog(flags.kind.clone());
|
||||||
|
|
|
||||||
|
|
@ -524,7 +524,7 @@ fn update<Message: Clone>(
|
||||||
viewport: &Rectangle,
|
viewport: &Rectangle,
|
||||||
) -> event::Status {
|
) -> event::Status {
|
||||||
let offset = layout.virtual_offset();
|
let offset = layout.virtual_offset();
|
||||||
let mut layout_bounds = layout.bounds();
|
let layout_bounds = layout.bounds();
|
||||||
|
|
||||||
if let Some(message) = widget.on_resize.as_ref() {
|
if let Some(message) = widget.on_resize.as_ref() {
|
||||||
if state.viewport != Some(*viewport) {
|
if state.viewport != Some(*viewport) {
|
||||||
|
|
|
||||||
|
|
@ -2455,7 +2455,7 @@ pub struct Tab {
|
||||||
pub(crate) parent_item_opt: Option<Item>,
|
pub(crate) parent_item_opt: Option<Item>,
|
||||||
pub(crate) items_opt: Option<Vec<Item>>,
|
pub(crate) items_opt: Option<Vec<Item>>,
|
||||||
pub dnd_hovered: Option<(Location, Instant)>,
|
pub dnd_hovered: Option<(Location, Instant)>,
|
||||||
scrollable_id: widget::Id,
|
pub(crate) scrollable_id: widget::Id,
|
||||||
select_focus: Option<usize>,
|
select_focus: Option<usize>,
|
||||||
select_range: Option<(usize, usize)>,
|
select_range: Option<(usize, usize)>,
|
||||||
clicked: Option<usize>,
|
clicked: Option<usize>,
|
||||||
|
|
@ -2535,6 +2535,7 @@ impl Tab {
|
||||||
config: TabConfig,
|
config: TabConfig,
|
||||||
thumb_config: ThumbCfg,
|
thumb_config: ThumbCfg,
|
||||||
sorting_options: Option<&OrderMap<String, (HeadingOptions, bool)>>,
|
sorting_options: Option<&OrderMap<String, (HeadingOptions, bool)>>,
|
||||||
|
scrollable_id: widget::Id,
|
||||||
window_id: Option<window::Id>,
|
window_id: Option<window::Id>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let location_str = location.to_string();
|
let location_str = location.to_string();
|
||||||
|
|
@ -2570,7 +2571,7 @@ impl Tab {
|
||||||
gallery: false,
|
gallery: false,
|
||||||
parent_item_opt: None,
|
parent_item_opt: None,
|
||||||
items_opt: None,
|
items_opt: None,
|
||||||
scrollable_id: widget::Id::unique(),
|
scrollable_id,
|
||||||
select_focus: None,
|
select_focus: None,
|
||||||
select_range: None,
|
select_range: None,
|
||||||
clicked: None,
|
clicked: None,
|
||||||
|
|
@ -3589,7 +3590,7 @@ impl Tab {
|
||||||
Some(selected_paths),
|
Some(selected_paths),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
Message::RightClick(p, click_i_opt) => {
|
Message::RightClick(_point_opt, click_i_opt) => {
|
||||||
if mod_ctrl || mod_shift {
|
if mod_ctrl || mod_shift {
|
||||||
self.update(Message::Click(click_i_opt), modifiers);
|
self.update(Message::Click(click_i_opt), modifiers);
|
||||||
}
|
}
|
||||||
|
|
@ -5529,7 +5530,7 @@ impl Tab {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Location::Network(uri, _display_name, path) if uri == "network:///" => {
|
Location::Network(uri, _display_name, _path) if uri == "network:///" => {
|
||||||
tab_column = tab_column.push(
|
tab_column = tab_column.push(
|
||||||
widget::layer_container(widget::row::with_children(vec![
|
widget::layer_container(widget::row::with_children(vec![
|
||||||
widget::horizontal_space().into(),
|
widget::horizontal_space().into(),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue