Skip to main content

fractal/
intent.rs

1use std::borrow::Cow;
2
3use gtk::{glib, prelude::*};
4
5use crate::{session::VerificationKey, utils::matrix::MatrixIdUri};
6
7/// Intents that can be handled by a session.
8///
9/// It cannot be cloned intentionally, so it is handled only once.
10#[derive(Debug)]
11pub(crate) enum SessionIntent {
12    /// Show the target of a Matrix ID URI.
13    ShowMatrixId(MatrixIdUri),
14    /// Show an ongoing identity verification.
15    ShowIdentityVerification(VerificationKey),
16}
17
18impl SessionIntent {
19    /// The application action name for the [`SessionIntent::ShowMatrixId`]
20    /// variant.
21    pub(crate) const SHOW_MATRIX_ID_APP_ACTION_NAME: &str = "app.show-matrix-id";
22
23    /// The action name without the `app.` prefix for the
24    /// [`SessionIntent::ShowMatrixId`] variant.
25    pub(crate) const SHOW_MATRIX_ID_ACTION_NAME: &str =
26        Self::SHOW_MATRIX_ID_APP_ACTION_NAME.split_at(4).1;
27
28    /// The application action name for the
29    /// [`SessionIntent::ShowIdentityVerification`] variant.
30    pub(crate) const SHOW_IDENTITY_VERIFICATION_APP_ACTION_NAME: &str =
31        "app.show-identity-verification";
32
33    /// The action name without the `app.` prefix for the
34    /// [`SessionIntent::ShowIdentityVerification`] variant.
35    pub(crate) const SHOW_IDENTITY_VERIFICATION_ACTION_NAME: &str =
36        Self::SHOW_IDENTITY_VERIFICATION_APP_ACTION_NAME
37            .split_at(4)
38            .1;
39
40    /// Get the application action name for this session intent type.
41    pub(crate) fn app_action_name(&self) -> &'static str {
42        match self {
43            SessionIntent::ShowMatrixId(_) => Self::SHOW_MATRIX_ID_APP_ACTION_NAME,
44            SessionIntent::ShowIdentityVerification(_) => {
45                Self::SHOW_IDENTITY_VERIFICATION_APP_ACTION_NAME
46            }
47        }
48    }
49
50    /// Convert the given `GVariant` to a [`SessionIntent::ShowMatrixId`] and
51    /// session ID, given the intent type.
52    ///
53    /// Returns a  `(session_id, intent)` tuple on success. Returns `None` if
54    /// the `GVariant` could not be parsed successfully.
55    pub(crate) fn show_matrix_id_from_variant(variant: &glib::Variant) -> Option<(String, Self)> {
56        let SessionIntentActionParameter {
57            session_id,
58            payload,
59        } = variant.get()?;
60
61        Some((session_id, Self::ShowMatrixId(payload.get()?)))
62    }
63
64    /// Convert the given `GVariant` to a
65    /// [`SessionIntent::ShowIdentityVerification`] and session ID, given the
66    /// intent type.
67    ///
68    /// Returns a  `(session_id, intent)` tuple on success. Returns `None` if
69    /// the `GVariant` could not be parsed successfully.
70    pub(crate) fn show_identity_verification_from_variant(
71        variant: &glib::Variant,
72    ) -> Option<(String, Self)> {
73        let SessionIntentActionParameter {
74            session_id,
75            payload,
76        } = variant.get()?;
77
78        Some((session_id, Self::ShowIdentityVerification(payload.get()?)))
79    }
80
81    /// Convert this intent to a `GVariant` with the given session ID.
82    pub(crate) fn to_variant_with_session_id(&self, session_id: String) -> glib::Variant {
83        let payload = match self {
84            Self::ShowMatrixId(uri) => uri.to_variant(),
85            Self::ShowIdentityVerification(key) => key.to_variant(),
86        };
87
88        SessionIntentActionParameter {
89            session_id,
90            payload,
91        }
92        .to_variant()
93    }
94}
95
96impl StaticVariantType for SessionIntent {
97    fn static_variant_type() -> Cow<'static, glib::VariantTy> {
98        SessionIntentActionParameter::static_variant_type()
99    }
100}
101
102impl From<MatrixIdUri> for SessionIntent {
103    fn from(value: MatrixIdUri) -> Self {
104        Self::ShowMatrixId(value)
105    }
106}
107
108impl From<VerificationKey> for SessionIntent {
109    fn from(value: VerificationKey) -> Self {
110        Self::ShowIdentityVerification(value)
111    }
112}
113
114/// The payload of a [`SessionIntent`], when converted to a `GVariant` for an
115/// app action.
116#[derive(Debug, Clone, glib::Variant)]
117struct SessionIntentActionParameter {
118    /// The ID of the session that should handle the intent.
119    session_id: String,
120    /// The payload of the intent.
121    payload: glib::Variant,
122}