mirror of
https://github.com/chatmail/core.git
synced 2026-05-08 17:36:29 +03:00
feat: Add strings 'You left the channel.' and 'Scan to join Channel' (#7266)
Close https://github.com/chatmail/core/issues/7233 Part of https://github.com/chatmail/core/issues/6884
This commit is contained in:
14
src/chat.rs
14
src/chat.rs
@@ -4207,7 +4207,7 @@ pub async fn remove_contact_from_chat(
|
|||||||
if chat.typ == Chattype::Group && chat.is_promoted() {
|
if chat.typ == Chattype::Group && chat.is_promoted() {
|
||||||
let addr = contact.get_addr();
|
let addr = contact.get_addr();
|
||||||
|
|
||||||
let res = send_member_removal_msg(context, chat_id, contact_id, addr).await;
|
let res = send_member_removal_msg(context, &chat, contact_id, addr).await;
|
||||||
|
|
||||||
if contact_id == ContactId::SELF {
|
if contact_id == ContactId::SELF {
|
||||||
res?;
|
res?;
|
||||||
@@ -4231,7 +4231,7 @@ pub async fn remove_contact_from_chat(
|
|||||||
// For incoming broadcast channels, it's not possible to remove members,
|
// For incoming broadcast channels, it's not possible to remove members,
|
||||||
// but it's possible to leave:
|
// but it's possible to leave:
|
||||||
let self_addr = context.get_primary_self_addr().await?;
|
let self_addr = context.get_primary_self_addr().await?;
|
||||||
send_member_removal_msg(context, chat_id, contact_id, &self_addr).await?;
|
send_member_removal_msg(context, &chat, contact_id, &self_addr).await?;
|
||||||
} else {
|
} else {
|
||||||
bail!("Cannot remove members from non-group chats.");
|
bail!("Cannot remove members from non-group chats.");
|
||||||
}
|
}
|
||||||
@@ -4241,14 +4241,18 @@ pub async fn remove_contact_from_chat(
|
|||||||
|
|
||||||
async fn send_member_removal_msg(
|
async fn send_member_removal_msg(
|
||||||
context: &Context,
|
context: &Context,
|
||||||
chat_id: ChatId,
|
chat: &Chat,
|
||||||
contact_id: ContactId,
|
contact_id: ContactId,
|
||||||
addr: &str,
|
addr: &str,
|
||||||
) -> Result<MsgId> {
|
) -> Result<MsgId> {
|
||||||
let mut msg = Message::new(Viewtype::Text);
|
let mut msg = Message::new(Viewtype::Text);
|
||||||
|
|
||||||
if contact_id == ContactId::SELF {
|
if contact_id == ContactId::SELF {
|
||||||
msg.text = stock_str::msg_group_left_local(context, ContactId::SELF).await;
|
if chat.typ == Chattype::InBroadcast {
|
||||||
|
msg.text = stock_str::msg_you_left_broadcast(context).await;
|
||||||
|
} else {
|
||||||
|
msg.text = stock_str::msg_group_left_local(context, ContactId::SELF).await;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
msg.text = stock_str::msg_del_member_local(context, contact_id, ContactId::SELF).await;
|
msg.text = stock_str::msg_del_member_local(context, contact_id, ContactId::SELF).await;
|
||||||
}
|
}
|
||||||
@@ -4258,7 +4262,7 @@ async fn send_member_removal_msg(
|
|||||||
msg.param
|
msg.param
|
||||||
.set(Param::ContactAddedRemoved, contact_id.to_u32());
|
.set(Param::ContactAddedRemoved, contact_id.to_u32());
|
||||||
|
|
||||||
send_msg(context, chat_id, &mut msg).await
|
send_msg(context, chat.id, &mut msg).await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn set_group_explicitly_left(context: &Context, grpid: &str) -> Result<()> {
|
async fn set_group_explicitly_left(context: &Context, grpid: &str) -> Result<()> {
|
||||||
|
|||||||
@@ -3026,7 +3026,7 @@ async fn test_leave_broadcast() -> Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Tests that if Bob leaves a broadcast channel with one device,
|
/// Tests that if Bob leaves a broadcast channel with one device,
|
||||||
/// the other device shows a correct info message "You left.".
|
/// the other device shows a correct info message "You left the channel.".
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||||
async fn test_leave_broadcast_multidevice() -> Result<()> {
|
async fn test_leave_broadcast_multidevice() -> Result<()> {
|
||||||
let mut tcm = TestContextManager::new();
|
let mut tcm = TestContextManager::new();
|
||||||
@@ -3061,10 +3061,7 @@ async fn test_leave_broadcast_multidevice() -> Result<()> {
|
|||||||
assert_eq!(rcvd.chat_id, bob1_hello.chat_id);
|
assert_eq!(rcvd.chat_id, bob1_hello.chat_id);
|
||||||
assert!(rcvd.is_info());
|
assert!(rcvd.is_info());
|
||||||
assert_eq!(rcvd.get_info_type(), SystemMessage::MemberRemovedFromGroup);
|
assert_eq!(rcvd.get_info_type(), SystemMessage::MemberRemovedFromGroup);
|
||||||
assert_eq!(
|
assert_eq!(rcvd.text, stock_str::msg_you_left_broadcast(bob1).await);
|
||||||
rcvd.text,
|
|
||||||
stock_str::msg_group_left_local(bob1, ContactId::SELF).await
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
//! # QR code generation module.
|
//! # QR code generation module.
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::{Result, bail};
|
||||||
use base64::Engine as _;
|
use base64::Engine as _;
|
||||||
use qrcodegen::{QrCode, QrCodeEcc};
|
use qrcodegen::{QrCode, QrCodeEcc};
|
||||||
|
|
||||||
@@ -108,8 +108,18 @@ async fn generate_join_group_qr_code(context: &Context, chat_id: ChatId) -> Resu
|
|||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let qrcode_description = match chat.typ {
|
||||||
|
crate::constants::Chattype::Group => {
|
||||||
|
stock_str::secure_join_group_qr_description(context, &chat).await
|
||||||
|
}
|
||||||
|
crate::constants::Chattype::OutBroadcast => {
|
||||||
|
stock_str::secure_join_broadcast_qr_description(context, &chat).await
|
||||||
|
}
|
||||||
|
_ => bail!("Unexpected chat type {}", chat.typ),
|
||||||
|
};
|
||||||
|
|
||||||
inner_generate_secure_join_qr_code(
|
inner_generate_secure_join_qr_code(
|
||||||
&stock_str::secure_join_group_qr_description(context, &chat).await,
|
&qrcode_description,
|
||||||
&securejoin::get_securejoin_qr(context, Some(chat_id)).await?,
|
&securejoin::get_securejoin_qr(context, Some(chat_id)).await?,
|
||||||
&color_int_to_hex_string(chat.get_color(context).await?),
|
&color_int_to_hex_string(chat.get_color(context).await?),
|
||||||
avatar,
|
avatar,
|
||||||
|
|||||||
@@ -3532,8 +3532,7 @@ async fn apply_in_broadcast_changes(
|
|||||||
// The only member added/removed message that is ever sent is "I left.",
|
// The only member added/removed message that is ever sent is "I left.",
|
||||||
// so, this is the only case we need to handle here
|
// so, this is the only case we need to handle here
|
||||||
if from_id == ContactId::SELF {
|
if from_id == ContactId::SELF {
|
||||||
better_msg
|
better_msg.get_or_insert(stock_str::msg_you_left_broadcast(context).await);
|
||||||
.get_or_insert(stock_str::msg_group_left_local(context, ContactId::SELF).await);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -279,7 +279,7 @@ pub enum StockMessage {
|
|||||||
#[strum(props(fallback = "Member %1$s removed by %2$s."))]
|
#[strum(props(fallback = "Member %1$s removed by %2$s."))]
|
||||||
MsgDelMemberBy = 131,
|
MsgDelMemberBy = 131,
|
||||||
|
|
||||||
#[strum(props(fallback = "You left."))]
|
#[strum(props(fallback = "You left the group."))]
|
||||||
MsgYouLeftGroup = 132,
|
MsgYouLeftGroup = 132,
|
||||||
|
|
||||||
#[strum(props(fallback = "Group left by %1$s."))]
|
#[strum(props(fallback = "Group left by %1$s."))]
|
||||||
@@ -439,6 +439,12 @@ https://delta.chat/donate"))]
|
|||||||
|
|
||||||
#[strum(props(fallback = "Missed Call"))]
|
#[strum(props(fallback = "Missed Call"))]
|
||||||
MissedCall = 198,
|
MissedCall = 198,
|
||||||
|
|
||||||
|
#[strum(props(fallback = "You left the channel."))]
|
||||||
|
MsgYouLeftBroadcast = 200,
|
||||||
|
|
||||||
|
#[strum(props(fallback = "Scan to join channel %1$s"))]
|
||||||
|
SecureJoinBrodcastQRDescription = 201,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StockMessage {
|
impl StockMessage {
|
||||||
@@ -711,7 +717,7 @@ pub(crate) async fn msg_group_left_remote(context: &Context) -> String {
|
|||||||
translated(context, StockMessage::MsgILeftGroup).await
|
translated(context, StockMessage::MsgILeftGroup).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Stock string: `You left.` or `Group left by %1$s.`.
|
/// Stock string: `You left the group.` or `Group left by %1$s.`.
|
||||||
pub(crate) async fn msg_group_left_local(context: &Context, by_contact: ContactId) -> String {
|
pub(crate) async fn msg_group_left_local(context: &Context, by_contact: ContactId) -> String {
|
||||||
if by_contact == ContactId::SELF {
|
if by_contact == ContactId::SELF {
|
||||||
translated(context, StockMessage::MsgYouLeftGroup).await
|
translated(context, StockMessage::MsgYouLeftGroup).await
|
||||||
@@ -722,6 +728,11 @@ pub(crate) async fn msg_group_left_local(context: &Context, by_contact: ContactI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Stock string: `You left the channel.`
|
||||||
|
pub(crate) async fn msg_you_left_broadcast(context: &Context) -> String {
|
||||||
|
translated(context, StockMessage::MsgYouLeftBroadcast).await
|
||||||
|
}
|
||||||
|
|
||||||
/// Stock string: `You reacted %1$s to "%2$s"` or `%1$s reacted %2$s to "%3$s"`.
|
/// Stock string: `You reacted %1$s to "%2$s"` or `%1$s reacted %2$s to "%3$s"`.
|
||||||
pub(crate) async fn msg_reacted(
|
pub(crate) async fn msg_reacted(
|
||||||
context: &Context,
|
context: &Context,
|
||||||
@@ -857,13 +868,20 @@ pub(crate) async fn setup_contact_qr_description(
|
|||||||
.replace1(&name)
|
.replace1(&name)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Stock string: `Scan to join %1$s`.
|
/// Stock string: `Scan to join group %1$s`.
|
||||||
pub(crate) async fn secure_join_group_qr_description(context: &Context, chat: &Chat) -> String {
|
pub(crate) async fn secure_join_group_qr_description(context: &Context, chat: &Chat) -> String {
|
||||||
translated(context, StockMessage::SecureJoinGroupQRDescription)
|
translated(context, StockMessage::SecureJoinGroupQRDescription)
|
||||||
.await
|
.await
|
||||||
.replace1(chat.get_name())
|
.replace1(chat.get_name())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Stock string: `Scan to join channel %1$s`.
|
||||||
|
pub(crate) async fn secure_join_broadcast_qr_description(context: &Context, chat: &Chat) -> String {
|
||||||
|
translated(context, StockMessage::SecureJoinBrodcastQRDescription)
|
||||||
|
.await
|
||||||
|
.replace1(chat.get_name())
|
||||||
|
}
|
||||||
|
|
||||||
/// Stock string: `%1$s verified.`.
|
/// Stock string: `%1$s verified.`.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub(crate) async fn contact_verified(context: &Context, contact: &Contact) -> String {
|
pub(crate) async fn contact_verified(context: &Context, contact: &Contact) -> String {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ Group#Chat#10: Group chat [3 member(s)]
|
|||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
Msg#10: info (Contact#Contact#Info): Messages are end-to-end encrypted. [NOTICED][INFO]
|
Msg#10: info (Contact#Contact#Info): Messages are end-to-end encrypted. [NOTICED][INFO]
|
||||||
Msg#11🔒: (Contact#Contact#10): Hi! I created a group. [FRESH]
|
Msg#11🔒: (Contact#Contact#10): Hi! I created a group. [FRESH]
|
||||||
Msg#12🔒: Me (Contact#Contact#Self): You left. [INFO] √
|
Msg#12🔒: Me (Contact#Contact#Self): You left the group. [INFO] √
|
||||||
Msg#13🔒: (Contact#Contact#10): Member charlie@example.net added by alice@example.org. [FRESH][INFO]
|
Msg#13🔒: (Contact#Contact#10): Member charlie@example.net added by alice@example.org. [FRESH][INFO]
|
||||||
Msg#14🔒: (Contact#Contact#10): What a silence! [FRESH]
|
Msg#14🔒: (Contact#Contact#10): What a silence! [FRESH]
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user