chore(default_apps): reduce code duplication

Also fixes the flex items wrapping too early by setting the FlexRow width to Shrink.
This commit is contained in:
Vukašin Vojinović 2026-04-17 14:26:39 +02:00 • committed by Michael Murphy
parent 317de19eb3
commit 26f0fb0609

View file

@ -11,7 +11,7 @@ use std::{
use cosmic::{ use cosmic::{
Apply, Element, Task, Apply, Element, Task,
iced::Alignment, iced::{Alignment, Length},
surface, surface,
widget::{self, dropdown, icon, settings}, widget::{self, dropdown, icon, settings},
}; };
@ -281,269 +281,83 @@ impl Page {
} }
} }
fn app_item(meta: &AppMeta, label: String, category: Category) -> widget::FlexRow<'_, Message> {
// Avoid creating popup_dropdown for empty app lists.
// Empty categories are rendered as non-interactive text to prevent Wayland crashes.
settings::flex_item(
label,
if meta.apps.is_empty() {
widget::text(fl!("default-apps", "not-installed")).apply(Element::from)
} else {
dropdown::popup_dropdown(
&meta.apps,
meta.selected,
move |id| Message::SetDefault(category, id),
cosmic::iced::window::Id::RESERVED,
Message::Surface,
|a| crate::app::Message::PageMessage(crate::pages::Message::DefaultApps(a)),
)
.icons(Cow::Borrowed(&meta.icons))
.apply(Element::from)
},
)
.align_items(Alignment::Center)
.width(Length::Shrink)
}
fn apps() -> Section<crate::pages::Message> { fn apps() -> Section<crate::pages::Message> {
Section::default().view::<Page>(move |_binder, page, section| { Section::default().view::<Page>(move |_binder, page, section| {
let Some(mime_apps) = page.mime_apps.as_ref() else { let Some(mime_apps) = page.mime_apps.as_ref() else {
return widget::space().into(); return widget::space().into();
}; };
// Avoid creating popup_dropdown for empty app lists. settings::section::with_capacity(9)
// Empty categories are rendered as non-interactive text to prevent Wayland crashes.
settings::section()
.title(&section.title) .title(&section.title)
.add({ .add(app_item(
let meta = &mime_apps.apps[DROPDOWN_WEB_BROWSER]; &mime_apps.apps[DROPDOWN_WEB_BROWSER],
if meta.apps.is_empty() { fl!("default-apps", "web-browser"),
settings::flex_item( Category::WebBrowser,
fl!("default-apps", "web-browser"), ))
widget::text(fl!("default-apps", "not-installed")), .add(app_item(
) &mime_apps.apps[DROPDOWN_FILE_MANAGER],
.align_items(Alignment::Center) fl!("default-apps", "file-manager"),
} else { Category::FileManager,
settings::flex_item( ))
fl!("default-apps", "web-browser"), .add(app_item(
dropdown::popup_dropdown( &mime_apps.apps[DROPDOWN_MAIL],
&meta.apps, fl!("default-apps", "mail-client"),
meta.selected, Category::Mail,
|id| Message::SetDefault(Category::WebBrowser, id), ))
cosmic::iced::window::Id::RESERVED, .add(app_item(
Message::Surface, &mime_apps.apps[DROPDOWN_MUSIC],
|a| { fl!("default-apps", "music"),
crate::app::Message::PageMessage( Category::Audio,
crate::pages::Message::DefaultApps(a), ))
) .add(app_item(
}, &mime_apps.apps[DROPDOWN_VIDEO],
) fl!("default-apps", "video"),
.icons(Cow::Borrowed(&meta.icons)), Category::Video,
) ))
.align_items(Alignment::Center) .add(app_item(
.min_item_width(300.0) &mime_apps.apps[DROPDOWN_PHOTO],
} fl!("default-apps", "photos"),
}) Category::Image,
.add({ ))
let meta = &mime_apps.apps[DROPDOWN_FILE_MANAGER]; .add(app_item(
if meta.apps.is_empty() { &mime_apps.apps[DROPDOWN_CALENDAR],
settings::flex_item( fl!("default-apps", "calendar"),
fl!("default-apps", "file-manager"), Category::Calendar,
widget::text(fl!("default-apps", "not-installed")), ))
) .add(app_item(
.align_items(Alignment::Center) &mime_apps.apps[DROPDOWN_TERMINAL],
} else { fl!("default-apps", "terminal"),
settings::flex_item( Category::Terminal,
fl!("default-apps", "file-manager"), ))
dropdown::popup_dropdown( .add(app_item(
&meta.apps, &mime_apps.apps[DROPDOWN_TEXT_EDITOR],
meta.selected, fl!("default-apps", "text-editor"),
|id| Message::SetDefault(Category::FileManager, id), Category::TextEditor,
cosmic::iced::window::Id::RESERVED, ))
Message::Surface,
|a| {
crate::app::Message::PageMessage(
crate::pages::Message::DefaultApps(a),
)
},
)
.icons(Cow::Borrowed(&meta.icons)),
)
.align_items(Alignment::Center)
}
})
.add({
let meta = &mime_apps.apps[DROPDOWN_MAIL];
if meta.apps.is_empty() {
settings::flex_item(
fl!("default-apps", "mail-client"),
widget::text(fl!("default-apps", "not-installed")),
)
.align_items(Alignment::Center)
} else {
settings::flex_item(
fl!("default-apps", "mail-client"),
dropdown::popup_dropdown(
&meta.apps,
meta.selected,
|id| Message::SetDefault(Category::Mail, id),
cosmic::iced::window::Id::RESERVED,
Message::Surface,
|a| {
crate::app::Message::PageMessage(
crate::pages::Message::DefaultApps(a),
)
},
)
.icons(Cow::Borrowed(&meta.icons)),
)
.align_items(Alignment::Center)
}
})
.add({
let meta = &mime_apps.apps[DROPDOWN_MUSIC];
if meta.apps.is_empty() {
settings::flex_item(
fl!("default-apps", "music"),
widget::text(fl!("default-apps", "not-installed")),
)
.align_items(Alignment::Center)
} else {
settings::flex_item(
fl!("default-apps", "music"),
dropdown::popup_dropdown(
&meta.apps,
meta.selected,
|id| Message::SetDefault(Category::Audio, id),
cosmic::iced::window::Id::RESERVED,
Message::Surface,
|a| {
crate::app::Message::PageMessage(
crate::pages::Message::DefaultApps(a),
)
},
)
.icons(Cow::Borrowed(&meta.icons)),
)
.align_items(Alignment::Center)
}
})
.add({
let meta = &mime_apps.apps[DROPDOWN_VIDEO];
if meta.apps.is_empty() {
settings::flex_item(
fl!("default-apps", "video"),
widget::text(fl!("default-apps", "not-installed")),
)
.align_items(Alignment::Center)
} else {
settings::flex_item(
fl!("default-apps", "video"),
dropdown::popup_dropdown(
&meta.apps,
meta.selected,
|id| Message::SetDefault(Category::Video, id),
cosmic::iced::window::Id::RESERVED,
Message::Surface,
|a| {
crate::app::Message::PageMessage(
crate::pages::Message::DefaultApps(a),
)
},
)
.icons(Cow::Borrowed(&meta.icons)),
)
.align_items(Alignment::Center)
}
})
.add({
let meta = &mime_apps.apps[DROPDOWN_PHOTO];
if meta.apps.is_empty() {
settings::flex_item(
fl!("default-apps", "photos"),
widget::text(fl!("default-apps", "not-installed")),
)
.align_items(Alignment::Center)
} else {
settings::flex_item(
fl!("default-apps", "photos"),
dropdown::popup_dropdown(
&meta.apps,
meta.selected,
|id| Message::SetDefault(Category::Image, id),
cosmic::iced::window::Id::RESERVED,
Message::Surface,
|a| {
crate::app::Message::PageMessage(
crate::pages::Message::DefaultApps(a),
)
},
)
.icons(Cow::Borrowed(&meta.icons)),
)
.align_items(Alignment::Center)
}
})
.add({
let meta = &mime_apps.apps[DROPDOWN_CALENDAR];
if meta.apps.is_empty() {
settings::flex_item(
fl!("default-apps", "calendar"),
widget::text(fl!("default-apps", "not-installed")),
)
.align_items(Alignment::Center)
} else {
settings::flex_item(
fl!("default-apps", "calendar"),
dropdown::popup_dropdown(
&meta.apps,
meta.selected,
|id| Message::SetDefault(Category::Calendar, id),
cosmic::iced::window::Id::RESERVED,
Message::Surface,
|a| {
crate::app::Message::PageMessage(
crate::pages::Message::DefaultApps(a),
)
},
)
.icons(Cow::Borrowed(&meta.icons)),
)
.align_items(Alignment::Center)
}
})
.add({
let meta = &mime_apps.apps[DROPDOWN_TERMINAL];
if meta.apps.is_empty() {
settings::flex_item(
fl!("default-apps", "terminal"),
widget::text(fl!("default-apps", "not-installed")),
)
.align_items(Alignment::Center)
} else {
settings::flex_item(
fl!("default-apps", "terminal"),
dropdown::popup_dropdown(
&meta.apps,
meta.selected,
|id| Message::SetDefault(Category::Terminal, id),
cosmic::iced::window::Id::RESERVED,
Message::Surface,
|a| {
crate::app::Message::PageMessage(
crate::pages::Message::DefaultApps(a),
)
},
)
.icons(Cow::Borrowed(&meta.icons)),
)
.align_items(Alignment::Center)
}
})
.add({
let meta = &mime_apps.apps[DROPDOWN_TEXT_EDITOR];
if meta.apps.is_empty() {
settings::flex_item(
fl!("default-apps", "text-editor"),
widget::text(fl!("default-apps", "not-installed")),
)
.align_items(Alignment::Center)
} else {
settings::flex_item(
fl!("default-apps", "text-editor"),
dropdown::popup_dropdown(
&meta.apps,
meta.selected,
|id| Message::SetDefault(Category::TextEditor, id),
cosmic::iced::window::Id::RESERVED,
Message::Surface,
|a| {
crate::app::Message::PageMessage(
crate::pages::Message::DefaultApps(a),
)
},
)
.icons(Cow::Borrowed(&meta.icons)),
)
.align_items(Alignment::Center)
}
})
.apply(Element::from) .apply(Element::from)
.map(crate::pages::Message::DefaultApps) .map(crate::pages::Message::DefaultApps)
}) })