desktop: custom bookmark names

Bookmark names can now be changed by the user, defaults to the URL file.
This commit is contained in:
sleepycatcoding 2024-04-02 18:13:42 +03:00 committed by Nathan Adams
parent 231fbb7d66
commit 5cb9988183
5 changed files with 81 additions and 17 deletions

View File

@ -316,6 +316,7 @@ impl RuffleGui {
// FIXME: if spoof url is used, the URL here is incorrect (fun fact, its also incorrect in the debug tools). // FIXME: if spoof url is used, the URL here is incorrect (fun fact, its also incorrect in the debug tools).
match Url::from_str(player.swf().url()) { match Url::from_str(player.swf().url()) {
Ok(url) => writer.add(crate::preferences::Bookmark { Ok(url) => writer.add(crate::preferences::Bookmark {
name: crate::util::url_to_readable_name(&url).into_owned(),
url, url,
}), }),
Err(e) => tracing::warn!("Failed to parse SWF url for bookmark: {e}"), Err(e) => tracing::warn!("Failed to parse SWF url for bookmark: {e}"),
@ -336,7 +337,7 @@ impl RuffleGui {
ui.separator(); ui.separator();
self.preferences.bookmarks(|bookmarks| { self.preferences.bookmarks(|bookmarks| {
for bookmark in bookmarks.iter().filter(|x| !x.is_invalid()) { for bookmark in bookmarks.iter().filter(|x| !x.is_invalid()) {
if Button::new(crate::util::url_to_readable_name(&bookmark.url)).ui(ui).clicked() { if Button::new(&bookmark.name).ui(ui).clicked() {
ui.close_menu(); ui.close_menu();
let _ = self.event_loop.send_event(RuffleEvent::OpenURL(bookmark.url.clone(), Box::new(self.default_player_options.clone()))); let _ = self.event_loop.send_event(RuffleEvent::OpenURL(bookmark.url.clone(), Box::new(self.default_player_options.clone())));
} }

View File

@ -1,13 +1,13 @@
use crate::gui::text; use crate::gui::text;
use crate::gui::widgets::PathOrUrlField; use crate::gui::widgets::PathOrUrlField;
use crate::preferences::GlobalPreferences; use crate::preferences::GlobalPreferences;
use crate::util::url_to_readable_name;
use egui::{Align2, Grid, Label, Sense, Ui, Window}; use egui::{Align2, Grid, Label, Sense, Ui, Window};
use egui_extras::{Column, TableBuilder}; use egui_extras::{Column, TableBuilder};
use unic_langid::LanguageIdentifier; use unic_langid::LanguageIdentifier;
struct SelectedBookmark { struct SelectedBookmark {
index: usize, index: usize,
name: String,
url: PathOrUrlField, url: PathOrUrlField,
} }
@ -94,11 +94,7 @@ impl BookmarksDialog {
} }
row.col(|ui| { row.col(|ui| {
ui.add( ui.add(Label::new(&bookmark.name).selectable(false).wrap(false));
Label::new(url_to_readable_name(&bookmark.url))
.selectable(false)
.wrap(false),
);
}); });
row.col(|ui| { row.col(|ui| {
ui.add( ui.add(
@ -119,6 +115,7 @@ impl BookmarksDialog {
self.selected_bookmark = Some(SelectedBookmark { self.selected_bookmark = Some(SelectedBookmark {
index, index,
// TODO: set hint // TODO: set hint
name: bookmark.name.clone(),
url: PathOrUrlField::new(Some(bookmark.url.clone()), ""), url: PathOrUrlField::new(Some(bookmark.url.clone()), ""),
}); });
} }
@ -145,11 +142,22 @@ impl BookmarksDialog {
Grid::new("bookmarks-dialog-panel-grid") Grid::new("bookmarks-dialog-panel-grid")
.num_columns(2) .num_columns(2)
.show(ui, |ui| { .show(ui, |ui| {
ui.label(text(locale, "bookmarks-dialog-name"));
if ui.text_edit_singleline(&mut bookmark.name).lost_focus() {
if let Err(e) = self.preferences.write_bookmarks(|writer| {
writer.set_name(bookmark.index, bookmark.name.clone());
}) {
tracing::warn!("Couldn't update bookmarks: {e}");
}
}
ui.end_row();
let previous_url = bookmark.url.value().cloned(); let previous_url = bookmark.url.value().cloned();
ui.label(text(locale, "bookmarks-dialog-url")); ui.label(text(locale, "bookmarks-dialog-url"));
let current_url = bookmark.url.ui(locale, ui).value(); let current_url = bookmark.url.ui(locale, ui).value();
// TOOD: Change the UrlOrPathField widget to return a response instead, so we can update when we lose the focus, removes the need to clone every redraw.
if previous_url.as_ref() != current_url { if previous_url.as_ref() != current_url {
if let Some(url) = current_url { if let Some(url) = current_url {
if let Err(e) = self.preferences.write_bookmarks(|writer| { if let Err(e) = self.preferences.write_bookmarks(|writer| {
@ -159,7 +167,6 @@ impl BookmarksDialog {
} }
} }
} }
ui.end_row(); ui.end_row();
}); });
} else { } else {

View File

@ -256,6 +256,7 @@ pub static INVALID_URL: &str = "invalid:///";
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub struct Bookmark { pub struct Bookmark {
pub url: Url, pub url: Url,
pub name: String,
} }
impl Bookmark { impl Bookmark {

View File

@ -271,7 +271,13 @@ pub fn read_bookmarks(input: &str) -> (ParseResult<Vec<Bookmark>>, DocumentMut)
.expect("Url is constant and valid"), .expect("Url is constant and valid"),
}; };
result.result.push(Bookmark { url }); let name = match bookmark.parse_from_str(cx, "name") {
Some(value) => value,
// Fallback to using the URL as the name.
None => crate::util::url_to_readable_name(&url).into_owned(),
};
result.result.push(Bookmark { url, name });
} }
}); });
@ -603,6 +609,7 @@ mod tests {
assert_eq!( assert_eq!(
ParseResult { ParseResult {
result: vec![], result: vec![],
warnings: vec![ warnings: vec![
"Invalid bookmark: expected array of tables but found table".to_string() "Invalid bookmark: expected array of tables but found table".to_string()
] ]
@ -614,6 +621,7 @@ mod tests {
ParseResult { ParseResult {
result: vec![Bookmark { result: vec![Bookmark {
url: Url::parse(crate::preferences::INVALID_URL).unwrap(), url: Url::parse(crate::preferences::INVALID_URL).unwrap(),
name: "".to_string(),
}], }],
warnings: vec![], warnings: vec![],
}, },
@ -624,11 +632,26 @@ mod tests {
ParseResult { ParseResult {
result: vec![Bookmark { result: vec![Bookmark {
url: Url::parse(crate::preferences::INVALID_URL).unwrap(), url: Url::parse(crate::preferences::INVALID_URL).unwrap(),
name: "".to_string(),
}], }],
warnings: vec!["Invalid bookmark.url: unsupported value \"invalid\"".to_string()], warnings: vec!["Invalid bookmark.url: unsupported value \"invalid\"".to_string()],
}, },
read_bookmarks("[[bookmark]]\nurl = \"invalid\"").0, read_bookmarks("[[bookmark]]\nurl = \"invalid\"").0,
); );
assert_eq!(
ParseResult {
result: vec![Bookmark {
url: Url::parse("https://ruffle.rs/logo-anim.swf").unwrap(),
name: "Logo SWF".to_string(),
}],
warnings: vec![],
},
read_bookmarks(
"[[bookmark]]\nurl = \"https://ruffle.rs/logo-anim.swf\"\nname = \"Logo SWF\""
)
.0
);
} }
#[test] #[test]
@ -638,9 +661,11 @@ mod tests {
result: vec![ result: vec![
Bookmark { Bookmark {
url: Url::from_str("file:///home/user/example.swf").unwrap(), url: Url::from_str("file:///home/user/example.swf").unwrap(),
name: "example.swf".to_string(),
}, },
Bookmark { Bookmark {
url: Url::from_str("https://ruffle.rs/logo-anim.swf").unwrap(), url: Url::from_str("https://ruffle.rs/logo-anim.swf").unwrap(),
name: "logo-anim.swf".to_string(),
} }
], ],
warnings: vec![], warnings: vec![],
@ -662,15 +687,19 @@ mod tests {
result: vec![ result: vec![
Bookmark { Bookmark {
url: Url::from_str("file:///home/user/example.swf").unwrap(), url: Url::from_str("file:///home/user/example.swf").unwrap(),
name: "example.swf".to_string(),
}, },
Bookmark { Bookmark {
url: Url::parse(crate::preferences::INVALID_URL).unwrap(), url: Url::parse(crate::preferences::INVALID_URL).unwrap(),
name: "".to_string(),
}, },
Bookmark { Bookmark {
url: Url::parse(crate::preferences::INVALID_URL).unwrap(), url: Url::parse(crate::preferences::INVALID_URL).unwrap(),
name: "".to_string(),
}, },
Bookmark { Bookmark {
url: Url::from_str("https://ruffle.rs/logo-anim.swf").unwrap(), url: Url::from_str("https://ruffle.rs/logo-anim.swf").unwrap(),
name: "logo-anim.swf".to_string(),
} }
], ],

View File

@ -82,6 +82,7 @@ impl<'a> BookmarksWriter<'a> {
let table = self.get_underlying_table(); let table = self.get_underlying_table();
let mut bookmark_table = Table::new(); let mut bookmark_table = Table::new();
bookmark_table["url"] = value(bookmark.url.to_string()); bookmark_table["url"] = value(bookmark.url.to_string());
bookmark_table["name"] = value(&bookmark.name);
table.push(bookmark_table); table.push(bookmark_table);
self.0.values.push(bookmark); self.0.values.push(bookmark);
} }
@ -92,6 +93,12 @@ impl<'a> BookmarksWriter<'a> {
self.0.values[index].url = url; self.0.values[index].url = url;
} }
pub fn set_name(&mut self, index: usize, name: String) {
let table = self.bookmark_table(index);
table["name"] = value(&name);
self.0.values[index].name = name;
}
pub fn remove(&mut self, index: usize) { pub fn remove(&mut self, index: usize) {
let table = self.get_underlying_table(); let table = self.get_underlying_table();
table.remove(index); table.remove(index);
@ -242,6 +249,7 @@ mod tests {
use super::*; use super::*;
use crate::preferences::read::read_bookmarks; use crate::preferences::read::read_bookmarks;
use std::str::FromStr; use std::str::FromStr;
use url::Url;
define_serialization_test_helpers!(read_bookmarks, BookmarksAndDocument, BookmarksWriter); define_serialization_test_helpers!(read_bookmarks, BookmarksAndDocument, BookmarksWriter);
@ -251,14 +259,30 @@ mod tests {
"", "",
|writer| { |writer| {
writer.add(Bookmark { writer.add(Bookmark {
url: url::Url::from_str("file:///home/user/example.swf").unwrap(), url: Url::from_str("file:///home/user/example.swf").unwrap(),
name: "example.swf".to_string(),
}) })
}, },
"[[bookmark]]\nurl = \"file:///home/user/example.swf\"\n", "[[bookmark]]\nurl = \"file:///home/user/example.swf\"\nname = \"example.swf\"\n",
); );
test("[[bookmark]]\nurl = \"file:///home/user/example.swf\"\n", |writer| writer.add(Bookmark { test("[[bookmark]]\nurl = \"file:///home/user/example.swf\"\n", |writer| writer.add(Bookmark {
url: url::Url::from_str("file:///home/user/another_file.swf").unwrap() url: Url::from_str("file:///home/user/another_file.swf").unwrap(),
}), "[[bookmark]]\nurl = \"file:///home/user/example.swf\"\n\n[[bookmark]]\nurl = \"file:///home/user/another_file.swf\"\n"); name: "another_file.swf".to_string(),
}), "[[bookmark]]\nurl = \"file:///home/user/example.swf\"\n\n[[bookmark]]\nurl = \"file:///home/user/another_file.swf\"\nname = \"another_file.swf\"\n");
}
#[test]
fn modify_bookmark() {
test(
"[[bookmark]]\nurl = \"file:///example.swf\"\n",
|writer| writer.set_name(0, "Custom Name".to_string()),
"[[bookmark]]\nurl = \"file:///example.swf\"\nname = \"Custom Name\"\n",
);
test(
"[[bookmark]]\nurl = \"file:///example.swf\"\nname = \"example.swf\"",
|writer| writer.set_url(0, Url::parse("https://ruffle.rs/logo-anim.swf").unwrap()),
"[[bookmark]]\nurl = \"https://ruffle.rs/logo-anim.swf\"\nname = \"example.swf\"\n",
);
} }
#[test] #[test]
@ -284,20 +308,22 @@ mod tests {
"[bookmark]", "[bookmark]",
|writer| { |writer| {
writer.add(Bookmark { writer.add(Bookmark {
url: url::Url::from_str("file:///test.swf").unwrap(), url: Url::from_str("file:///test.swf").unwrap(),
name: "test.swf".to_string(),
}) })
}, },
"[[bookmark]]\nurl = \"file:///test.swf\"\n", "[[bookmark]]\nurl = \"file:///test.swf\"\nname = \"test.swf\"\n",
); );
test( test(
"bookmark = 1010", "bookmark = 1010",
|writer| { |writer| {
writer.add(Bookmark { writer.add(Bookmark {
url: url::Url::from_str("file:///test.swf").unwrap(), url: Url::from_str("file:///test.swf").unwrap(),
name: "test.swf".to_string(),
}) })
}, },
"[[bookmark]]\nurl = \"file:///test.swf\"\n", "[[bookmark]]\nurl = \"file:///test.swf\"\nname = \"test.swf\"\n",
); );
} }
} }