owned this note
owned this note
Published
Linked with GitHub
# Contacts Zome
###### tags: `Kizuna-architecture`
<img src="https://i.imgur.com/IxrnWIH.png" width=200 align="inline"/>
User Stories
-
* [get a list of all of my blocked contacts](https://beyonder.atlassian.net/browse/KIZUNA-23)
* [get a list of all of my contacts](https://beyonder.atlassian.net/browse/KIZUNA-22)
* [add another user to contacts](https://beyonder.atlassian.net/browse/KIZUNA-10)
* [remove someone from contacts](https://beyonder.atlassian.net/browse/KIZUNA-19)
* [block someone from contacts](https://beyonder.atlassian.net/browse/KIZUNA-20)
* [unblock someone from contacts](https://beyonder.atlassian.net/browse/KIZUNA-21)
* [I don't want to receive messages from contacts that I blocked](https://beyonder.atlassian.net/browse/KIZUNA-294)
* [check whether an agent is in my contacts](https://beyonder.atlassian.net/browse/KIZUNA-24)
* [check whether an agent is in my blocked list](https://beyonder.atlassian.net/browse/KIZUNA-409)
### Comments
- username -> agentpubkey (in ui work with agentpubkey not username)
- return error instead
- accommodate multiple agents to be operated on
## Entry Structure
```rust=
enum ContactType {
Add,
Remove,
Block,
Unblock,
AddToCategory
}
struct CategoryWithId {
id: String,
name: String,
}
#[hdk_entry(id = "contact", visibility = "private")]
pub struct Contacts {
// allows multiple agents to be added etc.
agent_ids: Vec<AgentPubkey>,
created: Timestamp,
contact_type: ContactType,
category: Option<CategoryWithId>
}
#[hdk_entry(id = "category", visibility = "private")]
pub struct Category {
name: String,
}
#[hdk_entry(id = "alias", visibility = "private")]
pub struct Alias {
id: AgentPubKey,
first_name: Option<String>,
last_name: Option<String>
}
```
## Contact Entry Conditionals
- This is to show the general pattern of OpType that can be done to a Contact entry
![](https://i.imgur.com/WrHf8bg.png)
## Zome Fn
### `add_contacts`
```rust
pub fn add_contacts(agent_ids: AgentPubKeysWrapper)
-> ExternResult<AgentPubKeysWrapper>
```
```mermaid
sequenceDiagram
participant AUI as Alice_UI
participant ACD as Alice_Cell
AUI-->>ACD: agent pubkeys
ACD-->>ACD: call get_latest_contacts_info()
opt same agent was operated as contact before
alt added
ACD-->>AUI: Err("agent already added")
else blocked
ACD-->>AUI: Err("agent is blocked")
end
end
ACD-->>ACD: commit Contact entry with ContactType Add
ACD-->>AUI: return AgentPubKeysWrapper
```
### `remove_contacts`
```rust
pub fn remove_contacts(agent_ids: AgentPubKeysWrapper)
-> ExternResult<AgentPubKeysWrapper>
```
```mermaid
sequenceDiagram
participant AUI as Alice_UI
participant ACD as Alice_Cell
AUI-->>ACD: agent pubkeys
ACD-->>ACD: call get_latest_contacts_info()
opt same agent was operated as contact before
alt removed/unblocked/None
ACD-->>AUI: Err("agent is already removed")
else blocked
ACD-->>AUI: Err("agent is blocked")
end
end
ACD-->>ACD: commit Contact entry with ContactType Remove
ACD-->>AUI: return AgentPubKeysWrapper
```
### `block_contacts`
```rust
pub fn block_contacts(agent_ids: AgentPubKeysWrapper)
-> ExternResult<AgentPubKeysWrapper>
```
```mermaid
sequenceDiagram
participant AUI as Alice_UI
participant ACD as Alice_Cell
AUI-->>ACD: agent pubkeys
ACD-->>ACD: call get_latest_contacts_info()
opt same agent was operated as contact before
alt blocked
ACD-->>AUI: Err("this agent is already blocked")
end
end
ACD-->>ACD: commit Contact entry with ContactType Block
ACD-->>AUI: return AgentPubKeysWrapper
```
### `unblock_contacts`
```rust
pub fn unblock_contacts(agent_ids: AgentPubKeysWrapper)
-> ExternResult<AgentPubKeysWrapper>
```
```mermaid
sequenceDiagram
participant AUI as Alice_UI
participant ACD as Alice_Cell
AUI-->>ACD: agent pubkeys
ACD-->>ACD: call get_latest_contacts_info()
opt same agent was operated as contact before
alt unblocked/none/removed
ACD-->>AUI: Err("agent is already unblocked")
else added
ACD-->>AUI: Err("agent cannot be unblocked if added")
end
end
ACD-->>ACD: commit Contact entry with ContactType Unblock
ACD-->>AUI: AgentPubKeysWrapper
```
### `list_added_or_blocked`
- helper function used for the zome fn `list_added` and `list_blocked`
```rust
pub struct AgentPubKeysWrapper(pub Vec<AgentPubkey>)
pub fn list_added_or_blocked(filter: ContactType)
-> ExternResult<AgentPubKeysWrapper>
```
```mermaid
sequenceDiagram
participant AUI as Alice_UI
participant ACD as Alice_Cell
AUI-->>ACD: call list_added() or list_blocked()
ACD-->>ACD: create an empty HashMap<AgentPubKey, Vec<Contact>>
ACD-->>ACD: query all Contacts
loop for contact in queried contacts
alt first Contact for an agent
ACD-->>ACD: insert the contact with key being agentpubkey
else agent already has another Contact entry
ACD-->>ACD: push the contact to Vec<Contact>
end
end
loop for agentpubkey in HashMap
ACD-->>ACD: check the latest Contact for the agent with created field
alt both filter and latest Contact's Contact Type are ContactType:Add
ACD-->>ACD: include the agentpubkey of agent in AgentPubKeysWrapper
else both filter and latest Contact's Contact Type are ContactType:Block
ACD-->>ACD: include the agentpubkey of agent in AgentPubKeysWrapper
else other ContactType
ACD-->>ACD: ignore
end
end
ACD-->>AUI: return AgentPubKeysWrapper
```
### `in_contacts`
- needs to check if this function is still needed
```rust
pub struct BooleanWrapper(pub bool);
pub fn in_contacts(agent_pubkey: AgentPubKey)
-> ExternResult<BooleanWrapper>
```
```mermaid
sequenceDiagram
participant AUI as Alice_UI
participant ACD as Alice_Cell
participant LDHT as Lobby_DHT
ACD-->>ACD: call list_added()
ACD-->>ACD: check if the given AgentPubKey is part of the contacts
ACD-->>ACD: return boolean
```
### `in_blocked`
- needs to check if this function is still needed
```rust
pub struct BooleanWrapper(pub bool);
pub fn in_blocked(agent_pubkey: AgentPubKey)
-> ExternResult<BooleanWrapper>
```
```mermaid
sequenceDiagram
participant AUI as Alice_UI
participant ACD as Alice_Cell
participant LDHT as Lobby_DHT
ACD-->>ACD: call list_blocked()
ACD-->>ACD: check if the given AgentPubKey is part of the blocked contacts
ACD-->>ACD: return boolean
```
### `update_alias`
```rust
pub struct AliasInput {
id: AgentPubKey,
first_name: Option<String>,
last_name: Option<String>
}
pub fn create_alias(input: AliasInput)
-> ExternResult<Alias>
```
### `list_alias`
```rust
pub struct AliasInput {
id: AgentPubKey,
first_name: String,
last_name: String
}pub fn list_alias(input: AliasInput)
-> ExternResult<Vec<Alias>>
```
## Redux State
```javascript=
type ProfileID = string;
export interface Profile {
id: ProfileID;
username: string;
first_name?: string;
last_name?: stringl
}
export interface IndexedContacts {
[key: string]: Profile[];
}
export interface ContactsState {
contacts: Profile[];
blocked: Profile[];
indexedContacts: IndexedContacts;
}
// redux state
const initialState: ContactsState = {
contacts: [],
indexedContacts: {},
blocked: [],
};
```