diff --git a/src/application.rs b/src/application.rs index b9f99734..26fbbe7e 100644 --- a/src/application.rs +++ b/src/application.rs @@ -7,7 +7,7 @@ use tracing::{debug, error, info, warn}; use crate::{ GETTEXT_PACKAGE, Window, config, - intent::{SessionIntent, SessionIntentType}, + intent::SessionIntent, prelude::*, session::model::{Session, SessionState}, session_list::{FailedSession, SessionInfo, SessionList}, @@ -182,23 +182,20 @@ mod imp { .build(), // Show a room. This is the action triggered when clicking a notification about a // message. - gio::ActionEntry::builder(SessionIntentType::ShowMatrixId.action_name()) - .parameter_type(Some(&SessionIntentType::static_variant_type())) + gio::ActionEntry::builder(SessionIntent::SHOW_MATRIX_ID_ACTION_NAME) + .parameter_type(Some(&SessionIntent::static_variant_type())) .activate(|obj: &super::Application, _, variant| { debug!( - "`app.{}` action activated", - SessionIntentType::ShowMatrixId.action_name() + "`{}` action activated", + SessionIntent::SHOW_MATRIX_ID_APP_ACTION_NAME ); - let Some((session_id, intent)) = variant.and_then(|variant| { - SessionIntent::from_variant_with_session_id( - SessionIntentType::ShowMatrixId, - variant, - ) - }) else { + let Some((session_id, intent)) = + variant.and_then(SessionIntent::show_matrix_id_from_variant) + else { error!( - "Activated `app.{}` action without the proper payload", - SessionIntentType::ShowMatrixId.action_name() + "Activated `{}` action without the proper payload", + SessionIntent::SHOW_MATRIX_ID_APP_ACTION_NAME ); return; }; @@ -208,32 +205,27 @@ mod imp { .build(), // Show an identity verification. This is the action triggered when clicking a // notification about a new verification. - gio::ActionEntry::builder( - SessionIntentType::ShowIdentityVerification.action_name(), - ) - .parameter_type(Some(&SessionIntentType::static_variant_type())) - .activate(|obj: &super::Application, _, variant| { - debug!( - "`app.{}` action activated", - SessionIntentType::ShowIdentityVerification.action_name() - ); - - let Some((session_id, intent)) = variant.and_then(|variant| { - SessionIntent::from_variant_with_session_id( - SessionIntentType::ShowIdentityVerification, - variant, - ) - }) else { - error!( - "Activated `app.{}` action without the proper payload", - SessionIntentType::ShowIdentityVerification.action_name() + gio::ActionEntry::builder(SessionIntent::SHOW_IDENTITY_VERIFICATION_ACTION_NAME) + .parameter_type(Some(&SessionIntent::static_variant_type())) + .activate(|obj: &super::Application, _, variant| { + debug!( + "`{}` action activated", + SessionIntent::SHOW_IDENTITY_VERIFICATION_APP_ACTION_NAME ); - return; - }; - obj.imp().process_session_intent(session_id, intent); - }) - .build(), + let Some((session_id, intent)) = variant + .and_then(SessionIntent::show_identity_verification_from_variant) + else { + error!( + "Activated `{}` action without the proper payload", + SessionIntent::SHOW_IDENTITY_VERIFICATION_APP_ACTION_NAME + ); + return; + }; + + obj.imp().process_session_intent(session_id, intent); + }) + .build(), ]); } diff --git a/src/intent.rs b/src/intent.rs index 1352bae9..4df8be4d 100644 --- a/src/intent.rs +++ b/src/intent.rs @@ -1,7 +1,6 @@ use std::borrow::Cow; use gtk::{glib, prelude::*}; -use ruma::OwnedUserId; use crate::{session::model::VerificationKey, utils::matrix::MatrixIdUri}; @@ -17,44 +16,86 @@ pub(crate) enum SessionIntent { } impl SessionIntent { + /// The application action name for the [`SessionIntent::ShowMatrixId`] + /// variant. + pub(crate) const SHOW_MATRIX_ID_APP_ACTION_NAME: &str = "app.show-matrix-id"; + + /// The action name without the `app.` prefix for the + /// [`SessionIntent::ShowMatrixId`] variant. + pub(crate) const SHOW_MATRIX_ID_ACTION_NAME: &str = + Self::SHOW_MATRIX_ID_APP_ACTION_NAME.split_at(4).1; + + /// The application action name for the + /// [`SessionIntent::ShowIdentityVerification`] variant. + pub(crate) const SHOW_IDENTITY_VERIFICATION_APP_ACTION_NAME: &str = + "app.show-identity-verification"; + + /// The action name without the `app.` prefix for the + /// [`SessionIntent::ShowIdentityVerification`] variant. + pub(crate) const SHOW_IDENTITY_VERIFICATION_ACTION_NAME: &str = + Self::SHOW_IDENTITY_VERIFICATION_APP_ACTION_NAME + .split_at(4) + .1; + /// Get the application action name for this session intent type. pub(crate) fn app_action_name(&self) -> &'static str { match self { - SessionIntent::ShowMatrixId(_) => "app.show-matrix-id", - SessionIntent::ShowIdentityVerification(_) => "app.show-identity-verification", + SessionIntent::ShowMatrixId(_) => Self::SHOW_MATRIX_ID_APP_ACTION_NAME, + SessionIntent::ShowIdentityVerification(_) => { + Self::SHOW_IDENTITY_VERIFICATION_APP_ACTION_NAME + } } } - /// Convert this intent to a `GVariant` with the given session ID. - pub(crate) fn to_variant_with_session_id(&self, session_id: &str) -> glib::Variant { - let payload = match self { - Self::ShowMatrixId(uri) => uri.to_variant(), - Self::ShowIdentityVerification(key) => key.to_variant(), - }; - (session_id, payload).to_variant() + /// Convert the given `GVariant` to a [`SessionIntent::ShowMatrixId`] and + /// session ID, given the intent type. + /// + /// Returns a `(session_id, intent)` tuple on success. Returns `None` if + /// the `GVariant` could not be parsed successfully. + pub(crate) fn show_matrix_id_from_variant(variant: &glib::Variant) -> Option<(String, Self)> { + let SessionIntentActionParameter { + session_id, + payload, + } = variant.get()?; + + Some((session_id, Self::ShowMatrixId(payload.get()?))) } - /// Convert a `GVariant` to a `SessionIntent` and session ID, given the + /// Convert the given `GVariant` to a + /// [`SessionIntent::ShowIdentityVerification`] and session ID, given the /// intent type. /// - /// Returns an `(session_id, intent)` tuple on success. Returns `None` if - /// the payload could not be parsed successfully. - pub(crate) fn from_variant_with_session_id( - intent_type: SessionIntentType, + /// Returns a `(session_id, intent)` tuple on success. Returns `None` if + /// the `GVariant` could not be parsed successfully. + pub(crate) fn show_identity_verification_from_variant( variant: &glib::Variant, ) -> Option<(String, Self)> { - let (session_id, payload) = variant.get::<(String, glib::Variant)>()?; - - let intent = match intent_type { - SessionIntentType::ShowMatrixId => Self::ShowMatrixId(payload.get::()?), - SessionIntentType::ShowIdentityVerification => { - let (user_id_str, flow_id) = payload.get::<(String, String)>()?; - let user_id = OwnedUserId::try_from(user_id_str).ok()?; - Self::ShowIdentityVerification(VerificationKey { user_id, flow_id }) - } + let SessionIntentActionParameter { + session_id, + payload, + } = variant.get()?; + + Some((session_id, Self::ShowIdentityVerification(payload.get()?))) + } + + /// Convert this intent to a `GVariant` with the given session ID. + pub(crate) fn to_variant_with_session_id(&self, session_id: String) -> glib::Variant { + let payload = match self { + Self::ShowMatrixId(uri) => uri.to_variant(), + Self::ShowIdentityVerification(key) => key.to_variant(), }; - Some((session_id, intent)) + SessionIntentActionParameter { + session_id, + payload, + } + .to_variant() + } +} + +impl StaticVariantType for SessionIntent { + fn static_variant_type() -> Cow<'static, glib::VariantTy> { + SessionIntentActionParameter::static_variant_type() } } @@ -70,27 +111,12 @@ impl From for SessionIntent { } } -/// The type of an intent that can be handled by a session. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub(crate) enum SessionIntentType { - /// Show the target of a Matrix ID URI. - ShowMatrixId, - /// Show an ongoing identity verification. - ShowIdentityVerification, -} - -impl SessionIntentType { - /// Get the action name for this session intent type. - pub(crate) fn action_name(self) -> &'static str { - match self { - SessionIntentType::ShowMatrixId => "show-matrix-id", - SessionIntentType::ShowIdentityVerification => "show-identity-verification", - } - } -} - -impl StaticVariantType for SessionIntentType { - fn static_variant_type() -> Cow<'static, glib::VariantTy> { - <(String, glib::Variant)>::static_variant_type() - } +/// The payload of a [`SessionIntent`], when converted to a `GVariant` for an +/// app action. +#[derive(Debug, Clone, glib::Variant)] +struct SessionIntentActionParameter { + /// The ID of the session that should handle the intent. + session_id: String, + /// The payload of the intent. + payload: glib::Variant, } diff --git a/src/session/model/notifications/mod.rs b/src/session/model/notifications/mod.rs index 60a8ef09..2091c487 100644 --- a/src/session/model/notifications/mod.rs +++ b/src/session/model/notifications/mod.rs @@ -135,7 +135,7 @@ impl Notifications { notification.set_body(Some(&body)); let action = intent.app_action_name(); - let target_value = intent.to_variant_with_session_id(session_id); + let target_value = intent.to_variant_with_session_id(session_id.to_owned()); notification.set_default_action_and_target_value(action, Some(&target_value)); if let Some(notification_icon) = icon {