Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 28 additions & 12 deletions crates/bitwarden-uniffi/src/vault/collections.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use std::{collections::HashMap, sync::Arc};
use std::sync::Arc;

use bitwarden_collections::{
collection::{Collection, CollectionView},
collection::{Collection, CollectionId, CollectionView},
tree::{NodeItem, Tree},
};
use uuid::Uuid;
use bitwarden_vault::collection_client::AncestorMap;

use crate::Result;

Expand Down Expand Up @@ -40,25 +40,34 @@ pub struct CollectionViewTree {
}

#[derive(uniffi::Object)]
#[allow(unused)]
pub struct CollectionViewNodeItem {
node_item: NodeItem<CollectionView>,
}

#[uniffi::export]
impl CollectionViewTree {
pub fn get_item_by_id(&self, collection_id: Uuid) -> Option<Arc<CollectionViewNodeItem>> {
pub fn get_item_for_view(
&self,
collection_view: CollectionView,
) -> Option<Arc<CollectionViewNodeItem>> {
self.tree
.get_item_by_id(collection_id)
.get_item_by_id(collection_view.id.unwrap_or_default().into())
Copy link

@jaasen-livefront jaasen-livefront Sep 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

โ“ Are we ok with swallowing an empty or invalid id here? Is that the goal of this?

Copy link
Member

@Hinton Hinton Sep 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Long term I think we would split CollectionView similar to folders so that ID is required, and you have a separate DTO for creating them.

I wouldn't be particularly concerned about ID being None here.

.map(|n| Arc::new(CollectionViewNodeItem { node_item: n }))
}

pub fn get_root_items(&self) -> Vec<Arc<CollectionViewNodeItem>> {
self.tree
.nodes
.iter()
.filter(|n| n.parent_idx.is_none())
.filter_map(|n| self.get_item_by_id(n.item_id))
.get_root_items()
.into_iter()
.map(|n| Arc::new(CollectionViewNodeItem { node_item: n }))
.collect()
}

pub fn get_flat_items(&self) -> Vec<Arc<CollectionViewNodeItem>> {
self.tree
.get_flat_items()
.into_iter()
.map(|n| Arc::new(CollectionViewNodeItem { node_item: n }))
.collect()
}
}
Expand All @@ -77,7 +86,14 @@ impl CollectionViewNodeItem {
self.node_item.children.clone()
}

pub fn get_ancestors(&self) -> HashMap<Uuid, String> {
self.node_item.ancestors.clone()
pub fn get_ancestors(&self) -> AncestorMap {
AncestorMap {
ancestors: self
.node_item
.ancestors
.iter()
.map(|(&uuid, name)| (CollectionId::new(uuid), name.clone()))
.collect(),
}
}
}
37 changes: 25 additions & 12 deletions crates/bitwarden-vault/src/collection_client.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
use std::collections::HashMap;

use bitwarden_collections::{
collection::{Collection, CollectionView},
collection::{Collection, CollectionId, CollectionView},
tree::{NodeItem, Tree},
};
use bitwarden_core::Client;
use serde::{Deserialize, Serialize};
#[cfg(feature = "wasm")]
use bitwarden_error::js_sys::Map;
use tsify::Tsify;
#[cfg(feature = "wasm")]
use wasm_bindgen::prelude::wasm_bindgen;

Expand Down Expand Up @@ -56,6 +59,16 @@ pub struct CollectionViewNodeItem {
node_item: NodeItem<CollectionView>,
}

#[cfg_attr(
feature = "wasm",
derive(Tsify, Serialize, Deserialize),
tsify(into_wasm_abi, from_wasm_abi)
)]
#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
pub struct AncestorMap {
pub ancestors: HashMap<CollectionId, String>,
}

#[cfg_attr(feature = "wasm", wasm_bindgen)]
impl CollectionViewNodeItem {
pub fn get_item(&self) -> CollectionView {
Expand All @@ -70,21 +83,21 @@ impl CollectionViewNodeItem {
self.node_item.children.clone()
}

#[cfg(feature = "wasm")]
pub fn get_ancestors(&self) -> Map {
self.node_item
.ancestors
.iter()
.fold(Map::new(), |map, (id, name)| {
map.set(&id.to_string().into(), &name.into());
map
})
pub fn get_ancestors(&self) -> AncestorMap {
AncestorMap {
ancestors: self
.node_item
.ancestors
.iter()
.map(|(&uuid, name)| (CollectionId::new(uuid), name.clone()))
.collect(),
}
}
}

#[cfg_attr(feature = "wasm", wasm_bindgen)]
impl CollectionViewTree {
pub fn get_item_by_id(
pub fn get_item_for_view(
&self,
collection_view: CollectionView,
) -> Option<CollectionViewNodeItem> {
Expand Down