deltachat/
constants.rs

1//! # Constants.
2
3#![allow(missing_docs)]
4
5use std::sync::LazyLock;
6
7use deltachat_derive::{FromSql, ToSql};
8use percent_encoding::{AsciiSet, NON_ALPHANUMERIC};
9use serde::{Deserialize, Serialize};
10
11use crate::chat::ChatId;
12
13pub static DC_VERSION_STR: LazyLock<String> =
14    LazyLock::new(|| env!("CARGO_PKG_VERSION").to_string());
15
16/// Set of characters to percent-encode in email addresses and names.
17pub(crate) const NON_ALPHANUMERIC_WITHOUT_DOT: &AsciiSet = &NON_ALPHANUMERIC.remove(b'.');
18
19#[derive(
20    Debug,
21    Default,
22    Display,
23    Clone,
24    Copy,
25    PartialEq,
26    Eq,
27    FromPrimitive,
28    ToPrimitive,
29    FromSql,
30    ToSql,
31    Serialize,
32    Deserialize,
33)]
34#[repr(i8)]
35pub enum Blocked {
36    #[default]
37    Not = 0,
38    Yes = 1,
39    Request = 2,
40}
41
42#[derive(
43    Debug, Default, Display, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive, FromSql, ToSql,
44)]
45#[repr(u8)]
46pub enum ShowEmails {
47    Off = 0,
48    AcceptedContacts = 1,
49    #[default] // also change Config.ShowEmails props(default) on changes
50    All = 2,
51}
52
53#[derive(
54    Debug, Default, Display, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive, FromSql, ToSql,
55)]
56#[repr(u8)]
57pub enum MediaQuality {
58    #[default] // also change Config.MediaQuality props(default) on changes
59    Balanced = 0,
60    Worse = 1,
61}
62
63/// Video chat URL type.
64#[derive(
65    Debug, Default, Display, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive, FromSql, ToSql,
66)]
67#[repr(i8)]
68pub enum VideochatType {
69    /// Unknown type.
70    #[default]
71    Unknown = 0,
72
73    /// [basicWebRTC](https://github.com/cracker0dks/basicwebrtc) instance.
74    BasicWebrtc = 1,
75
76    /// [Jitsi Meet](https://jitsi.org/jitsi-meet/) instance.
77    Jitsi = 2,
78}
79
80pub const DC_HANDSHAKE_CONTINUE_NORMAL_PROCESSING: i32 = 0x01;
81pub const DC_HANDSHAKE_STOP_NORMAL_PROCESSING: i32 = 0x02;
82pub const DC_HANDSHAKE_ADD_DELETE_JOB: i32 = 0x04;
83
84pub(crate) const DC_FROM_HANDSHAKE: i32 = 0x01;
85
86pub const DC_GCL_ARCHIVED_ONLY: usize = 0x01;
87pub const DC_GCL_NO_SPECIALS: usize = 0x02;
88pub const DC_GCL_ADD_ALLDONE_HINT: usize = 0x04;
89pub const DC_GCL_FOR_FORWARDING: usize = 0x08;
90
91pub const DC_GCL_ADD_SELF: u32 = 0x02;
92pub const DC_GCL_ADDRESS: u32 = 0x04;
93
94// unchanged user avatars are resent to the recipients every some days
95pub(crate) const DC_RESEND_USER_AVATAR_DAYS: i64 = 14;
96
97// warn about an outdated app after a given number of days.
98// as we use the "provider-db generation date" as reference (that might not be updated very often)
99// and as not all system get speedy updates,
100// do not use too small value that will annoy users checking for nonexistent updates.
101pub(crate) const DC_OUTDATED_WARNING_DAYS: i64 = 365;
102
103/// messages that should be deleted get this chat_id; the messages are deleted from the working thread later then. This is also needed as rfc724_mid should be preset as long as the message is not deleted on the server (otherwise it is downloaded again)
104pub const DC_CHAT_ID_TRASH: ChatId = ChatId::new(3);
105/// only an indicator in a chatlist
106pub const DC_CHAT_ID_ARCHIVED_LINK: ChatId = ChatId::new(6);
107/// only an indicator in a chatlist
108pub const DC_CHAT_ID_ALLDONE_HINT: ChatId = ChatId::new(7);
109/// larger chat IDs are "real" chats, their messages are "real" messages.
110pub const DC_CHAT_ID_LAST_SPECIAL: ChatId = ChatId::new(9);
111
112/// Chat type.
113#[derive(
114    Debug,
115    Display,
116    Clone,
117    Copy,
118    PartialEq,
119    Eq,
120    FromPrimitive,
121    ToPrimitive,
122    FromSql,
123    ToSql,
124    IntoStaticStr,
125    Serialize,
126    Deserialize,
127)]
128#[repr(u32)]
129pub enum Chattype {
130    /// A 1:1 chat, i.e. a normal chat with a single contact.
131    ///
132    /// Created by [`ChatId::create_for_contact`].
133    Single = 100,
134
135    /// Group chat.
136    ///
137    /// Created by [`crate::chat::create_group_chat`].
138    Group = 120,
139
140    /// An (unencrypted) mailing list,
141    /// created by an incoming mailing list email.
142    Mailinglist = 140,
143
144    /// Outgoing broadcast channel, called "Channel" in the UI.
145    ///
146    /// The user can send into this chat,
147    /// and all recipients will receive messages
148    /// in an `InBroadcast`.
149    ///
150    /// Called `broadcast` here rather than `channel`,
151    /// because the word "channel" already appears a lot in the code,
152    /// which would make it hard to grep for it.
153    ///
154    /// Created by [`crate::chat::create_broadcast`].
155    OutBroadcast = 160,
156
157    /// Incoming broadcast channel, called "Channel" in the UI.
158    ///
159    /// This chat is read-only,
160    /// and we do not know who the other recipients are.
161    ///
162    /// This is similar to a `MailingList`,
163    /// with the main difference being that
164    /// `InBroadcast`s are encrypted.
165    ///
166    /// Called `broadcast` here rather than `channel`,
167    /// because the word "channel" already appears a lot in the code,
168    /// which would make it hard to grep for it.
169    InBroadcast = 165,
170}
171
172pub const DC_MSG_ID_DAYMARKER: u32 = 9;
173pub const DC_MSG_ID_LAST_SPECIAL: u32 = 9;
174
175/// String that indicates that something is left out or truncated.
176pub(crate) const DC_ELLIPSIS: &str = "[...]";
177// how many lines desktop can display when fullscreen (fullscreen at zoomlevel 1x)
178// (taken from "subjective" testing what looks ok)
179pub const DC_DESIRED_TEXT_LINES: usize = 38;
180// how many chars desktop can display per line (from "subjective" testing)
181pub const DC_DESIRED_TEXT_LINE_LEN: usize = 100;
182
183/// Message length limit.
184///
185/// To keep bubbles and chat flow usable and to avoid problems with controls using very long texts,
186/// we limit the text length to `DC_DESIRED_TEXT_LEN`.  If the text is longer, the full text can be
187/// retrieved using has_html()/get_html().
188///
189/// Note that for simplicity maximum length is defined as the number of Unicode Scalar Values (Rust
190/// `char`s), not Unicode Grapheme Clusters.
191pub const DC_DESIRED_TEXT_LEN: usize = DC_DESIRED_TEXT_LINE_LEN * DC_DESIRED_TEXT_LINES;
192
193// Flags for configuring IMAP and SMTP servers.
194// These flags are optional
195// and may be set together with the username, password etc.
196// via dc_set_config() using the key "server_flags".
197
198/// Force OAuth2 authorization.
199///
200/// This flag does not skip automatic configuration.
201/// Before calling configure() with DC_LP_AUTH_OAUTH2 set,
202/// the user has to confirm access at the URL returned by dc_get_oauth2_url().
203pub const DC_LP_AUTH_OAUTH2: i32 = 0x2;
204
205/// Force NORMAL authorization, this is the default.
206/// If this flag is set, automatic configuration is skipped.
207pub const DC_LP_AUTH_NORMAL: i32 = 0x4;
208
209/// if none of these flags are set, the default is chosen
210pub const DC_LP_AUTH_FLAGS: i32 = DC_LP_AUTH_OAUTH2 | DC_LP_AUTH_NORMAL;
211
212// max. weight of images to send w/o recoding
213pub const BALANCED_IMAGE_BYTES: usize = 500_000;
214pub const WORSE_IMAGE_BYTES: usize = 130_000;
215
216// max. width/height and bytes of an avatar
217pub(crate) const BALANCED_AVATAR_SIZE: u32 = 512;
218pub(crate) const BALANCED_AVATAR_BYTES: usize = 60_000;
219pub(crate) const WORSE_AVATAR_SIZE: u32 = 128;
220pub(crate) const WORSE_AVATAR_BYTES: usize = 20_000; // this also fits to Outlook servers don't allowing headers larger than 32k.
221
222// max. width/height of images scaled down because of being too huge
223pub const BALANCED_IMAGE_SIZE: u32 = 1280;
224pub const WORSE_IMAGE_SIZE: u32 = 640;
225
226/// Limit for received images size. Bigger images become `Viewtype::File` to avoid excessive memory
227/// usage by UIs.
228pub const MAX_RCVD_IMAGE_PIXELS: u32 = 50_000_000;
229
230// Key for the folder configuration version (see below).
231pub(crate) const DC_FOLDERS_CONFIGURED_KEY: &str = "folders_configured";
232// this value can be increased if the folder configuration is changed and must be redone on next program start
233pub(crate) const DC_FOLDERS_CONFIGURED_VERSION: i32 = 5;
234
235// If more recipients are needed in SMTP's `RCPT TO:` header, the recipient list is split into
236// chunks. This does not affect MIME's `To:` header. Can be overwritten by setting
237// `max_smtp_rcpt_to` in the provider db.
238pub(crate) const DEFAULT_MAX_SMTP_RCPT_TO: usize = 50;
239
240/// How far the last quota check needs to be in the past to be checked by the background function (in seconds).
241pub(crate) const DC_BACKGROUND_FETCH_QUOTA_CHECK_RATELIMIT: u64 = 12 * 60 * 60; // 12 hours
242
243/// How far in the future the sender timestamp of a message is allowed to be, in seconds. Also used
244/// in the group membership consistency algo to reject outdated membership changes.
245pub(crate) const TIMESTAMP_SENT_TOLERANCE: i64 = 60;
246
247// To make text edits clearer for Non-Delta-MUA or old Delta Chats, edited text will be prefixed by EDITED_PREFIX.
248// Newer Delta Chats will remove the prefix as needed.
249pub(crate) const EDITED_PREFIX: &str = "✏️";
250
251// Strings needed to render the Autocrypt Setup Message.
252// Left untranslated as not being supported/recommended workflow and as translations would require deep knowledge.
253pub(crate) const ASM_SUBJECT: &str = "Autocrypt Setup Message";
254pub(crate) const ASM_BODY: &str = "This is the Autocrypt Setup Message \
255    used to transfer your end-to-end setup between clients.
256
257    To decrypt and use your setup, \
258    open the message in an Autocrypt-compliant client \
259    and enter the setup code presented on the generating device.
260
261    If you see this message in a chatmail client (Delta Chat, Arcane Chat, Delta Touch ...), \
262    use \"Settings / Add Second Device\" instead.";
263
264/// Period between `sql::housekeeping()` runs.
265pub(crate) const HOUSEKEEPING_PERIOD: i64 = 24 * 60 * 60;
266
267#[cfg(test)]
268mod tests {
269    use num_traits::FromPrimitive;
270
271    use super::*;
272
273    #[test]
274    fn test_chattype_values() {
275        // values may be written to disk and must not change
276        assert_eq!(Chattype::Single, Chattype::from_i32(100).unwrap());
277        assert_eq!(Chattype::Group, Chattype::from_i32(120).unwrap());
278        assert_eq!(Chattype::Mailinglist, Chattype::from_i32(140).unwrap());
279        assert_eq!(Chattype::OutBroadcast, Chattype::from_i32(160).unwrap());
280    }
281
282    #[test]
283    fn test_showemails_values() {
284        // values may be written to disk and must not change
285        assert_eq!(ShowEmails::All, ShowEmails::default());
286        assert_eq!(ShowEmails::Off, ShowEmails::from_i32(0).unwrap());
287        assert_eq!(
288            ShowEmails::AcceptedContacts,
289            ShowEmails::from_i32(1).unwrap()
290        );
291        assert_eq!(ShowEmails::All, ShowEmails::from_i32(2).unwrap());
292    }
293
294    #[test]
295    fn test_blocked_values() {
296        // values may be written to disk and must not change
297        assert_eq!(Blocked::Not, Blocked::default());
298        assert_eq!(Blocked::Not, Blocked::from_i32(0).unwrap());
299        assert_eq!(Blocked::Yes, Blocked::from_i32(1).unwrap());
300        assert_eq!(Blocked::Request, Blocked::from_i32(2).unwrap());
301    }
302
303    #[test]
304    fn test_mediaquality_values() {
305        // values may be written to disk and must not change
306        assert_eq!(MediaQuality::Balanced, MediaQuality::default());
307        assert_eq!(MediaQuality::Balanced, MediaQuality::from_i32(0).unwrap());
308        assert_eq!(MediaQuality::Worse, MediaQuality::from_i32(1).unwrap());
309    }
310
311    #[test]
312    fn test_videochattype_values() {
313        // values may be written to disk and must not change
314        assert_eq!(VideochatType::Unknown, VideochatType::default());
315        assert_eq!(VideochatType::Unknown, VideochatType::from_i32(0).unwrap());
316        assert_eq!(
317            VideochatType::BasicWebrtc,
318            VideochatType::from_i32(1).unwrap()
319        );
320        assert_eq!(VideochatType::Jitsi, VideochatType::from_i32(2).unwrap());
321    }
322}