fractal/
intent.rs

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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
use std::borrow::Cow;

use gtk::{glib, prelude::*};
use ruma::{OwnedRoomId, OwnedUserId, RoomId, UserId};

use crate::{
    session::model::VerificationKey,
    utils::matrix::{MatrixIdUri, MatrixRoomIdUri},
};

/// An intent when opening or activating the application.
///
/// This can be received either via D-Bus or via the command line.
///
/// It cannot be cloned intentionnally, so it is handled only once.
#[derive(Debug)]
pub enum AppIntent {
    /// An intent for a given session.
    WithSession(SessionIntent),
    /// Show the target of a Matrix ID URI.
    ShowMatrixId(MatrixIdUri),
}

impl From<SessionIntent> for AppIntent {
    fn from(value: SessionIntent) -> Self {
        Self::WithSession(value)
    }
}

impl From<MatrixIdUri> for AppIntent {
    fn from(value: MatrixIdUri) -> Self {
        Self::ShowMatrixId(value)
    }
}

/// An intent for a given session.
///
/// It cannot be cloned intentionnally, so it is handled only once.
#[derive(Debug)]
pub enum SessionIntent {
    /// Show an existing room.
    ShowRoom(ShowRoomPayload),
    /// Show an ongoing identity verification.
    ShowIdentityVerification(ShowIdentityVerificationPayload),
    /// Join a room.
    JoinRoom(JoinRoomPayload),
    /// Show a user.
    ShowUser(ShowUserPayload),
}

impl SessionIntent {
    /// Constructs an `AppIntent` with the given Matrix ID URI and session ID.
    pub fn with_matrix_uri(session_id: String, matrix_uri: MatrixIdUri) -> Self {
        match matrix_uri {
            MatrixIdUri::Room(room_uri) => Self::JoinRoom(JoinRoomPayload {
                session_id,
                room_uri,
            }),
            MatrixIdUri::User(user_id) => Self::ShowUser(ShowUserPayload {
                session_id,
                user_id,
            }),
            // FIXME: We don't support showing specific events in the room history.
            MatrixIdUri::Event(event_uri) => Self::JoinRoom(JoinRoomPayload {
                session_id,
                room_uri: event_uri.room_uri,
            }),
        }
    }

    /// The ID of the session that should process this intent.
    pub fn session_id(&self) -> &str {
        match self {
            Self::ShowRoom(p) => &p.session_id,
            Self::ShowIdentityVerification(p) => &p.session_id,
            Self::JoinRoom(p) => &p.session_id,
            Self::ShowUser(p) => &p.session_id,
        }
    }
}

/// The payload to show a room.
#[derive(Debug)]
pub struct ShowRoomPayload {
    pub session_id: String,
    pub room_id: OwnedRoomId,
}

impl StaticVariantType for ShowRoomPayload {
    fn static_variant_type() -> Cow<'static, glib::VariantTy> {
        <(String, String)>::static_variant_type()
    }
}

impl ToVariant for ShowRoomPayload {
    fn to_variant(&self) -> glib::Variant {
        (&self.session_id, self.room_id.as_str()).to_variant()
    }
}

impl FromVariant for ShowRoomPayload {
    fn from_variant(variant: &glib::Variant) -> Option<Self> {
        let (session_id, room_id) = variant.get::<(String, String)>()?;
        let room_id = RoomId::parse(room_id).ok()?;
        Some(Self {
            session_id,
            room_id,
        })
    }
}

/// The payload to show an ongoing identity verification.
#[derive(Debug)]
pub struct ShowIdentityVerificationPayload {
    pub session_id: String,
    pub key: VerificationKey,
}

impl StaticVariantType for ShowIdentityVerificationPayload {
    fn static_variant_type() -> Cow<'static, glib::VariantTy> {
        <(String, String, String)>::static_variant_type()
    }
}

impl ToVariant for ShowIdentityVerificationPayload {
    fn to_variant(&self) -> glib::Variant {
        (
            &self.session_id,
            self.key.user_id.as_str(),
            &self.key.flow_id,
        )
            .to_variant()
    }
}

impl FromVariant for ShowIdentityVerificationPayload {
    fn from_variant(variant: &glib::Variant) -> Option<Self> {
        let (session_id, user_id, flow_id) = variant.get::<(String, String, String)>()?;
        let user_id = UserId::parse(user_id).ok()?;
        Some(Self {
            session_id,
            key: VerificationKey::new(user_id, flow_id),
        })
    }
}

/// The payload to join a room.
#[derive(Debug)]
pub struct JoinRoomPayload {
    pub session_id: String,
    pub room_uri: MatrixRoomIdUri,
}

/// The payload to show a user.
#[derive(Debug)]
pub struct ShowUserPayload {
    pub session_id: String,
    pub user_id: OwnedUserId,
}