mirror of
https://github.com/narrrl/proton-drive-linux.git
synced 2026-11-04 00:47:00 +01:00
fix(core,fuse,gui): UI/UX quick wins from the audit (phase 0)
- Move Google Takeout import out of Settings; Photos owns it, and the
Takeout page's back button returns there.
- Trash from the file browser is Undo-only (no confirm); F2 on a
multi-selection explains why it does nothing.
- Ask before sign-out, rejecting an invitation, removing someone's access,
removing a public link, and switching a folder to on-demand.
- Clearer offline wording ("Make available offline" / "Make online only")
with dedicated offline, online-only and upload symbolic icons; the pin row
is hidden for folders.
- Search hits report whether a file is cached, so search results show the
offline badge.
- Activity log: readable Empty Trash / link entries, distinct icons, and
error/warning styling for failures and conflicts.
- Proper singular/plural counts instead of "item(s)" / "archive(s)".
- Name earlier versions by save time instead of revision id; capitalise
the public link role; stop-syncing uses a stop icon, not a trash can.
- Label the Photos Upload and "Show on map" buttons; toast when a
thumbnail build finishes; the versions button follows the mount state.
- Mode switches and device mutations reload both sync pages.
This commit is contained in:
1 parent
690b91deab
commit
cc308ac25a
27 files changed
+341
-190
No files matched your search
@@ -603,7 +603,6 @@ fn build_window(app: &adw::Application) {
|
||||
&ui,
|
||||
&main_widgets.purge_button,
|
||||
&main_widgets.mountpoint_button,
|
||||
&main_widgets.import_row,
|
||||
);
|
||||
wire_sidebar(&ui);
|
||||
wire_browser(&ui, &browser_widgets.grid, &browser_widgets.column_view);
|
||||
@@ -773,12 +772,12 @@ fn build_sidebar() -> (adw::NavigationPage, gtk4::ListBox) {
|
||||
}
|
||||
|
||||
/// The sidebar destination a page belongs under. Most pages are their own
|
||||
/// destination; a sub-page reached from one (Import, off Settings) has no row of
|
||||
/// destination; a sub-page reached from one (Import, off Photos) has no row of
|
||||
/// its own and answers with its parent, so the sidebar highlights where the user
|
||||
/// came from rather than clearing — which would read as "nowhere".
|
||||
fn destination_of(page: &str) -> &str {
|
||||
match page {
|
||||
"takeout" => "main",
|
||||
"takeout" => "gallery",
|
||||
other => other,
|
||||
}
|
||||
}
|
||||
@@ -956,6 +955,12 @@ fn sync_sidebar(ui: &Rc<Ui>) {
|
||||
}
|
||||
}
|
||||
|
||||
/// "1 item" / "5 items": a count with the noun form that agrees with it, so
|
||||
/// no user-facing string has to fall back to "item(s)".
|
||||
fn count_noun(n: usize, one: &str, many: &str) -> String {
|
||||
format!("{n} {}", if n == 1 { one } else { many })
|
||||
}
|
||||
|
||||
/// Show a transient toast. Non-blocking by design: an action's outcome is
|
||||
/// reported without stealing focus or forcing a click, so the user can keep
|
||||
/// working while a slow upload lands.
|
||||
@@ -1134,7 +1139,11 @@ fn install_shortcuts(ui: &Rc<Ui>, window: &adw::ApplicationWindow) {
|
||||
gtk4::gdk::Key::n | gtk4::gdk::Key::N if ctrl && on_browser => prompt_new_folder(&ui),
|
||||
gtk4::gdk::Key::u | gtk4::gdk::Key::U if ctrl && on_browser => prompt_upload(&ui),
|
||||
gtk4::gdk::Key::F2 if on_browser => {
|
||||
if let Some(entry) = selected_entry(&ui) {
|
||||
// Renaming is one name at a time; saying so beats a key that
|
||||
// silently does nothing with several items highlighted.
|
||||
if selected_entries(&ui).len() > 1 {
|
||||
toast(&ui, "Select a single item to rename it");
|
||||
} else if let Some(entry) = selected_entry(&ui) {
|
||||
prompt_rename(&ui, &entry);
|
||||
}
|
||||
}
|
||||
@@ -1144,7 +1153,7 @@ fn install_shortcuts(ui: &Rc<Ui>, window: &adw::ApplicationWindow) {
|
||||
gtk4::gdk::Key::Delete if on_browser => {
|
||||
let entries = selected_entries(&ui);
|
||||
if !entries.is_empty() {
|
||||
prompt_delete_many(&ui, entries);
|
||||
trash_entries(&ui, entries);
|
||||
}
|
||||
}
|
||||
gtk4::gdk::Key::Escape
|
||||
@@ -1196,6 +1205,28 @@ fn ui_window(ui: &Rc<Ui>) -> Option<gtk4::Window> {
|
||||
ui.stack.root().and_downcast::<gtk4::Window>()
|
||||
}
|
||||
|
||||
/// Ask before an action that has no Undo. `on_confirm` runs only when the user
|
||||
/// picks `action`; Cancel is the default, so Enter never destroys anything.
|
||||
fn confirm_destructive(
|
||||
parent: &impl IsA<gtk4::Widget>,
|
||||
heading: &str,
|
||||
body: &str,
|
||||
action: &str,
|
||||
on_confirm: impl Fn() + 'static,
|
||||
) {
|
||||
let dialog = adw::AlertDialog::builder()
|
||||
.heading(heading)
|
||||
.body(body)
|
||||
.build();
|
||||
dialog.add_response("cancel", "Cancel");
|
||||
dialog.add_response("confirm", action);
|
||||
dialog.set_response_appearance("confirm", adw::ResponseAppearance::Destructive);
|
||||
dialog.set_default_response(Some("cancel"));
|
||||
dialog.set_close_response("cancel");
|
||||
dialog.connect_response(Some("confirm"), move |_, _| on_confirm());
|
||||
dialog.present(Some(parent));
|
||||
}
|
||||
|
||||
/// A dim, non-interactive placeholder row for an empty section.
|
||||
fn dim_row(text: &str) -> adw::ActionRow {
|
||||
let row = adw::ActionRow::builder().title(text).build();
|
||||
|
||||
Reference in new issue
Block a user