mirror of
https://github.com/matrix-org/matrix-rust-sdk.git
synced 2026-05-18 13:40:55 -04:00
feat(crypto): Add method to format emojis
This patch adds a method to format a list of emojis in a a terminal friendly way. This method was borrowed from weechat-matrix but it's also quite useful in our own emoji verification example.
This commit is contained in:
@@ -87,7 +87,9 @@ pub use requests::{
|
||||
OutgoingVerificationRequest, RoomMessageRequest, ToDeviceRequest, UploadSigningKeysRequest,
|
||||
};
|
||||
pub use store::{CrossSigningKeyExport, CryptoStoreError, SecretImportError, SecretInfo};
|
||||
pub use verification::{AcceptSettings, CancelInfo, Emoji, Sas, Verification, VerificationRequest};
|
||||
pub use verification::{
|
||||
format_emojis, AcceptSettings, CancelInfo, Emoji, Sas, Verification, VerificationRequest,
|
||||
};
|
||||
#[cfg(feature = "qrcode")]
|
||||
pub use verification::{QrVerification, ScanError};
|
||||
|
||||
|
||||
@@ -83,6 +83,43 @@ pub struct Emoji {
|
||||
pub description: &'static str,
|
||||
}
|
||||
|
||||
/// Format the the list of emojis as a two line string.
|
||||
///
|
||||
/// The first line will contain the emojis spread out so the second line can
|
||||
/// contain the descriptions centered bellow the emoji.
|
||||
pub fn format_emojis(emojis: [Emoji; 7]) -> String {
|
||||
let (emojis, descriptions): (Vec<_>, Vec<_>) =
|
||||
emojis.iter().map(|e| (e.symbol, e.description)).unzip();
|
||||
|
||||
let center_emoji = |emoji: &str| -> String {
|
||||
const EMOJI_WIDTH: usize = 2;
|
||||
// These are emojis that need VARIATION-SELECTOR-16 (U+FE0F) so that they are
|
||||
// rendered with coloured glyphs. For these, we need to add an extra
|
||||
// space after them so that they are rendered properly in terminals.
|
||||
const VARIATION_SELECTOR_EMOJIS: [&str; 7] = ["☁️", "❤️", "☂️", "✏️", "✂️", "☎️", "✈️"];
|
||||
|
||||
// Hack to make terminals behave properly when one of the above is printed.
|
||||
let emoji = if VARIATION_SELECTOR_EMOJIS.contains(&emoji) {
|
||||
format!("{} ", emoji)
|
||||
} else {
|
||||
emoji.to_owned()
|
||||
};
|
||||
|
||||
// This is a trick to account for the fact that emojis are wider than other
|
||||
// monospace characters.
|
||||
let placeholder = ".".repeat(EMOJI_WIDTH);
|
||||
|
||||
format!("{:^12}", placeholder).replace(&placeholder, &emoji)
|
||||
};
|
||||
|
||||
let emoji_string = emojis.iter().map(|e| center_emoji(e)).collect::<Vec<_>>().join("");
|
||||
|
||||
let description =
|
||||
descriptions.iter().map(|d| format!("{:^12}", d)).collect::<Vec<_>>().join("");
|
||||
|
||||
format!("{emoji_string}\n{description}")
|
||||
}
|
||||
|
||||
impl VerificationStore {
|
||||
pub async fn get_device(
|
||||
&self,
|
||||
|
||||
@@ -32,9 +32,9 @@ use crate::{
|
||||
identities::{ReadOnlyDevice, ReadOnlyUserIdentities},
|
||||
verification::{
|
||||
event_enums::{AnyVerificationContent, OutgoingContent, OwnedAcceptContent, StartContent},
|
||||
Cancelled,
|
||||
Cancelled, Emoji,
|
||||
},
|
||||
Emoji, ReadOnlyAccount, ReadOnlyOwnUserIdentity,
|
||||
ReadOnlyAccount, ReadOnlyOwnUserIdentity,
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
||||
@@ -61,9 +61,9 @@ use crate::{
|
||||
AcceptContent, DoneContent, KeyContent, MacContent, OwnedAcceptContent,
|
||||
OwnedStartContent, StartContent,
|
||||
},
|
||||
Cancelled, FlowId,
|
||||
Cancelled, Emoji, FlowId,
|
||||
},
|
||||
Emoji, ReadOnlyAccount, ReadOnlyOwnUserIdentity,
|
||||
ReadOnlyAccount, ReadOnlyOwnUserIdentity,
|
||||
};
|
||||
|
||||
const KEY_AGREEMENT_PROTOCOLS: &[KeyAgreementProtocol] =
|
||||
|
||||
@@ -35,9 +35,9 @@ mod qrcode;
|
||||
mod requests;
|
||||
mod sas;
|
||||
|
||||
pub use matrix_sdk_base::crypto::{format_emojis, AcceptSettings, CancelInfo, Emoji};
|
||||
#[cfg(feature = "qrcode")]
|
||||
pub use matrix_sdk_base::crypto::{matrix_sdk_qrcode::QrVerificationData, ScanError};
|
||||
pub use matrix_sdk_base::crypto::{AcceptSettings, CancelInfo, Emoji};
|
||||
#[cfg(feature = "qrcode")]
|
||||
pub use qrcode::QrVerification;
|
||||
pub use requests::VerificationRequest;
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use matrix_sdk_base::crypto::{AcceptSettings, CancelInfo, ReadOnlyDevice, Sas as BaseSas};
|
||||
use matrix_sdk_base::crypto::{AcceptSettings, CancelInfo, Emoji, ReadOnlyDevice, Sas as BaseSas};
|
||||
use ruma::{events::key::verification::cancel::CancelCode, UserId};
|
||||
|
||||
use crate::{error::Result, Client};
|
||||
@@ -151,7 +151,7 @@ impl SasVerification {
|
||||
/// }
|
||||
/// # anyhow::Ok(()) });
|
||||
/// ```
|
||||
pub fn emoji(&self) -> Option<[super::Emoji; 7]> {
|
||||
pub fn emoji(&self) -> Option<[Emoji; 7]> {
|
||||
self.inner.emoji()
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use std::{
|
||||
io,
|
||||
io::{self, Write},
|
||||
sync::{
|
||||
atomic::{AtomicBool, Ordering},
|
||||
Arc,
|
||||
@@ -11,7 +11,7 @@ use clap::Parser;
|
||||
use matrix_sdk::{
|
||||
self,
|
||||
config::SyncSettings,
|
||||
encryption::verification::{SasVerification, Verification},
|
||||
encryption::verification::{format_emojis, SasVerification, Verification},
|
||||
ruma::{
|
||||
events::{
|
||||
room::message::MessageType, AnySyncMessageLikeEvent, AnySyncTimelineEvent,
|
||||
@@ -25,9 +25,10 @@ use url::Url;
|
||||
|
||||
async fn wait_for_confirmation(client: Client, sas: SasVerification) {
|
||||
let emoji = sas.emoji().expect("The emoji should be available now");
|
||||
let emoji: Vec<&str> = emoji.iter().map(|e| e.symbol).collect();
|
||||
|
||||
println!("Does the emoji match: {:?}", emoji);
|
||||
println!("\nDo the emojis match: \n{}", format_emojis(emoji));
|
||||
print!("Confirm with `yes` or cancel with `no`: ");
|
||||
std::io::stdout().flush().expect("We should be able to flush stdout");
|
||||
|
||||
let mut input = String::new();
|
||||
io::stdin().read_line(&mut input).expect("error: unable to read user input");
|
||||
|
||||
Reference in New Issue
Block a user