Compare commits

...
Author SHA1 Message Date
Septias 1d8e969b34 use future and result 2024-11-11 00:35:26 +01:00
Septias f4d1298669 feat: add device message for imported contacts after configuration
Add a short info message about how many contacts were added during
configuration.
2024-11-11 00:26:26 +01:00
Sebastian Klähn 6b2d49acb8 Copy over some docs as requested in the associated issue. (#6193)
Copy over some docs as requested in the associated issue.

close #5503
2024-11-10 23:30:43 +01:00
3 changed files with 117 additions and 25 deletions
+84 -11
View File
@@ -6,87 +6,161 @@ use typescript_type_def::TypeDef;
#[serde(rename = "Qr", rename_all = "camelCase")]
#[serde(tag = "kind")]
pub enum QrObject {
/// Ask the user whether to verify the contact.
///
/// If the user agrees, pass this QR code to [`crate::securejoin::join_securejoin`].
AskVerifyContact {
/// ID of the contact.
contact_id: u32,
/// Fingerprint of the contact key as scanned from the QR code.
fingerprint: String,
/// Invite number.
invitenumber: String,
/// Authentication code.
authcode: String,
},
/// Ask the user whether to join the group.
AskVerifyGroup {
/// Group name.
grpname: String,
/// Group ID.
grpid: String,
/// ID of the contact.
contact_id: u32,
/// Fingerprint of the contact key as scanned from the QR code.
fingerprint: String,
/// Invite number.
invitenumber: String,
/// Authentication code.
authcode: String,
},
/// Contact fingerprint is verified.
///
/// Ask the user if they want to start chatting.
FprOk {
/// Contact ID.
contact_id: u32,
},
/// Scanned fingerprint does not match the last seen fingerprint.
FprMismatch {
/// Contact ID.
contact_id: Option<u32>,
},
/// The scanned QR code contains a fingerprint but no e-mail address.
FprWithoutAddr {
/// Key fingerprint.
fingerprint: String,
},
/// Ask the user if they want to create an account on the given domain.
Account {
/// Server domain name.
domain: String,
},
/// Provides a backup that can be retrieved using iroh-net based backup transfer protocol.
Backup2 {
/// Authentication token.
auth_token: String,
/// Iroh node address.
node_addr: String,
},
/// Ask the user if they want to use the given service for video chats.
WebrtcInstance {
domain: String,
instance_pattern: String,
},
/// Ask the user if they want to use the given proxy.
///
/// Note that HTTP(S) URLs without a path
/// and query parameters are treated as HTTP(S) proxy URL.
/// UI may want to still offer to open the URL
/// in the browser if QR code contents
/// starts with `http://` or `https://`
/// and the QR code was not scanned from
/// the proxy configuration screen.
Proxy {
/// Proxy URL.
///
/// This is the URL that is going to be added.
url: String,
/// Host extracted from the URL to display in the UI.
host: String,
/// Port extracted from the URL to display in the UI.
port: u16,
},
/// Contact address is scanned.
///
/// Optionally, a draft message could be provided.
/// Ask the user if they want to start chatting.
Addr {
/// Contact ID.
contact_id: u32,
/// Draft message.
draft: Option<String>,
},
Url {
url: String,
},
Text {
text: String,
},
/// URL scanned.
///
/// Ask the user if they want to open a browser or copy the URL to clipboard.
Url { url: String },
/// Text scanned.
///
/// Ask the user if they want to copy the text to clipboard.
Text { text: String },
/// Ask the user if they want to withdraw their own QR code.
WithdrawVerifyContact {
/// Contact ID.
contact_id: u32,
/// Fingerprint of the contact key as scanned from the QR code.
fingerprint: String,
/// Invite number.
invitenumber: String,
/// Authentication code.
authcode: String,
},
/// Ask the user if they want to withdraw their own group invite QR code.
WithdrawVerifyGroup {
/// Group name.
grpname: String,
/// Group ID.
grpid: String,
/// Contact ID.
contact_id: u32,
/// Fingerprint of the contact key as scanned from the QR code.
fingerprint: String,
/// Invite number.
invitenumber: String,
/// Authentication code.
authcode: String,
},
/// Ask the user if they want to revive their own QR code.
ReviveVerifyContact {
/// Contact ID.
contact_id: u32,
/// Fingerprint of the contact key as scanned from the QR code.
fingerprint: String,
/// Invite number.
invitenumber: String,
/// Authentication code.
authcode: String,
},
/// Ask the user if they want to revive their own group invite QR code.
ReviveVerifyGroup {
/// Contact ID.
grpname: String,
/// Group ID.
grpid: String,
/// Contact ID.
contact_id: u32,
/// Fingerprint of the contact key as scanned from the QR code.
fingerprint: String,
/// Invite number.
invitenumber: String,
/// Authentication code.
authcode: String,
},
Login {
address: String,
},
/// `dclogin:` scheme parameters.
///
/// Ask the user if they want to login with the email address.
Login { address: String },
}
impl From<Qr> for QrObject {
@@ -141,7 +215,6 @@ impl From<Qr> for QrObject {
auth_token,
} => QrObject::Backup2 {
node_addr: serde_json::to_string(node_addr).unwrap_or_default(),
auth_token,
},
Qr::WebrtcInstance {
+19 -10
View File
@@ -768,14 +768,16 @@ impl Imap {
&mut self,
context: &Context,
session: &mut Session,
) -> Result<()> {
add_all_recipients_as_contacts(context, session, Config::ConfiguredSentboxFolder)
.await
.context("failed to get recipients from the sentbox")?;
add_all_recipients_as_contacts(context, session, Config::ConfiguredMvboxFolder)
) -> Result<i32> {
let mut created = 0;
created +=
add_all_recipients_as_contacts(context, session, Config::ConfiguredSentboxFolder)
.await
.context("failed to get recipients from the sentbox")?;
created += add_all_recipients_as_contacts(context, session, Config::ConfiguredMvboxFolder)
.await
.context("failed to get recipients from the movebox")?;
add_all_recipients_as_contacts(context, session, Config::ConfiguredInboxFolder)
created += add_all_recipients_as_contacts(context, session, Config::ConfiguredInboxFolder)
.await
.context("failed to get recipients from the inbox")?;
@@ -802,7 +804,7 @@ impl Imap {
}
info!(context, "Done fetching existing messages.");
Ok(())
Ok(created)
}
}
@@ -2479,11 +2481,14 @@ impl std::fmt::Display for UidRange {
}
}
}
/// Add all recipients as contacts.
/// Returns how many contacts were created.
async fn add_all_recipients_as_contacts(
context: &Context,
session: &mut Session,
folder: Config,
) -> Result<()> {
) -> Result<i32> {
let mailbox = if let Some(m) = context.get_config(folder).await? {
m
} else {
@@ -2491,7 +2496,7 @@ async fn add_all_recipients_as_contacts(
context,
"Folder {} is not configured, skipping fetching contacts from it.", folder
);
return Ok(());
return Ok(0);
};
session
.select_with_uidvalidity(context, &mailbox)
@@ -2504,6 +2509,7 @@ async fn add_all_recipients_as_contacts(
.context("could not get recipients")?;
let mut any_modified = false;
let mut created = 0;
for recipient in recipients {
let recipient_addr = match ContactAddress::new(&recipient.addr) {
Err(err) => {
@@ -2528,12 +2534,15 @@ async fn add_all_recipients_as_contacts(
if modified != Modifier::None {
any_modified = true;
}
if modified == Modifier::Created {
created += 1;
}
}
if any_modified {
context.emit_event(EventType::ContactsChanged(None));
}
Ok(())
Ok(created)
}
#[cfg(test)]
+14 -4
View File
@@ -19,12 +19,12 @@ use crate::download::{download_msg, DownloadState};
use crate::ephemeral::{self, delete_expired_imap_messages};
use crate::events::EventType;
use crate::imap::{session::Session, FolderMeaning, Imap};
use crate::location;
use crate::log::LogExt;
use crate::message::MsgId;
use crate::message::{Message, MsgId};
use crate::smtp::{send_smtp_messages, Smtp};
use crate::sql;
use crate::tools::{self, duration_to_str, maybe_add_time_based_warnings, time, time_elapsed};
use crate::{chat, location};
pub(crate) mod connectivity;
@@ -514,8 +514,18 @@ async fn inbox_fetch_idle(ctx: &Context, imap: &mut Imap, mut session: Session)
warn!(ctx, "Can't set Config::FetchedExistingMsgs: {:#}", err);
}
if let Err(err) = imap.fetch_existing_msgs(ctx, &mut session).await {
warn!(ctx, "Failed to fetch existing messages: {:#}", err);
match imap.fetch_existing_msgs(ctx, &mut session).await {
Err(err) => {
warn!(ctx, "Failed to fetch existing messages: {:#}", err);
}
Ok(count) => {
let mut msg = Message::new_text(format!(
"Added {} contacts from outgoing chats",
count
));
chat::add_device_msg(ctx, None, Some(&mut msg)).await?;
}
}
}
}