Fetching local and remote trees

First, we need to teach our Store to inflate trees from the storage backend. As you might expect, fetch_local_tree builds the local tree, and fetch_remote_tree builds the remote tree. The trees should be complete, so don't leave out orphans, missing children, or bookmarks with invalid GUIDs or URLs. That way, Dogear has a full picture of the state of the world.

Let's assume we've stored the following records. The current time is T = 11, A was downloaded during the last sync (at T = 6), and the menu and B during this sync:

{ "id": "menu", "type": "folder", "parentid": "places", "children": ["bookmarkAAAA", "bookmarkBBBB"], "modified": 10 }
{ "id": "bookmarkAAAA", "type": "bookmark", "parentid": "menu", "modified": 5 }
{ "id": "bookmarkBBBB", "type": "bookmark", "parentid": "menu", "modified": 10 }

We can build a tree from those records like this, starting with the root:


# #![allow(unused_variables)]
#fn main() {
# extern crate dogear;
use dogear::{Item, Tree};
let mut builder = Tree::with_root(Item::root());
#}

For cases where we know the structure is valid, and the tree already contains the parent, we can use by_structure to indicate that the parent's children and child's parentid match. This is how we build the local tree on Desktop. Notice that we also set the needs_merge flag, to indicate that the menu has changes that we should merge:

# extern crate dogear;
# use dogear::{Result, Tree};
use dogear::{Guid, Item, Kind, MENU_GUID, ROOT_GUID};

# fn main() -> Result<()> {
let now_millis = 11;

# let mut builder = Tree::with_root(Item::root());
let mut menu = Item::new(MENU_GUID.clone(), Kind::Folder);
menu.age = now_millis - 10;
menu.needs_merge = true;

builder
    .item(menu)?
    .by_structure(&ROOT_GUID)?;
# Ok(())
# }

For cases where the parentid and children might disagree, we can set parents from parentid and children separately, using by_parent_guid and by_children. This is equivalent to by_structure, just slightly less efficient:

# extern crate dogear;
# use dogear::{Item, Kind, Tree, Result, MENU_GUID, ROOT_GUID};
# fn main() -> Result<()> {
# let now_millis = 11;
# let mut builder = Tree::with_root(Item::root());
# let mut menu = Item::new(MENU_GUID.clone(), Kind::Folder);
# builder.item(menu)?.by_structure(&ROOT_GUID)?;
let mut a = Item::new("bookmarkAAAA".into(), Kind::Bookmark);
a.age = now_millis - 5;

builder
    .item(a)?
    .by_parent_guid(MENU_GUID.clone())?;
builder.parent_for(&"bookmarkAAAA".into())
    .by_children(&MENU_GUID)?;
# Ok(())
# }

We can also insert an item without its parents, and set parents by parentid and children later, if they exist. This is also equivalent to the above:

# extern crate dogear;
# use dogear::{Item, Kind, Tree, Result, MENU_GUID, ROOT_GUID};
# fn main() -> Result<()> {
# let now_millis = 11;
# let mut builder = Tree::with_root(Item::root());
# let mut menu = Item::new(MENU_GUID.clone(), Kind::Folder);
# builder.item(menu)?.by_structure(&ROOT_GUID)?;
let mut b = Item::new("bookmarkBBBB".into(), Kind::Bookmark);
b.age = now_millis - 10;
b.needs_merge = true;

builder.item(b)?;
builder.parent_for(&"bookmarkBBBB".into())
    .by_parent_guid(MENU_GUID.clone())?;
builder.parent_for(&"bookmarkBBBB".into())
    .by_children(&MENU_GUID)?;
# Ok(())
# }

Finally, let's build and print out our tree!

# extern crate dogear;
# use dogear::{Item, Tree, Result};
use dogear::IntoTree;
# fn main() -> Result<()> {
# let mut builder = Tree::with_root(Item::root());
let tree = builder.into_tree()?;
println!("{}", tree);
# Ok(())
# }

And we see:

📂 root________ (Folder; Age = 0ms)
| 📂 menu________ (Folder; Age = 1ms; Unmerged)
| | 🔖 bookmarkAAAA (Bookmark; Age = 6ms)
| | 🔖 bookmarkBBBB (Bookmark; Age = 1ms; Unmerged)