aboutsummaryrefslogtreecommitdiffstats
path: root/filamento/src/chat.rs
blob: 5f58866c869ace9b25cd88a3b11787fdf3c0f48d (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
use std::fmt::{Display, Write};

use chrono::{DateTime, Utc};
use jid::JID;
use rusqlite::{
    ToSql,
    types::{FromSql, ToSqlOutput, Value},
};
use uuid::Uuid;

#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "reactive_stores", derive(reactive_stores::Store))]
pub struct Message {
    pub id: Uuid,
    // does not contain full user information
    // bare jid (for now)
    pub from: JID,
    pub delivery: Option<Delivery>,
    pub timestamp: DateTime<Utc>,
    // TODO: originally_from
    // TODO: message edits
    // TODO: message timestamp
    pub body: Body,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub enum Delivery {
    Sending,
    Written,
    Sent,
    Delivered,
    Read,
    Failed,
    Queued,
}

impl Display for Delivery {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Delivery::Sending => f.write_str("sending"),
            Delivery::Written => f.write_str("written"),
            Delivery::Sent => f.write_str("sent"),
            Delivery::Delivered => f.write_str("delivered"),
            Delivery::Read => f.write_str("read"),
            Delivery::Failed => f.write_str("failed"),
            Delivery::Queued => f.write_str("queued"),
        }
    }
}

impl ToSql for Delivery {
    fn to_sql(&self) -> rusqlite::Result<rusqlite::types::ToSqlOutput<'_>> {
        Ok(match self {
            Delivery::Sending => ToSqlOutput::Owned(Value::Text("sending".to_string())),
            Delivery::Written => ToSqlOutput::Owned(Value::Text("written".to_string())),
            Delivery::Sent => ToSqlOutput::Owned(Value::Text("sent".to_string())),
            Delivery::Delivered => ToSqlOutput::Owned(Value::Text("delivered".to_string())),
            Delivery::Read => ToSqlOutput::Owned(Value::Text("read".to_string())),
            Delivery::Failed => ToSqlOutput::Owned(Value::Text("failed".to_string())),
            Delivery::Queued => ToSqlOutput::Owned(Value::Text("queued".to_string())),
        })
    }
}

impl FromSql for Delivery {
    fn column_result(value: rusqlite::types::ValueRef<'_>) -> rusqlite::types::FromSqlResult<Self> {
        Ok(match value.as_str()? {
            "sending" => Self::Sending,
            "written" => Self::Written,
            "sent" => Self::Sent,
            "delivered" => Self::Delivered,
            "read" => Self::Read,
            "failed" => Self::Failed,
            "queued" => Self::Queued,
            // TODO: don't have these lol
            value => panic!("unexpected subscription `{value}`"),
        })
    }
}

// TODO: user migrations
// pub enum Migrated {
//     Jabber(User),
//     Outside,
// }

#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct Body {
    // TODO: rich text, other contents, threads
    pub body: String,
}

#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "reactive_stores", derive(reactive_stores::Store))]
pub struct Chat {
    pub correspondent: JID,
    pub have_chatted: bool,
    // pub unread_messages: i32,
    // pub latest_message: Message,
    // when a new message is received, the chat should be updated, and the new message should be delivered too.
    // message history is not stored in chat, retreived separately.
    // pub message_history: Vec<Message>,
}

pub enum ChatUpdate {}

impl Chat {
    pub fn new(correspondent: JID, have_chatted: bool) -> Self {
        Self {
            correspondent,
            have_chatted,
        }
    }
    pub fn correspondent(&self) -> &JID {
        &self.correspondent
    }
}

// TODO: group chats
// pub enum Chat {
//     Direct(DirectChat),
//     Channel(Channel),
// }
// pub struct Channel {}