Merge branch 'master' into type-to-select

This commit is contained in:
Levi Portenier 2025-12-30 12:44:20 -07:00 committed by GitHub
commit 03ec21bdc9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 874 additions and 467 deletions

View file

@ -4179,10 +4179,19 @@ impl Application for App {
tab.sort_name = sort.0;
tab.sort_direction = sort.1;
let mut tasks = Vec::with_capacity(2);
if let Some(selection_paths) = selection_paths {
tab.select_paths(selection_paths);
// Ensure selected path is scrolled to after redraw
tasks.push(Task::done(cosmic::action::app(Message::TabMessage(
Some(entity),
tab::Message::ScrollToFocused,
))));
}
return clipboard::read_data::<ClipboardPaste>().map(|p| {
tasks.push(clipboard::read_data::<ClipboardPaste>().map(|p| {
cosmic::action::app(Message::CutPaths(match p {
Some(s) => match s.kind {
ClipboardKind::Copy => Vec::new(),
@ -4190,7 +4199,9 @@ impl Application for App {
},
None => Vec::new(),
}))
});
}));
return Task::batch(tasks);
}
}
}
@ -5615,7 +5626,7 @@ impl Application for App {
}
let finished = count - running;
total_progress /= count as f32;
if running > 1 || finished > 0 {
if running >= 1 && (running > 1 || finished > 0) {
if finished > 0 {
title = fl!(
"operations-running-finished",

View file

@ -50,6 +50,8 @@ fn gio_icon_to_path(icon: &gio::Icon, size: u16) -> Option<PathBuf> {
fn items(monitor: &gio::VolumeMonitor, sizes: IconSizes) -> MounterItems {
let mut items: MounterItems = (monitor.mounts().into_iter())
.enumerate()
// Hide shadowed mounts
.filter(|(_, mount)| !mount.is_shadowed())
.map(|(i, mount)| {
let root = MountExt::root(&mount);
let is_remote = root

View file

@ -527,14 +527,24 @@ fn update<Message: Clone>(
let offset = layout.virtual_offset();
let layout_bounds = layout.bounds();
let viewport_changed = state.viewport.map_or(true, |v| v != *viewport);
if let Some(message) = widget.on_resize.as_ref() {
if state.viewport != Some(*viewport) {
state.viewport = Some(*viewport);
if viewport_changed {
shell.publish(message(*viewport));
}
}
if let Event::Mouse(mouse::Event::CursorMoved { position }) = event {
state.viewport = Some(*viewport);
let should_check_hover = viewport_changed
|| matches!(
event,
Event::Mouse(mouse::Event::CursorMoved { .. })
| Event::Mouse(mouse::Event::WheelScrolled { .. })
);
if should_check_hover {
let position_in = cursor.position_in(layout_bounds);
match (position_in, state.last_position) {
(None, Some(_)) => {
@ -550,7 +560,9 @@ fn update<Message: Clone>(
_ => {}
}
state.last_position = position_in;
}
if let Event::Mouse(mouse::Event::CursorMoved { position }) = event {
let virtual_position = Point::new(
viewport.x - layout_bounds.x + position.x,
viewport.y - layout_bounds.y + position.y,

View file

@ -631,6 +631,17 @@ fn get_desktop_file_icon(path: &Path) -> Option<String> {
.map(str::to_string)
}
/// Creates an icon handle from a desktop file's Icon field value.
/// Supports both icon names (looked up in theme) and absolute paths (used directly).
fn desktop_icon_handle(icon: &str, size: u16) -> widget::icon::Handle {
let icon_path = Path::new(icon);
if icon_path.is_absolute() && icon_path.exists() {
widget::icon::from_path(icon_path.to_path_buf())
} else {
widget::icon::from_name(icon).size(size).handle()
}
}
pub fn parse_desktop_file(path: &Path) -> (Option<String>, Option<String>) {
let entry = match freedesktop_entry_parser::parse_entry(path) {
Ok(ok) => ok,
@ -694,15 +705,9 @@ pub fn item_from_gvfs_info(path: PathBuf, file_info: gio::FileInfo, sizes: IconS
if let Some(icon_name) = icon_name_opt {
(
mime,
widget::icon::from_name(&*icon_name)
.size(sizes.grid())
.handle(),
widget::icon::from_name(&*icon_name)
.size(sizes.list())
.handle(),
widget::icon::from_name(&*icon_name)
.size(sizes.list_condensed())
.handle(),
desktop_icon_handle(&icon_name, sizes.grid()),
desktop_icon_handle(&icon_name, sizes.list()),
desktop_icon_handle(&icon_name, sizes.list_condensed()),
)
} else {
(
@ -829,15 +834,9 @@ pub fn item_from_entry(
if let Some(icon_name) = icon_name_opt {
(
mime,
widget::icon::from_name(&*icon_name)
.size(sizes.grid())
.handle(),
widget::icon::from_name(&*icon_name)
.size(sizes.list())
.handle(),
widget::icon::from_name(icon_name)
.size(sizes.list_condensed())
.handle(),
desktop_icon_handle(&icon_name, sizes.grid()),
desktop_icon_handle(&icon_name, sizes.list()),
desktop_icon_handle(&icon_name, sizes.list_condensed()),
)
} else {
(
@ -1666,6 +1665,7 @@ pub enum Message {
Resize(Rectangle),
Scroll(Viewport),
ScrollTab(f32),
ScrollToFocused,
SearchContext(Location, SearchContextWrapper),
SearchReady(bool),
SelectAll,
@ -3906,6 +3906,13 @@ impl Tab {
.into(),
));
}
Message::ScrollToFocused => {
if let Some(offset) = self.select_focus_scroll() {
commands.push(Command::Iced(
scrollable::scroll_to(self.scrollable_id.clone(), offset).into(),
));
}
}
Message::SearchContext(location, context) => {
if location == self.location {
self.search_context = context.0;