desktop: allow multiple bookmarks with the same URL

This commit is contained in:
sleepycatcoding 2024-03-31 23:05:44 +03:00 committed by Nathan Adams
parent e1f9b5e5df
commit fb93ef9cb6
5 changed files with 51 additions and 48 deletions

View File

@ -333,7 +333,7 @@ impl RuffleGui {
if have_bookmarks {
ui.separator();
for bookmark in 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())));

View File

@ -36,7 +36,9 @@ impl BookmarksDialog {
// Close the dialog if we have no bookmarks to show.
should_close = bookmarks.is_empty();
for (index, bookmark) in bookmarks.iter().enumerate() {
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() {

View File

@ -241,7 +241,15 @@ pub struct LogPreferences {
pub filename_pattern: FilenamePattern,
}
pub static INVALID_URL: &str = "invalid:///";
#[derive(Debug, PartialEq)]
pub struct Bookmark {
pub url: Url,
}
impl Bookmark {
pub fn is_invalid(&self) -> bool {
self.url.as_str() == INVALID_URL
}
}

View File

@ -267,10 +267,8 @@ pub fn read_bookmarks(input: &str) -> (ParseResult<Vec<Bookmark>>, DocumentMut)
for bookmark in bookmarks.iter() {
let url = match bookmark.parse_from_str(cx, "url") {
Some(value) => value,
None => {
cx.add_warning("Missing bookmark.url".to_string());
continue;
}
None => url::Url::parse(crate::preferences::INVALID_URL)
.expect("Url is constant and valid"),
};
result.result.push(Bookmark { url });
@ -614,15 +612,19 @@ mod tests {
assert_eq!(
ParseResult {
result: vec![],
warnings: vec!["Missing bookmark.url".to_string()],
result: vec![Bookmark {
url: Url::parse(crate::preferences::INVALID_URL).unwrap(),
}],
warnings: vec![],
},
read_bookmarks("[[bookmark]]").0
);
assert_eq!(
ParseResult {
result: vec![],
result: vec![Bookmark {
url: Url::parse(crate::preferences::INVALID_URL).unwrap(),
}],
warnings: vec!["Invalid bookmark.url: unsupported value \"invalid\"".to_string()],
},
read_bookmarks("[[bookmark]]\nurl = \"invalid\"").0,
@ -661,15 +663,18 @@ mod tests {
Bookmark {
url: Url::from_str("file:///home/user/example.swf").unwrap(),
},
Bookmark {
url: Url::parse(crate::preferences::INVALID_URL).unwrap(),
},
Bookmark {
url: Url::parse(crate::preferences::INVALID_URL).unwrap(),
},
Bookmark {
url: Url::from_str("https://ruffle.rs/logo-anim.swf").unwrap(),
}
],
warnings: vec![
"Invalid bookmark.url: unsupported value \"invalid\"".to_string(),
"Missing bookmark.url".to_string()
],
warnings: vec!["Invalid bookmark.url: unsupported value \"invalid\"".to_string(),],
},
read_bookmarks(
r#"

View File

@ -59,42 +59,29 @@ impl<'a> BookmarksWriter<'a> {
}
pub fn add(&mut self, bookmark: Bookmark) {
// TODO: if more fields are added, this should use URL matching (e.g. other properties are ignored)
if !self.0.values.contains(&bookmark) {
if let Some(array) = self.0.toml_document["bookmark"]
.or_insert(array())
.as_array_of_tables_mut()
{
// TODO: If we add a BookmarkWriter use this here instead rather than duplicating the table write code.
let mut table = Table::new();
table["url"] = value(bookmark.url.to_string());
array.push(table);
self.0.values.push(bookmark);
} else {
// TODO: There is definitely a better way to handle this, then just logging a warning.
tracing::warn!("bookmark is not an array of tables, bookmarks will NOT be saved.");
}
}
}
pub fn remove(&mut self, index: usize) {
// We need to get the URL to find the bookmark in the TOML file, since index may not correspond to
// the same table entry (i.e. invalid tables and such that we want to keep intact for compatibility purposes)
let bookmark = self.0.values.remove(index);
// Remove the bookmark from the TOML file.
if let Some(array) = self.0.toml_document["bookmark"]
.or_insert(array())
.as_array_of_tables_mut()
{
let bookmark_url = bookmark.url.to_string();
array.retain(|x| {
if let Some(url) = x.get("url").and_then(|x| x.as_str()) {
return url != bookmark_url;
}
// TODO: If we add a BookmarkWriter use this here instead rather than duplicating the table write code.
let mut table = Table::new();
table["url"] = value(bookmark.url.to_string());
array.push(table);
self.0.values.push(bookmark);
} else {
// TODO: There is definitely a better way to handle this, then just logging a warning.
tracing::warn!("bookmark is not an array of tables, bookmarks will NOT be saved.");
}
}
true
});
pub fn remove(&mut self, index: usize) {
self.0.values.remove(index);
if let Some(array) = self.0.toml_document["bookmark"]
.or_insert(array())
.as_array_of_tables_mut()
{
array.remove(index);
} else {
// TODO: We should add a way to return an error from write methods.
tracing::warn!("bookmark is not an array of tables, bookmarks will NOT be saved.");
@ -273,11 +260,12 @@ mod tests {
},
"[[bookmark]]\nurl = \"file://home/user/example.swf\"\n\n[[bookmark]]\nurl = \"file:///another_file.swf\"\n",
);
// Test that we leave invalid bookmark tables intact when removing a bookmark.
test("[[bookmark]]\nurl = \"file://home/user/example.swf\"\n\n[[bookmark]]\n\n[[bookmark]]\nurl = \"https://ruffle.rs/logo-anim.swf\"\n\n[[bookmark]]\nurl = \"invalid\"\n", |writer| {
writer.remove(1);
}, "[[bookmark]]\nurl = \"file://home/user/example.swf\"\n\n[[bookmark]]\n\n[[bookmark]]\nurl = \"invalid\"\n")
writer.remove(2);
}, "[[bookmark]]\nurl = \"file://home/user/example.swf\"\n\n[[bookmark]]\n\n[[bookmark]]\nurl = \"invalid\"\n");
// check if we can remove invalid entries.
test("[[bookmark]]", |writer| writer.remove(0), "");
}
}
}