summaryrefslogtreecommitdiffstats
path: root/src/user.rs
blob: fb722c667ce8c7a2f5dabbb6590ae19a3dd95a18 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
use std::ops::{Deref, DerefMut};

use filamento::user::{User, UserStoreFields};
use jid::BareJID;
use reactive_stores::{ArcStore, Store};
use leptos::prelude::*;

use crate::{client::Client, roster::{Roster, RosterStoreFields}, state_store::{StateListener, StateStore}};

#[derive(Clone, Copy)]
pub struct MacawUser {
    pub user: ArenaItem<ArcMacawUser>,
    // TODO: just store avatar src in user
    // pub avatar: String,
    // pub avatar: RwSignal<String>,
}

impl MacawUser {
    pub fn get(&self) -> ArcStore<User> {
        self.try_get_value().unwrap().get().0
    }

    pub fn avatar(&self) -> ArcRwSignal<String> {
        self.try_get_value().unwrap().get().1
    }
}

impl Deref for MacawUser {
    type Target = ArenaItem<ArcMacawUser>;

    fn deref(&self) -> &Self::Target {
        &self.user
    }
}

impl DerefMut for MacawUser {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.user
    }
}

impl From<ArcMacawUser> for MacawUser {
    fn from(value: ArcMacawUser) -> Self {
        Self {
            user: ArenaItem::new_with_storage(value),
            // avatar: value.avatar.into(),
        }
    }
}

impl From<MacawUser> for ArcMacawUser {
    fn from(value: MacawUser) -> Self {
        value.user.try_get_value().unwrap()
    }
}

#[derive(Clone)]
pub struct ArcMacawUser {
    pub user: StateListener<BareJID, (ArcStore<User>, ArcRwSignal<String>)>,
}

impl ArcMacawUser {
    pub async fn got_user(user: User) -> Self {
        let user_state_store: StateStore<BareJID, (ArcStore<User>, ArcRwSignal<String>)> =
            use_context().expect("no user state store");
        let old_user = user_state_store.get_listener(user.jid.clone());
        let user = if let Some(old_user) = old_user {
            old_user.update(|(old_user, _avatar)| { old_user.set(user); });
            old_user
        } else {
            let avatar = fetch_avatar(user.avatar.as_deref()).await;
            let avatar = ArcRwSignal::new(avatar);
            user_state_store.store(user.jid.clone(), (ArcStore::new(user), avatar))
        };
        let user = ArcMacawUser { user };
        user
    }
}

impl Deref for ArcMacawUser {
    type Target = StateListener<BareJID, (ArcStore<User>, ArcRwSignal<String>)>;

    fn deref(&self) -> &Self::Target {
        &self.user
    }
}

impl DerefMut for ArcMacawUser {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.user
    }
}

pub const NO_AVATAR: &str = "/assets/no-avatar.png";

pub async fn fetch_avatar(id: Option<&str>) -> String {
    if let Some(avatar) = id {
        let client = use_context::<Client>().expect("client not in context");
        if let Some(data) = client.file_store.get_src(avatar).await {
            data
        } else {
            NO_AVATAR.to_string()
        }
    } else {
        NO_AVATAR.to_string()
    }
}

pub async fn get_avatar(user: Store<User>) -> String {
    if let Some(avatar) = &user.read().avatar {
        let client = use_context::<Client>().expect("client not in context");
        if let Some(data) = client.file_store.get_src(avatar).await {
            data
        } else {
            NO_AVATAR.to_string()
        }
    } else {
        NO_AVATAR.to_string()
    }
}

pub fn get_name(user: Store<User>, note_to_self: bool) -> String {
    let roster: Store<Roster> = use_context().expect("no roster in context");
    if note_to_self {
        let client: Client = use_context().expect("no client in context");
        if *client.jid == *user.jid().read() {
            return "Note to self".to_string()
        }
    }
    if let Some(name) = roster
        .contacts()
        .read()
        .get(&user.read().jid)
        .map(|contact| contact.read().name.clone())
        .unwrap_or_default()
    {
        name.to_string()
    } else if let Some(nick) = &user.read().nick {
        nick.to_string()
    } else {
        user.read().jid.to_string()
    }
}