Add bookmark thumbnail metadata
This commit is contained in:
@@ -286,6 +286,9 @@ fn bookmark_metadata_label(bookmark: &BookmarkEntry) -> String {
|
|||||||
if let Some(note) = bookmark.note() {
|
if let Some(note) = bookmark.note() {
|
||||||
parts.push(note.to_string());
|
parts.push(note.to_string());
|
||||||
}
|
}
|
||||||
|
if bookmark.thumbnail_key().is_some() {
|
||||||
|
parts.push("Snapshot saved".to_string());
|
||||||
|
}
|
||||||
parts.join(" - ")
|
parts.join(" - ")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -63,6 +63,23 @@ impl BrowserCore {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_bookmark_thumbnail_key(
|
||||||
|
&mut self,
|
||||||
|
bookmark_id: &BookmarkId,
|
||||||
|
thumbnail_key: impl Into<String>,
|
||||||
|
) -> Result<(), CoreError> {
|
||||||
|
self.bookmark_mut(bookmark_id)?.set_thumbnail_key(thumbnail_key)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear_bookmark_thumbnail_key(
|
||||||
|
&mut self,
|
||||||
|
bookmark_id: &BookmarkId,
|
||||||
|
) -> Result<(), CoreError> {
|
||||||
|
self.bookmark_mut(bookmark_id)?.clear_thumbnail_key();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn update_bookmark_metadata(
|
pub fn update_bookmark_metadata(
|
||||||
&mut self,
|
&mut self,
|
||||||
bookmark_id: &BookmarkId,
|
bookmark_id: &BookmarkId,
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ fn bookmark_active_tab_records_current_context() -> Result<(), Box<dyn Error>> {
|
|||||||
assert_eq!(bookmark.url().as_str(), "https://example.com/research");
|
assert_eq!(bookmark.url().as_str(), "https://example.com/research");
|
||||||
assert!(bookmark.tags().is_empty());
|
assert!(bookmark.tags().is_empty());
|
||||||
assert_eq!(bookmark.note(), None);
|
assert_eq!(bookmark.note(), None);
|
||||||
|
assert_eq!(bookmark.thumbnail_key(), None);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,6 +66,22 @@ fn bookmark_metadata_updates_collection_tags_and_note() -> Result<(), Box<dyn Er
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn bookmark_thumbnail_key_can_be_set_and_cleared() -> Result<(), Box<dyn Error>> {
|
||||||
|
let mut core = BrowserCore::new(InitialBrowserConfig::ely_defaults()?)?;
|
||||||
|
core.open_tab(UrlText::parse("https://example.com/research")?);
|
||||||
|
let bookmark_id = core.bookmark_active_tab()?;
|
||||||
|
|
||||||
|
core.set_bookmark_thumbnail_key(&bookmark_id, " screenshots/example.avif ")?;
|
||||||
|
let snapshot = core.snapshot()?;
|
||||||
|
assert_eq!(snapshot.bookmarks[0].thumbnail_key(), Some("screenshots/example.avif"));
|
||||||
|
|
||||||
|
core.clear_bookmark_thumbnail_key(&bookmark_id)?;
|
||||||
|
let snapshot = core.snapshot()?;
|
||||||
|
assert_eq!(snapshot.bookmarks[0].thumbnail_key(), None);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn bookmark_metadata_batch_update_is_atomic() -> Result<(), Box<dyn Error>> {
|
fn bookmark_metadata_batch_update_is_atomic() -> Result<(), Box<dyn Error>> {
|
||||||
let mut core = BrowserCore::new(InitialBrowserConfig::ely_defaults()?)?;
|
let mut core = BrowserCore::new(InitialBrowserConfig::ely_defaults()?)?;
|
||||||
@@ -111,6 +128,13 @@ fn bookmark_metadata_rejects_empty_fields() -> Result<(), Box<dyn Error>> {
|
|||||||
return Err("expected empty bookmark note error".into());
|
return Err("expected empty bookmark note error".into());
|
||||||
};
|
};
|
||||||
assert_eq!(note_error, CoreError::Domain(DomainError::EmptyField { field: "bookmark note" }));
|
assert_eq!(note_error, CoreError::Domain(DomainError::EmptyField { field: "bookmark note" }));
|
||||||
|
let Err(thumbnail_error) = core.set_bookmark_thumbnail_key(&bookmark_id, " ") else {
|
||||||
|
return Err("expected empty bookmark thumbnail key error".into());
|
||||||
|
};
|
||||||
|
assert_eq!(
|
||||||
|
thumbnail_error,
|
||||||
|
CoreError::Domain(DomainError::EmptyField { field: "bookmark thumbnail key" })
|
||||||
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ pub struct BookmarkEntry {
|
|||||||
url: UrlText,
|
url: UrlText,
|
||||||
tags: Vec<String>,
|
tags: Vec<String>,
|
||||||
note: Option<String>,
|
note: Option<String>,
|
||||||
|
thumbnail_key: Option<String>,
|
||||||
added_at: SystemTime,
|
added_at: SystemTime,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,6 +37,7 @@ impl BookmarkEntry {
|
|||||||
url,
|
url,
|
||||||
tags: Vec::new(),
|
tags: Vec::new(),
|
||||||
note: None,
|
note: None,
|
||||||
|
thumbnail_key: None,
|
||||||
added_at,
|
added_at,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -85,6 +87,11 @@ impl BookmarkEntry {
|
|||||||
self.note.as_deref()
|
self.note.as_deref()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn thumbnail_key(&self) -> Option<&str> {
|
||||||
|
self.thumbnail_key.as_deref()
|
||||||
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn added_at(&self) -> SystemTime {
|
pub fn added_at(&self) -> SystemTime {
|
||||||
self.added_at
|
self.added_at
|
||||||
@@ -111,6 +118,18 @@ impl BookmarkEntry {
|
|||||||
pub fn clear_note(&mut self) {
|
pub fn clear_note(&mut self) {
|
||||||
self.note = None;
|
self.note = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_thumbnail_key(
|
||||||
|
&mut self,
|
||||||
|
thumbnail_key: impl Into<String>,
|
||||||
|
) -> Result<(), DomainError> {
|
||||||
|
self.thumbnail_key = Some(non_empty_text("bookmark thumbnail key", thumbnail_key.into())?);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear_thumbnail_key(&mut self) {
|
||||||
|
self.thumbnail_key = None;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn non_empty_text(field: &'static str, value: String) -> Result<String, DomainError> {
|
fn non_empty_text(field: &'static str, value: String) -> Result<String, DomainError> {
|
||||||
|
|||||||
@@ -194,3 +194,18 @@ Group archive uses the explicit archive command for the same active group flow:
|
|||||||
│ example.com │ │
|
│ example.com │ │
|
||||||
└──────────────────────────────┴───────────────────────────────────────────────┘
|
└──────────────────────────────┴───────────────────────────────────────────────┘
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Bookmarks with saved page thumbnails keep the list compact and show the snapshot state inline:
|
||||||
|
|
||||||
|
```text
|
||||||
|
┌──────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
│ ELY Browser [ ely://bookmarks............................ ] [pin] [*] [+] │
|
||||||
|
├──────────────────────────────┬───────────────────────────────────────────────┤
|
||||||
|
│ Tabs │ Bookmarks 1 bookmark │
|
||||||
|
│ Bookmarks │ Profile: Default │
|
||||||
|
│ │ │
|
||||||
|
│ │ [book] example.com [open][edit]│
|
||||||
|
│ │ https://example.com/research │
|
||||||
|
│ │ Work - Snapshot saved │
|
||||||
|
└──────────────────────────────┴───────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|||||||
Reference in New Issue
Block a user