fix(mime_app): unalias mime types when associating apps
Fixes associations for `.iso`, where many apps define `application/x-cd-image` instead of `application/vnd.efi.iso`. Popsicle and GNOME Disks will now appear as exact matches for opening `.iso` files with this change.
This commit is contained in:
parent
9a3eb1cdea
commit
7d3487da7b
2 changed files with 48 additions and 18 deletions
|
|
@ -321,6 +321,7 @@ impl MimeAppCache {
|
||||||
#[cfg(feature = "desktop")]
|
#[cfg(feature = "desktop")]
|
||||||
pub fn reload(&mut self) {
|
pub fn reload(&mut self) {
|
||||||
use crate::localize::LANGUAGE_SORTER;
|
use crate::localize::LANGUAGE_SORTER;
|
||||||
|
use crate::mime_icon;
|
||||||
use cosmic::desktop::fde;
|
use cosmic::desktop::fde;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
|
|
@ -334,8 +335,10 @@ impl MimeAppCache {
|
||||||
let paths = cosmic_mime_apps::list_paths();
|
let paths = cosmic_mime_apps::list_paths();
|
||||||
list.load_from_paths(&paths);
|
list.load_from_paths(&paths);
|
||||||
let locales = fde::get_languages_from_env();
|
let locales = fde::get_languages_from_env();
|
||||||
|
|
||||||
let desktop_entries = fde::Iter::new(fde::default_paths()).entries(Some(&locales));
|
let desktop_entries = fde::Iter::new(fde::default_paths()).entries(Some(&locales));
|
||||||
|
let mime_icon_cache = mime_icon::MIME_ICON_CACHE.lock().unwrap();
|
||||||
|
let shared_mime_info = &mime_icon_cache.shared_mime_info;
|
||||||
|
let mut aliased_mimes = FxHashMap::default();
|
||||||
|
|
||||||
for desktop_entry in desktop_entries {
|
for desktop_entry in desktop_entries {
|
||||||
let name = desktop_entry
|
let name = desktop_entry
|
||||||
|
|
@ -368,7 +371,18 @@ impl MimeAppCache {
|
||||||
|
|
||||||
// Cache associations defined by the desktop entry.
|
// Cache associations defined by the desktop entry.
|
||||||
let mime_types = desktop_entry.mime_type().unwrap_or_else(Vec::new);
|
let mime_types = desktop_entry.mime_type().unwrap_or_else(Vec::new);
|
||||||
for mime in mime_types.iter().filter_map(|m| m.parse::<Mime>().ok()) {
|
let associated_mime_types = mime_types.iter().filter_map(|m| {
|
||||||
|
m.parse::<Mime>().ok().map(|mime| {
|
||||||
|
if let Some(unaliased) = shared_mime_info.unalias_mime_type(&mime) {
|
||||||
|
aliased_mimes.insert(unaliased.clone(), mime);
|
||||||
|
return unaliased;
|
||||||
|
}
|
||||||
|
|
||||||
|
mime
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
for mime in associated_mime_types {
|
||||||
let apps = self.cache.entry(mime.clone()).or_default();
|
let apps = self.cache.entry(mime.clone()).or_default();
|
||||||
if apps.iter().all(|cached_app| cached_app.id != app.id) {
|
if apps.iter().all(|cached_app| cached_app.id != app.id) {
|
||||||
apps.push(app.clone());
|
apps.push(app.clone());
|
||||||
|
|
@ -377,7 +391,14 @@ impl MimeAppCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cache added associations from mimeapps lists.
|
// Cache added associations from mimeapps lists.
|
||||||
for (added_mime, added_apps) in &list.added_associations {
|
for (mut added_mime, added_apps) in &list.added_associations {
|
||||||
|
let _unaliased;
|
||||||
|
if let Some(unaliased) = shared_mime_info.unalias_mime_type(added_mime) {
|
||||||
|
aliased_mimes.insert(unaliased.clone(), added_mime.clone());
|
||||||
|
_unaliased = unaliased;
|
||||||
|
added_mime = &_unaliased;
|
||||||
|
}
|
||||||
|
|
||||||
for added_app in added_apps {
|
for added_app in added_apps {
|
||||||
if let Some(app) = self
|
if let Some(app) = self
|
||||||
.apps
|
.apps
|
||||||
|
|
@ -393,7 +414,14 @@ impl MimeAppCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove associations
|
// Remove associations
|
||||||
for (removed_mime, removed_apps) in &list.removed_associations {
|
for (mut removed_mime, removed_apps) in &list.removed_associations {
|
||||||
|
let _unaliased;
|
||||||
|
if let Some(unaliased) = shared_mime_info.unalias_mime_type(removed_mime) {
|
||||||
|
aliased_mimes.insert(unaliased.clone(), removed_mime.clone());
|
||||||
|
_unaliased = unaliased;
|
||||||
|
removed_mime = &_unaliased;
|
||||||
|
}
|
||||||
|
|
||||||
for removed_app in removed_apps {
|
for removed_app in removed_apps {
|
||||||
if let Some(app) = self
|
if let Some(app) = self
|
||||||
.apps
|
.apps
|
||||||
|
|
@ -409,13 +437,21 @@ impl MimeAppCache {
|
||||||
// Fetch defaults and sort apps by their default precedence.
|
// Fetch defaults and sort apps by their default precedence.
|
||||||
for (mime, mut apps) in std::mem::take(&mut self.cache).into_iter() {
|
for (mime, mut apps) in std::mem::take(&mut self.cache).into_iter() {
|
||||||
let defaults = list.default_app_for(&mime);
|
let defaults = list.default_app_for(&mime);
|
||||||
|
let aliased_defaults = aliased_mimes
|
||||||
|
.get(&mime)
|
||||||
|
.and_then(|mime| list.default_app_for(mime));
|
||||||
|
|
||||||
let cache = self
|
let cache = self
|
||||||
.cache
|
.cache
|
||||||
.entry(mime.clone())
|
.entry(mime.clone())
|
||||||
.or_insert_with(|| Vec::with_capacity(apps.len()));
|
.or_insert_with(|| Vec::with_capacity(apps.len()));
|
||||||
|
|
||||||
// Sort cached apps for this mime by default precedence.
|
// Sort cached apps for this mime by default precedence.
|
||||||
for default in defaults.into_iter().flatten() {
|
for default in defaults
|
||||||
|
.into_iter()
|
||||||
|
.flatten()
|
||||||
|
.chain(aliased_defaults.into_iter().flatten())
|
||||||
|
{
|
||||||
let default = default.strip_suffix(".desktop").unwrap_or(default.as_ref());
|
let default = default.strip_suffix(".desktop").unwrap_or(default.as_ref());
|
||||||
let mut found_any = false;
|
let mut found_any = false;
|
||||||
apps.retain(|app| {
|
apps.retain(|app| {
|
||||||
|
|
|
||||||
|
|
@ -15,28 +15,21 @@ struct MimeIconKey {
|
||||||
size: u16,
|
size: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MimeIconCache {
|
#[derive(Default)]
|
||||||
|
pub struct MimeIconCache {
|
||||||
cache: FxHashMap<MimeIconKey, Option<icon::Handle>>,
|
cache: FxHashMap<MimeIconKey, Option<icon::Handle>>,
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
shared_mime_info: xdg_mime::SharedMimeInfo,
|
pub shared_mime_info: xdg_mime::SharedMimeInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MimeIconCache {
|
impl MimeIconCache {
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
cache: FxHashMap::default(),
|
|
||||||
#[cfg(unix)]
|
|
||||||
shared_mime_info: xdg_mime::SharedMimeInfo::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(unix))]
|
#[cfg(not(unix))]
|
||||||
pub fn get(&mut self, _key: MimeIconKey) -> Option<icon::Handle> {
|
pub fn get(&mut self, _key: MimeIconKey) -> Option<icon::Handle> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
pub fn get(&mut self, key: MimeIconKey) -> Option<icon::Handle> {
|
fn get(&mut self, key: MimeIconKey) -> Option<icon::Handle> {
|
||||||
self.cache
|
self.cache
|
||||||
.entry(key)
|
.entry(key)
|
||||||
.or_insert_with_key(|key| {
|
.or_insert_with_key(|key| {
|
||||||
|
|
@ -56,8 +49,9 @@ impl MimeIconCache {
|
||||||
.clone()
|
.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static MIME_ICON_CACHE: LazyLock<Mutex<MimeIconCache>> =
|
|
||||||
LazyLock::new(|| Mutex::new(MimeIconCache::new()));
|
pub static MIME_ICON_CACHE: LazyLock<Mutex<MimeIconCache>> =
|
||||||
|
LazyLock::new(|| Mutex::new(MimeIconCache::default()));
|
||||||
|
|
||||||
#[cfg(not(unix))]
|
#[cfg(not(unix))]
|
||||||
pub fn mime_for_path(
|
pub fn mime_for_path(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue