Improve initial directory listing latency
Avoid synchronous child counts during item construction, use extension-based MIME detection for initial scans, and defer expensive MIME icon resolution by using generic file icons for ordinary files. Document the local xdg-desktop-portal FileChooser workaround for COSMIC portal crashes.
This commit is contained in:
parent
f0538190d9
commit
338354c4d0
2 changed files with 118 additions and 32 deletions
72
src/tab.rs
72
src/tab.rs
|
|
@ -302,6 +302,26 @@ pub fn folder_icon_symbolic(path: &PathBuf, icon_size: u16) -> widget::icon::Han
|
|||
.handle()
|
||||
}
|
||||
|
||||
fn generic_file_icons(
|
||||
sizes: IconSizes,
|
||||
) -> (
|
||||
widget::icon::Handle,
|
||||
widget::icon::Handle,
|
||||
widget::icon::Handle,
|
||||
) {
|
||||
(
|
||||
widget::icon::from_name("text-x-generic")
|
||||
.size(sizes.grid())
|
||||
.handle(),
|
||||
widget::icon::from_name("text-x-generic")
|
||||
.size(sizes.list())
|
||||
.handle(),
|
||||
widget::icon::from_name("text-x-generic")
|
||||
.size(sizes.list_condensed())
|
||||
.handle(),
|
||||
)
|
||||
}
|
||||
|
||||
//TODO: replace with Path::has_trailing_sep when stable
|
||||
fn has_trailing_sep(path: &Path) -> bool {
|
||||
path.as_os_str()
|
||||
|
|
@ -665,9 +685,9 @@ pub fn item_from_gvfs_info(path: PathBuf, file_info: gio::FileInfo, sizes: IconS
|
|||
folder_icon(&path, sizes.list_condensed()),
|
||||
)
|
||||
} else {
|
||||
// ALWAYS assume we're remote for mime guessing here, since gvfs reading can be expensive
|
||||
// @todo - expose this as a config option?
|
||||
let mime = mime_for_path(&path, None, true);
|
||||
// Keep the initial directory scan cheap. Opening files still
|
||||
// recalculates MIME from the real path before launching apps.
|
||||
let mime = mime_guess::from_path(&path).first_or_octet_stream();
|
||||
|
||||
//TODO: clean this up, implement for trash
|
||||
let icon_name_opt = if mime == "application/x-desktop" {
|
||||
|
|
@ -684,28 +704,21 @@ pub fn item_from_gvfs_info(path: PathBuf, file_info: gio::FileInfo, sizes: IconS
|
|||
desktop_icon_handle(&icon_name, sizes.list_condensed()),
|
||||
)
|
||||
} else {
|
||||
let (icon_handle_grid, icon_handle_list, icon_handle_list_condensed) =
|
||||
generic_file_icons(sizes);
|
||||
(
|
||||
mime.clone(),
|
||||
mime_icon(mime.clone(), sizes.grid()),
|
||||
mime_icon(mime.clone(), sizes.list()),
|
||||
mime_icon(mime, sizes.list_condensed()),
|
||||
mime,
|
||||
icon_handle_grid,
|
||||
icon_handle_list,
|
||||
icon_handle_list_condensed,
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
let mut children_opt = None;
|
||||
let children_opt = None;
|
||||
let mut dir_size = DirSize::NotDirectory;
|
||||
if is_dir && !remote {
|
||||
dir_size = DirSize::Calculating(Controller::default());
|
||||
//TODO: calculate children in the background (and make it cancellable?)
|
||||
match fs::read_dir(&path) {
|
||||
Ok(entries) => {
|
||||
children_opt = Some(entries.count());
|
||||
}
|
||||
Err(err) => {
|
||||
log::warn!("failed to read directory {}: {}", path.display(), err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let display_name = display_name_for_file(&path, &file_info.display_name(), false, is_desktop);
|
||||
|
|
@ -807,7 +820,9 @@ pub fn item_from_entry(
|
|||
folder_icon(&path, sizes.list_condensed()),
|
||||
)
|
||||
} else {
|
||||
let mime = mime_for_path(&path, Some(&metadata), remote);
|
||||
// Keep the initial directory scan cheap. Opening files still
|
||||
// recalculates MIME from the real path before launching apps.
|
||||
let mime = mime_guess::from_path(&path).first_or_octet_stream();
|
||||
//TODO: clean this up, implement for trash
|
||||
let icon_name_opt = if mime == "application/x-desktop" {
|
||||
is_desktop = true;
|
||||
|
|
@ -823,28 +838,21 @@ pub fn item_from_entry(
|
|||
desktop_icon_handle(&icon_name, sizes.list_condensed()),
|
||||
)
|
||||
} else {
|
||||
let (icon_handle_grid, icon_handle_list, icon_handle_list_condensed) =
|
||||
generic_file_icons(sizes);
|
||||
(
|
||||
mime.clone(),
|
||||
mime_icon(mime.clone(), sizes.grid()),
|
||||
mime_icon(mime.clone(), sizes.list()),
|
||||
mime_icon(mime, sizes.list_condensed()),
|
||||
mime,
|
||||
icon_handle_grid,
|
||||
icon_handle_list,
|
||||
icon_handle_list_condensed,
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
let mut children_opt = None;
|
||||
let children_opt = None;
|
||||
let mut dir_size = DirSize::NotDirectory;
|
||||
if metadata.is_dir() && !remote {
|
||||
dir_size = DirSize::Calculating(Controller::default());
|
||||
//TODO: calculate children in the background (and make it cancellable?)
|
||||
match fs::read_dir(&path) {
|
||||
Ok(entries) => {
|
||||
children_opt = Some(entries.count());
|
||||
}
|
||||
Err(err) => {
|
||||
log::warn!("failed to read directory {}: {}", path.display(), err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let display_name = display_name_for_file(&path, &name, is_gvfs, is_desktop);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue