improv(app): use about widget
This commit is contained in:
parent
f95869a631
commit
4d642ee3fa
4 changed files with 62 additions and 101 deletions
10
Cargo.toml
10
Cargo.toml
|
|
@ -6,9 +6,6 @@ edition = "2024"
|
||||||
license = "GPL-3.0-only"
|
license = "GPL-3.0-only"
|
||||||
rust-version = "1.85"
|
rust-version = "1.85"
|
||||||
|
|
||||||
[build-dependencies]
|
|
||||||
vergen = { version = "8", features = ["git", "gitcl"] }
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1"
|
anyhow = "1"
|
||||||
chrono = { version = "0.4", features = ["unstable-locales"] }
|
chrono = { version = "0.4", features = ["unstable-locales"] }
|
||||||
|
|
@ -102,7 +99,12 @@ default = [
|
||||||
"xz2",
|
"xz2",
|
||||||
]
|
]
|
||||||
dbus-config = ["libcosmic/dbus-config"]
|
dbus-config = ["libcosmic/dbus-config"]
|
||||||
desktop = ["libcosmic/desktop", "dep:cosmic-mime-apps", "dep:xdg"]
|
desktop = [
|
||||||
|
"libcosmic/desktop",
|
||||||
|
"libcosmic/about",
|
||||||
|
"dep:cosmic-mime-apps",
|
||||||
|
"dep:xdg",
|
||||||
|
]
|
||||||
desktop-applet = []
|
desktop-applet = []
|
||||||
gvfs = ["dep:gio", "dep:glib"]
|
gvfs = ["dep:gio", "dep:glib"]
|
||||||
io-uring = ["compio/io-uring", "dep:io-uring"]
|
io-uring = ["compio/io-uring", "dep:io-uring"]
|
||||||
|
|
|
||||||
17
build.rs
17
build.rs
|
|
@ -1,17 +0,0 @@
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
||||||
// Rebuild if i18n files change
|
|
||||||
println!("cargo:rerun-if-changed=i18n");
|
|
||||||
|
|
||||||
// Emit version information (if not cached by just vendor)
|
|
||||||
let mut vergen = vergen::EmitBuilder::builder();
|
|
||||||
println!("cargo:rerun-if-env-changed=VERGEN_GIT_COMMIT_DATE");
|
|
||||||
if std::env::var_os("VERGEN_GIT_COMMIT_DATE").is_none() {
|
|
||||||
vergen.git_commit_date();
|
|
||||||
}
|
|
||||||
println!("cargo:rerun-if-env-changed=VERGEN_GIT_SHA");
|
|
||||||
if std::env::var_os("VERGEN_GIT_SHA").is_none() {
|
|
||||||
vergen.git_sha(false);
|
|
||||||
}
|
|
||||||
vergen.fail_on_error().emit()?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
@ -150,7 +150,8 @@ keep = Keep
|
||||||
# Context Pages
|
# Context Pages
|
||||||
|
|
||||||
## About
|
## About
|
||||||
git-description = Git commit {$hash} on {$date}
|
repository = Repository
|
||||||
|
support = Support
|
||||||
|
|
||||||
## Add Network Drive
|
## Add Network Drive
|
||||||
add-network-drive = Add network drive
|
add-network-drive = Add network drive
|
||||||
|
|
|
||||||
125
src/app.rs
125
src/app.rs
|
|
@ -34,8 +34,9 @@ use cosmic::{
|
||||||
style, surface, theme,
|
style, surface, theme,
|
||||||
widget::{
|
widget::{
|
||||||
self,
|
self,
|
||||||
|
about::About,
|
||||||
dnd_destination::DragId,
|
dnd_destination::DragId,
|
||||||
horizontal_space,
|
horizontal_space, icon,
|
||||||
menu::{action::MenuAction, key_bind::KeyBind},
|
menu::{action::MenuAction, key_bind::KeyBind},
|
||||||
segmented_button::{self, Entity},
|
segmented_button::{self, Entity},
|
||||||
vertical_space,
|
vertical_space,
|
||||||
|
|
@ -634,6 +635,7 @@ impl PartialEq for WatcherWrapper {
|
||||||
// The [`App`] stores application-specific state.
|
// The [`App`] stores application-specific state.
|
||||||
pub struct App {
|
pub struct App {
|
||||||
core: Core,
|
core: Core,
|
||||||
|
about: About,
|
||||||
nav_bar_context_id: segmented_button::Entity,
|
nav_bar_context_id: segmented_button::Entity,
|
||||||
nav_model: segmented_button::SingleSelectModel,
|
nav_model: segmented_button::SingleSelectModel,
|
||||||
tab_model: segmented_button::Model<segmented_button::SingleSelect>,
|
tab_model: segmented_button::Model<segmented_button::SingleSelect>,
|
||||||
|
|
@ -1432,7 +1434,7 @@ impl App {
|
||||||
|
|
||||||
nav_model = nav_model.insert(|b| {
|
nav_model = nav_model.insert(|b| {
|
||||||
b.text(fl!("recents"))
|
b.text(fl!("recents"))
|
||||||
.icon(widget::icon::from_name("document-open-recent-symbolic"))
|
.icon(icon::from_name("document-open-recent-symbolic"))
|
||||||
.data(Location::Recents)
|
.data(Location::Recents)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -1448,12 +1450,10 @@ impl App {
|
||||||
nav_model = nav_model.insert(move |b| {
|
nav_model = nav_model.insert(move |b| {
|
||||||
b.text(name.clone())
|
b.text(name.clone())
|
||||||
.icon(
|
.icon(
|
||||||
widget::icon::icon(if path.is_dir() {
|
icon::icon(if path.is_dir() {
|
||||||
tab::folder_icon_symbolic(&path, 16)
|
tab::folder_icon_symbolic(&path, 16)
|
||||||
} else {
|
} else {
|
||||||
widget::icon::from_name("text-x-generic-symbolic")
|
icon::from_name("text-x-generic-symbolic").size(16).handle()
|
||||||
.size(16)
|
|
||||||
.handle()
|
|
||||||
})
|
})
|
||||||
.size(16),
|
.size(16),
|
||||||
)
|
)
|
||||||
|
|
@ -1470,7 +1470,7 @@ impl App {
|
||||||
|
|
||||||
nav_model = nav_model.insert(|b| {
|
nav_model = nav_model.insert(|b| {
|
||||||
b.text(fl!("trash"))
|
b.text(fl!("trash"))
|
||||||
.icon(widget::icon::icon(tab::trash_icon_symbolic(16)))
|
.icon(icon::icon(tab::trash_icon_symbolic(16)))
|
||||||
.data(Location::Trash)
|
.data(Location::Trash)
|
||||||
.divider_above()
|
.divider_above()
|
||||||
});
|
});
|
||||||
|
|
@ -1478,8 +1478,8 @@ impl App {
|
||||||
if !MOUNTERS.is_empty() {
|
if !MOUNTERS.is_empty() {
|
||||||
nav_model = nav_model.insert(|b| {
|
nav_model = nav_model.insert(|b| {
|
||||||
b.text(fl!("networks"))
|
b.text(fl!("networks"))
|
||||||
.icon(widget::icon::icon(
|
.icon(icon::icon(
|
||||||
widget::icon::from_name("network-workgroup-symbolic")
|
icon::from_name("network-workgroup-symbolic")
|
||||||
.size(16)
|
.size(16)
|
||||||
.handle(),
|
.handle(),
|
||||||
))
|
))
|
||||||
|
|
@ -1512,7 +1512,7 @@ impl App {
|
||||||
b = b.data(Location::Network(uri, item.name(), None));
|
b = b.data(Location::Network(uri, item.name(), None));
|
||||||
}
|
}
|
||||||
if let Some(icon) = item.icon(true) {
|
if let Some(icon) = item.icon(true) {
|
||||||
b = b.icon(widget::icon::icon(icon).size(16));
|
b = b.icon(icon::icon(icon).size(16));
|
||||||
}
|
}
|
||||||
if item.is_mounted() {
|
if item.is_mounted() {
|
||||||
b = b.closable();
|
b = b.closable();
|
||||||
|
|
@ -1618,38 +1618,6 @@ impl App {
|
||||||
Task::none()
|
Task::none()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn about(&self) -> Element<Message> {
|
|
||||||
let cosmic_theme::Spacing { space_xxs, .. } = theme::active().cosmic().spacing;
|
|
||||||
let repository = "https://github.com/pop-os/cosmic-files";
|
|
||||||
let hash = env!("VERGEN_GIT_SHA");
|
|
||||||
let short_hash: String = hash.chars().take(7).collect();
|
|
||||||
let date = env!("VERGEN_GIT_COMMIT_DATE");
|
|
||||||
widget::column::with_children(vec![
|
|
||||||
widget::svg(widget::svg::Handle::from_memory(
|
|
||||||
&include_bytes!(
|
|
||||||
"../res/icons/hicolor/128x128/apps/com.system76.CosmicFiles.svg"
|
|
||||||
)[..],
|
|
||||||
))
|
|
||||||
.into(),
|
|
||||||
widget::text::title3(fl!("cosmic-files")).into(),
|
|
||||||
widget::button::link(repository)
|
|
||||||
.on_press(Message::LaunchUrl(repository.to_string()))
|
|
||||||
.padding(0)
|
|
||||||
.into(),
|
|
||||||
widget::button::link(fl!(
|
|
||||||
"git-description",
|
|
||||||
hash = short_hash.as_str(),
|
|
||||||
date = date
|
|
||||||
))
|
|
||||||
.on_press(Message::LaunchUrl(format!("{}/commits/{}", repository, hash)))
|
|
||||||
.padding(0)
|
|
||||||
.into(),
|
|
||||||
])
|
|
||||||
.align_x(Alignment::Center)
|
|
||||||
.spacing(space_xxs)
|
|
||||||
.into()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn network_drive(&self) -> Element<Message> {
|
fn network_drive(&self) -> Element<Message> {
|
||||||
let cosmic_theme::Spacing {
|
let cosmic_theme::Spacing {
|
||||||
space_xxs, space_m, ..
|
space_xxs, space_m, ..
|
||||||
|
|
@ -1782,7 +1750,7 @@ impl App {
|
||||||
.into(),
|
.into(),
|
||||||
if controller.is_paused() {
|
if controller.is_paused() {
|
||||||
widget::tooltip(
|
widget::tooltip(
|
||||||
widget::button::icon(widget::icon::from_name(
|
widget::button::icon(icon::from_name(
|
||||||
"media-playback-start-symbolic",
|
"media-playback-start-symbolic",
|
||||||
))
|
))
|
||||||
.on_press(Message::PendingPause(*id, false))
|
.on_press(Message::PendingPause(*id, false))
|
||||||
|
|
@ -1793,7 +1761,7 @@ impl App {
|
||||||
.into()
|
.into()
|
||||||
} else {
|
} else {
|
||||||
widget::tooltip(
|
widget::tooltip(
|
||||||
widget::button::icon(widget::icon::from_name(
|
widget::button::icon(icon::from_name(
|
||||||
"media-playback-pause-symbolic",
|
"media-playback-pause-symbolic",
|
||||||
))
|
))
|
||||||
.on_press(Message::PendingPause(*id, true))
|
.on_press(Message::PendingPause(*id, true))
|
||||||
|
|
@ -1804,7 +1772,7 @@ impl App {
|
||||||
.into()
|
.into()
|
||||||
},
|
},
|
||||||
widget::tooltip(
|
widget::tooltip(
|
||||||
widget::button::icon(widget::icon::from_name("window-close-symbolic"))
|
widget::button::icon(icon::from_name("window-close-symbolic"))
|
||||||
.on_press(Message::PendingCancel(*id))
|
.on_press(Message::PendingCancel(*id))
|
||||||
.padding(8),
|
.padding(8),
|
||||||
widget::text::body(fl!("cancel")),
|
widget::text::body(fl!("cancel")),
|
||||||
|
|
@ -2124,8 +2092,24 @@ impl Application for App {
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let about = About::default()
|
||||||
|
.name(fl!("cosmic-files"))
|
||||||
|
.icon(icon::from_name(Self::APP_ID))
|
||||||
|
.version(env!("CARGO_PKG_VERSION"))
|
||||||
|
.author("System76")
|
||||||
|
.license("GPL-3.0-only")
|
||||||
|
.developers([("Jeremy Soller", "jeremy@system76.com")])
|
||||||
|
.links([
|
||||||
|
(fl!("repository"), "https://github.com/pop-os/cosmic-files"),
|
||||||
|
(
|
||||||
|
fl!("support"),
|
||||||
|
"https://github.com/pop-os/cosmic-files/issues",
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
|
||||||
let mut app = App {
|
let mut app = App {
|
||||||
core,
|
core,
|
||||||
|
about,
|
||||||
nav_bar_context_id: segmented_button::Entity::null(),
|
nav_bar_context_id: segmented_button::Entity::null(),
|
||||||
nav_model: segmented_button::ModelBuilder::default().build(),
|
nav_model: segmented_button::ModelBuilder::default().build(),
|
||||||
tab_model: segmented_button::ModelBuilder::default().build(),
|
tab_model: segmented_button::ModelBuilder::default().build(),
|
||||||
|
|
@ -2235,11 +2219,7 @@ impl Application for App {
|
||||||
cosmic::Action::App(Message::NavMenuAction(NavMenuAction::OpenInNewTab(entity)))
|
cosmic::Action::App(Message::NavMenuAction(NavMenuAction::OpenInNewTab(entity)))
|
||||||
})
|
})
|
||||||
.context_menu(self.nav_context_menu(self.nav_bar_context_id))
|
.context_menu(self.nav_context_menu(self.nav_bar_context_id))
|
||||||
.close_icon(
|
.close_icon(icon::from_name("media-eject-symbolic").size(16).icon())
|
||||||
widget::icon::from_name("media-eject-symbolic")
|
|
||||||
.size(16)
|
|
||||||
.icon(),
|
|
||||||
)
|
|
||||||
.into_container();
|
.into_container();
|
||||||
|
|
||||||
if !self.core.is_condensed() {
|
if !self.core.is_condensed() {
|
||||||
|
|
@ -3606,7 +3586,7 @@ impl Application for App {
|
||||||
});
|
});
|
||||||
if let Some(entity) = maybe_entity {
|
if let Some(entity) = maybe_entity {
|
||||||
self.nav_model
|
self.nav_model
|
||||||
.icon_set(entity, widget::icon::icon(tab::trash_icon_symbolic(16)));
|
.icon_set(entity, icon::icon(tab::trash_icon_symbolic(16)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Task::batch([self.rescan_trash(), self.update_desktop()]);
|
return Task::batch([self.rescan_trash(), self.update_desktop()]);
|
||||||
|
|
@ -4721,8 +4701,9 @@ impl Application for App {
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(match &self.context_page {
|
Some(match &self.context_page {
|
||||||
ContextPage::About => context_drawer::context_drawer(
|
ContextPage::About => context_drawer::about(
|
||||||
self.about(),
|
&self.about,
|
||||||
|
Message::LaunchUrl,
|
||||||
Message::ToggleContextPage(ContextPage::About),
|
Message::ToggleContextPage(ContextPage::About),
|
||||||
),
|
),
|
||||||
ContextPage::EditHistory => context_drawer::context_drawer(
|
ContextPage::EditHistory => context_drawer::context_drawer(
|
||||||
|
|
@ -4932,7 +4913,7 @@ impl Application for App {
|
||||||
widget::dialog()
|
widget::dialog()
|
||||||
.title("Failed operation")
|
.title("Failed operation")
|
||||||
.body(format!("{:#?}\n{}", operation, err))
|
.body(format!("{:#?}\n{}", operation, err))
|
||||||
.icon(widget::icon::from_name("dialog-error").size(64))
|
.icon(icon::from_name("dialog-error").size(64))
|
||||||
//TODO: retry action
|
//TODO: retry action
|
||||||
.primary_action(
|
.primary_action(
|
||||||
widget::button::standard(fl!("cancel")).on_press(Message::DialogCancel),
|
widget::button::standard(fl!("cancel")).on_press(Message::DialogCancel),
|
||||||
|
|
@ -4941,7 +4922,7 @@ impl Application for App {
|
||||||
DialogPage::ExtractPassword { id, password } => {
|
DialogPage::ExtractPassword { id, password } => {
|
||||||
widget::dialog()
|
widget::dialog()
|
||||||
.title(fl!("extract-password-required"))
|
.title(fl!("extract-password-required"))
|
||||||
.icon(widget::icon::from_name("dialog-error").size(64))
|
.icon(icon::from_name("dialog-error").size(64))
|
||||||
.control(widget::text_input("", password).password().on_input(
|
.control(widget::text_input("", password).password().on_input(
|
||||||
move |password| {
|
move |password| {
|
||||||
Message::DialogUpdate(DialogPage::ExtractPassword { id: *id, password })
|
Message::DialogUpdate(DialogPage::ExtractPassword { id: *id, password })
|
||||||
|
|
@ -4962,7 +4943,7 @@ impl Application for App {
|
||||||
} => widget::dialog()
|
} => widget::dialog()
|
||||||
.title(fl!("mount-error"))
|
.title(fl!("mount-error"))
|
||||||
.body(error)
|
.body(error)
|
||||||
.icon(widget::icon::from_name("dialog-error").size(64))
|
.icon(icon::from_name("dialog-error").size(64))
|
||||||
.primary_action(
|
.primary_action(
|
||||||
widget::button::standard(fl!("try-again")).on_press(Message::DialogComplete),
|
widget::button::standard(fl!("try-again")).on_press(Message::DialogComplete),
|
||||||
)
|
)
|
||||||
|
|
@ -5105,7 +5086,7 @@ impl Application for App {
|
||||||
} => widget::dialog()
|
} => widget::dialog()
|
||||||
.title(fl!("network-drive-error"))
|
.title(fl!("network-drive-error"))
|
||||||
.body(error)
|
.body(error)
|
||||||
.icon(widget::icon::from_name("dialog-error").size(64))
|
.icon(icon::from_name("dialog-error").size(64))
|
||||||
.primary_action(
|
.primary_action(
|
||||||
widget::button::standard(fl!("try-again")).on_press(Message::DialogComplete),
|
widget::button::standard(fl!("try-again")).on_press(Message::DialogComplete),
|
||||||
)
|
)
|
||||||
|
|
@ -5216,7 +5197,7 @@ impl Application for App {
|
||||||
widget::mouse_area(
|
widget::mouse_area(
|
||||||
widget::button::custom(
|
widget::button::custom(
|
||||||
widget::row::with_children(vec![
|
widget::row::with_children(vec![
|
||||||
widget::icon(app.icon.clone()).size(32).into(),
|
icon(app.icon.clone()).size(32).into(),
|
||||||
if app.is_default && !displayed_default {
|
if app.is_default && !displayed_default {
|
||||||
displayed_default = true;
|
displayed_default = true;
|
||||||
widget::text::body(fl!(
|
widget::text::body(fl!(
|
||||||
|
|
@ -5229,9 +5210,7 @@ impl Application for App {
|
||||||
},
|
},
|
||||||
widget::horizontal_space().into(),
|
widget::horizontal_space().into(),
|
||||||
if *selected == i {
|
if *selected == i {
|
||||||
widget::icon::from_name("checkbox-checked-symbolic")
|
icon::from_name("checkbox-checked-symbolic").size(16).into()
|
||||||
.size(16)
|
|
||||||
.into()
|
|
||||||
} else {
|
} else {
|
||||||
widget::Space::with_width(Length::Fixed(16.0)).into()
|
widget::Space::with_width(Length::Fixed(16.0)).into()
|
||||||
},
|
},
|
||||||
|
|
@ -5473,7 +5452,7 @@ impl Application for App {
|
||||||
"favorite-path-error-description",
|
"favorite-path-error-description",
|
||||||
path = path.as_os_str().to_str()
|
path = path.as_os_str().to_str()
|
||||||
))
|
))
|
||||||
.icon(widget::icon::from_name("dialog-error").size(64))
|
.icon(icon::from_name("dialog-error").size(64))
|
||||||
.primary_action(
|
.primary_action(
|
||||||
widget::button::destructive(fl!("remove")).on_press(Message::DialogComplete),
|
widget::button::destructive(fl!("remove")).on_press(Message::DialogComplete),
|
||||||
)
|
)
|
||||||
|
|
@ -5547,29 +5526,25 @@ impl Application for App {
|
||||||
progress_bar.into(),
|
progress_bar.into(),
|
||||||
if all_paused {
|
if all_paused {
|
||||||
widget::tooltip(
|
widget::tooltip(
|
||||||
widget::button::icon(widget::icon::from_name(
|
widget::button::icon(icon::from_name("media-playback-start-symbolic"))
|
||||||
"media-playback-start-symbolic",
|
.on_press(Message::PendingPauseAll(false))
|
||||||
))
|
.padding(8),
|
||||||
.on_press(Message::PendingPauseAll(false))
|
|
||||||
.padding(8),
|
|
||||||
widget::text::body(fl!("resume")),
|
widget::text::body(fl!("resume")),
|
||||||
widget::tooltip::Position::Top,
|
widget::tooltip::Position::Top,
|
||||||
)
|
)
|
||||||
.into()
|
.into()
|
||||||
} else {
|
} else {
|
||||||
widget::tooltip(
|
widget::tooltip(
|
||||||
widget::button::icon(widget::icon::from_name(
|
widget::button::icon(icon::from_name("media-playback-pause-symbolic"))
|
||||||
"media-playback-pause-symbolic",
|
.on_press(Message::PendingPauseAll(true))
|
||||||
))
|
.padding(8),
|
||||||
.on_press(Message::PendingPauseAll(true))
|
|
||||||
.padding(8),
|
|
||||||
widget::text::body(fl!("pause")),
|
widget::text::body(fl!("pause")),
|
||||||
widget::tooltip::Position::Top,
|
widget::tooltip::Position::Top,
|
||||||
)
|
)
|
||||||
.into()
|
.into()
|
||||||
},
|
},
|
||||||
widget::tooltip(
|
widget::tooltip(
|
||||||
widget::button::icon(widget::icon::from_name("window-close-symbolic"))
|
widget::button::icon(icon::from_name("window-close-symbolic"))
|
||||||
.on_press(Message::PendingCancelAll)
|
.on_press(Message::PendingCancelAll)
|
||||||
.padding(8),
|
.padding(8),
|
||||||
widget::text::body(fl!("cancel")),
|
widget::text::body(fl!("cancel")),
|
||||||
|
|
@ -5618,7 +5593,7 @@ impl Application for App {
|
||||||
if self.core.is_condensed() {
|
if self.core.is_condensed() {
|
||||||
elements.push(
|
elements.push(
|
||||||
//TODO: selected state is not appearing different
|
//TODO: selected state is not appearing different
|
||||||
widget::button::icon(widget::icon::from_name("system-search-symbolic"))
|
widget::button::icon(icon::from_name("system-search-symbolic"))
|
||||||
.on_press(Message::SearchClear)
|
.on_press(Message::SearchClear)
|
||||||
.padding(8)
|
.padding(8)
|
||||||
.selected(true)
|
.selected(true)
|
||||||
|
|
@ -5636,7 +5611,7 @@ impl Application for App {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
elements.push(
|
elements.push(
|
||||||
widget::button::icon(widget::icon::from_name("system-search-symbolic"))
|
widget::button::icon(icon::from_name("system-search-symbolic"))
|
||||||
.on_press(Message::SearchActivate)
|
.on_press(Message::SearchActivate)
|
||||||
.padding(8)
|
.padding(8)
|
||||||
.into(),
|
.into(),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue