desktop: redesign bookmark UI
lets be fair, the previous one was ugly + this one allows you to actually change the URL!
This commit is contained in:
parent
077cf7c77b
commit
231fbb7d66
|
@ -1 +1,7 @@
|
|||
bookmarks-dialog = Manage Bookmarks
|
||||
bookmarks-dialog = Manage Bookmarks
|
||||
|
||||
bookmarks-dialog-name = Name
|
||||
bookmarks-dialog-location = Location
|
||||
bookmarks-dialog-url = URL
|
||||
bookmarks-dialog-no-bookmarks = There are no bookmarks right now
|
||||
bookmarks-dialog-not-selected = Nothing to show
|
|
@ -327,26 +327,21 @@ impl RuffleGui {
|
|||
}
|
||||
});
|
||||
|
||||
let mut have_bookmarks = false;
|
||||
if Button::new(text(locale, "bookmarks-menu-manage")).ui(ui).clicked() {
|
||||
ui.close_menu();
|
||||
self.open_bookmarks();
|
||||
}
|
||||
|
||||
self.preferences.bookmarks(|bookmarks| {
|
||||
have_bookmarks = !bookmarks.is_empty();
|
||||
|
||||
if have_bookmarks {
|
||||
ui.separator();
|
||||
if self.preferences.have_bookmarks() {
|
||||
ui.separator();
|
||||
self.preferences.bookmarks(|bookmarks| {
|
||||
for bookmark in bookmarks.iter().filter(|x| !x.is_invalid()) {
|
||||
if Button::new(crate::util::url_to_readable_name(&bookmark.url)).ui(ui).clicked() {
|
||||
ui.close_menu();
|
||||
let _ = self.event_loop.send_event(RuffleEvent::OpenURL(bookmark.url.clone(), Box::new(self.default_player_options.clone())));
|
||||
}
|
||||
}
|
||||
ui.separator();
|
||||
}
|
||||
});
|
||||
|
||||
if have_bookmarks && Button::new(text(locale, "bookmarks-menu-manage")).ui(ui).clicked() {
|
||||
ui.close_menu();
|
||||
self.open_bookmarks();
|
||||
});
|
||||
}
|
||||
});
|
||||
menu::menu_button(ui, text(locale, "debug-menu"), |ui| {
|
||||
|
|
|
@ -1,66 +1,171 @@
|
|||
use crate::gui::text;
|
||||
use crate::gui::widgets::PathOrUrlField;
|
||||
use crate::preferences::GlobalPreferences;
|
||||
use egui::{Align2, Button, Grid, Widget, Window};
|
||||
use crate::util::url_to_readable_name;
|
||||
use egui::{Align2, Grid, Label, Sense, Ui, Window};
|
||||
use egui_extras::{Column, TableBuilder};
|
||||
use unic_langid::LanguageIdentifier;
|
||||
|
||||
struct SelectedBookmark {
|
||||
index: usize,
|
||||
url: PathOrUrlField,
|
||||
}
|
||||
|
||||
pub struct BookmarksDialog {
|
||||
preferences: GlobalPreferences,
|
||||
selected_bookmark: Option<SelectedBookmark>,
|
||||
}
|
||||
|
||||
impl BookmarksDialog {
|
||||
pub fn new(preferences: GlobalPreferences) -> Self {
|
||||
Self { preferences }
|
||||
Self {
|
||||
preferences,
|
||||
selected_bookmark: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn show(&mut self, locale: &LanguageIdentifier, egui_ctx: &egui::Context) -> bool {
|
||||
let mut keep_open = true;
|
||||
let mut should_close = false;
|
||||
let should_close = false;
|
||||
|
||||
Window::new(text(locale, "bookmarks-dialog"))
|
||||
.open(&mut keep_open)
|
||||
.anchor(Align2::CENTER_CENTER, egui::Vec2::ZERO)
|
||||
.collapsible(false)
|
||||
.resizable(false)
|
||||
.default_width(600.0)
|
||||
.default_height(400.0)
|
||||
.show(egui_ctx, |ui| {
|
||||
Grid::new("bookmarks-dialog-grid")
|
||||
.num_columns(2)
|
||||
.striped(true)
|
||||
.show(ui, |ui| {
|
||||
enum BookmarkAction {
|
||||
Remove(usize),
|
||||
}
|
||||
|
||||
let mut action = None;
|
||||
|
||||
self.preferences.bookmarks(|bookmarks| {
|
||||
// Close the dialog if we have no bookmarks to show.
|
||||
should_close = bookmarks.is_empty();
|
||||
|
||||
for (index, bookmark) in
|
||||
bookmarks.iter().filter(|x| !x.is_invalid()).enumerate()
|
||||
{
|
||||
ui.label(bookmark.url.as_str());
|
||||
|
||||
if Button::new(text(locale, "remove")).ui(ui).clicked() {
|
||||
action = Some(BookmarkAction::Remove(index));
|
||||
}
|
||||
|
||||
ui.end_row();
|
||||
}
|
||||
});
|
||||
|
||||
if let Some(action) = action {
|
||||
if let Err(e) =
|
||||
self.preferences.write_bookmarks(|writer| match action {
|
||||
BookmarkAction::Remove(index) => writer.remove(index),
|
||||
})
|
||||
{
|
||||
tracing::warn!("Couldn't update bookmarks: {e}");
|
||||
}
|
||||
egui::TopBottomPanel::top("bookmark-dialog-top-panel")
|
||||
.resizable(true)
|
||||
.min_height(100.0)
|
||||
.show_inside(ui, |ui| {
|
||||
if self.preferences.have_bookmarks() {
|
||||
self.show_bookmark_table(locale, ui);
|
||||
} else {
|
||||
ui.centered_and_justified(|ui| {
|
||||
ui.label(text(locale, "bookmarks-dialog-no-bookmarks"));
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
self.show_bookmark_panel(locale, ui);
|
||||
});
|
||||
|
||||
keep_open && !should_close
|
||||
}
|
||||
|
||||
fn show_bookmark_table(&mut self, locale: &LanguageIdentifier, ui: &mut Ui) {
|
||||
let text_height = egui::TextStyle::Body
|
||||
.resolve(ui.style())
|
||||
.size
|
||||
.max(ui.spacing().interact_size.y);
|
||||
|
||||
enum BookmarkAction {
|
||||
Remove(usize),
|
||||
}
|
||||
|
||||
let mut action = None;
|
||||
|
||||
TableBuilder::new(ui)
|
||||
.striped(true)
|
||||
.resizable(true)
|
||||
.column(Column::auto())
|
||||
.column(Column::remainder())
|
||||
.sense(Sense::click())
|
||||
.header(20.0, |mut header| {
|
||||
header.col(|ui| {
|
||||
ui.strong(text(locale, "bookmarks-dialog-name"));
|
||||
});
|
||||
header.col(|ui| {
|
||||
ui.strong(text(locale, "bookmarks-dialog-location"));
|
||||
});
|
||||
})
|
||||
.body(|mut body| {
|
||||
self.preferences.bookmarks(|bookmarks| {
|
||||
for (index, bookmark) in bookmarks.iter().enumerate() {
|
||||
if bookmark.is_invalid() {
|
||||
continue;
|
||||
}
|
||||
|
||||
body.row(text_height, |mut row| {
|
||||
if let Some(selected) = &self.selected_bookmark {
|
||||
row.set_selected(index == selected.index);
|
||||
}
|
||||
|
||||
row.col(|ui| {
|
||||
ui.add(
|
||||
Label::new(url_to_readable_name(&bookmark.url))
|
||||
.selectable(false)
|
||||
.wrap(false),
|
||||
);
|
||||
});
|
||||
row.col(|ui| {
|
||||
ui.add(
|
||||
Label::new(bookmark.url.as_str())
|
||||
.selectable(false)
|
||||
.wrap(false),
|
||||
);
|
||||
});
|
||||
|
||||
let response = row.response();
|
||||
response.context_menu(|ui| {
|
||||
if ui.button(text(locale, "remove")).clicked() {
|
||||
ui.close_menu();
|
||||
action = Some(BookmarkAction::Remove(index));
|
||||
}
|
||||
});
|
||||
if response.clicked() {
|
||||
self.selected_bookmark = Some(SelectedBookmark {
|
||||
index,
|
||||
// TODO: set hint
|
||||
url: PathOrUrlField::new(Some(bookmark.url.clone()), ""),
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if let Some(action) = action {
|
||||
if let Err(e) = self.preferences.write_bookmarks(|writer| match action {
|
||||
BookmarkAction::Remove(index) => {
|
||||
// TODO: Recalculate the index for the selected bookmark, if it survives, otherwise just set to None.
|
||||
self.selected_bookmark = None;
|
||||
writer.remove(index);
|
||||
}
|
||||
}) {
|
||||
tracing::warn!("Couldn't update bookmarks: {e}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn show_bookmark_panel(&mut self, locale: &LanguageIdentifier, ui: &mut Ui) {
|
||||
if let Some(bookmark) = &mut self.selected_bookmark {
|
||||
Grid::new("bookmarks-dialog-panel-grid")
|
||||
.num_columns(2)
|
||||
.show(ui, |ui| {
|
||||
let previous_url = bookmark.url.value().cloned();
|
||||
|
||||
ui.label(text(locale, "bookmarks-dialog-url"));
|
||||
let current_url = bookmark.url.ui(locale, ui).value();
|
||||
|
||||
if previous_url.as_ref() != current_url {
|
||||
if let Some(url) = current_url {
|
||||
if let Err(e) = self.preferences.write_bookmarks(|writer| {
|
||||
writer.set_url(bookmark.index, url.clone());
|
||||
}) {
|
||||
tracing::warn!("Couldn't update bookmarks: {e}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ui.end_row();
|
||||
});
|
||||
} else {
|
||||
ui.vertical_centered_justified(|ui| {
|
||||
ui.label(text(locale, "bookmarks-dialog-not-selected"));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -151,10 +151,20 @@ impl GlobalPreferences {
|
|||
fun(&self
|
||||
.bookmarks
|
||||
.lock()
|
||||
.expect("Bookmarks is no reentrant")
|
||||
.expect("Bookmarks is not reentrant")
|
||||
.values)
|
||||
}
|
||||
|
||||
pub fn have_bookmarks(&self) -> bool {
|
||||
let bookmarks = &self
|
||||
.bookmarks
|
||||
.lock()
|
||||
.expect("Bookmarks is not reentrant")
|
||||
.values;
|
||||
|
||||
!bookmarks.is_empty() && !bookmarks.iter().all(|x| x.is_invalid())
|
||||
}
|
||||
|
||||
pub fn write_preferences(&self, fun: impl FnOnce(&mut PreferencesWriter)) -> Result<(), Error> {
|
||||
let mut preferences = self
|
||||
.preferences
|
||||
|
|
|
@ -58,6 +58,12 @@ impl<'a> BookmarksWriter<'a> {
|
|||
Self(bookmarks)
|
||||
}
|
||||
|
||||
fn bookmark_table(&mut self, index: usize) -> &mut Table {
|
||||
self.get_underlying_table()
|
||||
.get_mut(index)
|
||||
.expect("invalid bookmark index")
|
||||
}
|
||||
|
||||
fn get_underlying_table(&mut self) -> &mut ArrayOfTables {
|
||||
if self.0.toml_document.contains_array_of_tables("bookmark") {
|
||||
return self.0.toml_document["bookmark"]
|
||||
|
@ -80,6 +86,12 @@ impl<'a> BookmarksWriter<'a> {
|
|||
self.0.values.push(bookmark);
|
||||
}
|
||||
|
||||
pub fn set_url(&mut self, index: usize, url: url::Url) {
|
||||
let table = self.bookmark_table(index);
|
||||
table["url"] = value(url.as_str());
|
||||
self.0.values[index].url = url;
|
||||
}
|
||||
|
||||
pub fn remove(&mut self, index: usize) {
|
||||
let table = self.get_underlying_table();
|
||||
table.remove(index);
|
||||
|
|
Loading…
Reference in New Issue