mirror of
https://github.com/chatmail/core.git
synced 2026-07-23 03:13:06 +03:00
Compare commits
10 Commits
1.71.0
...
hocuri/fix
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0d5e0398da | ||
|
|
3e227f1566 | ||
|
|
800c95ae63 | ||
|
|
f6807d6b22 | ||
|
|
57ea4c1d92 | ||
|
|
bcdd15ef3a | ||
|
|
5f939c3123 | ||
|
|
2446fc44ad | ||
|
|
9ba8dd91df | ||
|
|
e35e6c44cf |
2
.github/mergeable.yml
vendored
2
.github/mergeable.yml
vendored
@@ -23,4 +23,4 @@ mergeable:
|
||||
status: 'action_required'
|
||||
payload:
|
||||
title: Changlog might need an update
|
||||
summary: "Check if CHANGELOG.md needs an update or add #skip-update to the PR description."
|
||||
summary: "Check if CHANGELOG.md needs an update or add #skip-changelog to the PR description."
|
||||
|
||||
11
CHANGELOG.md
11
CHANGELOG.md
@@ -1,5 +1,16 @@
|
||||
# Changelog
|
||||
|
||||
## Unreleased
|
||||
|
||||
### API changes
|
||||
- added `only_fetch_mvbox` config #3014
|
||||
|
||||
## 1.72.0
|
||||
|
||||
### Fixes
|
||||
- run migrations on backup import #3006
|
||||
|
||||
|
||||
## 1.71.0
|
||||
|
||||
### API Changes
|
||||
|
||||
10
Cargo.lock
generated
10
Cargo.lock
generated
@@ -1063,7 +1063,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "deltachat"
|
||||
version = "1.71.0"
|
||||
version = "1.72.0"
|
||||
dependencies = [
|
||||
"ansi_term",
|
||||
"anyhow",
|
||||
@@ -1120,7 +1120,7 @@ dependencies = [
|
||||
"sha-1 0.10.0",
|
||||
"sha2 0.10.1",
|
||||
"smallvec",
|
||||
"stop-token 0.6.1",
|
||||
"stop-token 0.7.0",
|
||||
"strum",
|
||||
"strum_macros",
|
||||
"surf",
|
||||
@@ -1144,7 +1144,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "deltachat_ffi"
|
||||
version = "1.71.0"
|
||||
version = "1.72.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-std",
|
||||
@@ -3610,9 +3610,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "stop-token"
|
||||
version = "0.6.1"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3829f0fc642e19ef8a1072ba8e33139a385f609ba56761df501c5272a9704918"
|
||||
checksum = "af91f480ee899ab2d9f8435bfdfc14d08a5754bd9d3fef1f1a1c23336aad6c8b"
|
||||
dependencies = [
|
||||
"async-channel",
|
||||
"cfg-if 1.0.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "deltachat"
|
||||
version = "1.71.0"
|
||||
version = "1.72.0"
|
||||
authors = ["Delta Chat Developers (ML) <delta@codespeak.net>"]
|
||||
edition = "2018"
|
||||
license = "MPL-2.0"
|
||||
@@ -66,7 +66,7 @@ serde = { version = "1.0", features = ["derive"] }
|
||||
sha-1 = "0.10"
|
||||
sha2 = "0.10"
|
||||
smallvec = "1"
|
||||
stop-token = "0.6"
|
||||
stop-token = "0.7"
|
||||
strum = "0.23"
|
||||
strum_macros = "0.23"
|
||||
surf = { version = "2.3", default-features = false, features = ["h1-client"] }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "deltachat_ffi"
|
||||
version = "1.71.0"
|
||||
version = "1.72.0"
|
||||
description = "Deltachat FFI"
|
||||
authors = ["Delta Chat Developers (ML) <delta@codespeak.net>"]
|
||||
edition = "2018"
|
||||
|
||||
@@ -343,6 +343,11 @@ char* dc_get_blobdir (const dc_context_t* context);
|
||||
* and watch the `DeltaChat` folder for updates (default),
|
||||
* 0=do not move chat-messages
|
||||
* changes require restarting IO by calling dc_stop_io() and then dc_start_io().
|
||||
* - `only_fetch_mvbox` = 1=ignore all folders except for the `DeltaChat` folder.
|
||||
* Setting this will automatically set `mvbox_move` to 1 and `sentbox_watch` to 0.
|
||||
* Setting `mvbox_move` to 0 or `sentbox_watch` to 1 will automatically disable this option.
|
||||
* When this option is set, the UI should disable the `mvbox_move` and `sentbox_watch` options.
|
||||
* 0=watch all folders normally (default)
|
||||
* - `show_emails` = DC_SHOW_EMAILS_OFF (0)=
|
||||
* show direct replies to chats only (default),
|
||||
* DC_SHOW_EMAILS_ACCEPTED_CONTACTS (1)=
|
||||
|
||||
@@ -74,6 +74,9 @@ pub enum Config {
|
||||
#[strum(props(default = "0"))]
|
||||
SentboxMove, // If `MvboxMove` is true, this config is ignored. Currently only used in tests.
|
||||
|
||||
#[strum(props(default = "0"))]
|
||||
OnlyFetchMvbox,
|
||||
|
||||
#[strum(props(default = "0"))] // also change ShowEmails.default() on changes
|
||||
ShowEmails,
|
||||
|
||||
@@ -281,35 +284,56 @@ impl Context {
|
||||
}
|
||||
}
|
||||
self.emit_event(EventType::SelfavatarChanged);
|
||||
Ok(())
|
||||
}
|
||||
Config::DeleteDeviceAfter => {
|
||||
let ret = self
|
||||
.sql
|
||||
.set_raw_config(key, value)
|
||||
.await
|
||||
.map_err(Into::into);
|
||||
let ret = self.sql.set_raw_config(key, value).await;
|
||||
// Force chatlist reload to delete old messages immediately.
|
||||
self.emit_event(EventType::MsgsChanged {
|
||||
msg_id: MsgId::new(0),
|
||||
chat_id: ChatId::new(0),
|
||||
});
|
||||
ret
|
||||
ret?
|
||||
}
|
||||
Config::Displayname => {
|
||||
let value = value.map(improve_single_line_input);
|
||||
self.sql.set_raw_config(key, value.as_deref()).await?;
|
||||
Ok(())
|
||||
}
|
||||
Config::SentboxWatch => {
|
||||
self.sql.set_raw_config(key, value).await?;
|
||||
if config_to_bool(value) {
|
||||
self.sql
|
||||
.set_raw_config(Config::OnlyFetchMvbox, Some("0"))
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
Config::MvboxMove => {
|
||||
self.sql.set_raw_config(key, value).await?;
|
||||
if !config_to_bool(value) {
|
||||
self.sql
|
||||
.set_raw_config(Config::OnlyFetchMvbox, Some("0"))
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
Config::OnlyFetchMvbox => {
|
||||
self.sql.set_raw_config(key, value).await?;
|
||||
if config_to_bool(value) {
|
||||
self.sql
|
||||
.set_raw_config(Config::SentboxWatch, Some("0"))
|
||||
.await?;
|
||||
self.sql
|
||||
.set_raw_config(Config::MvboxMove, Some("1"))
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
self.sql.set_raw_config(key, value).await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn set_config_bool(&self, key: Config, value: bool) -> Result<()> {
|
||||
self.set_config(key, if value { Some("1") } else { None })
|
||||
self.set_config(key, if value { Some("1") } else { Some("0") })
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -341,6 +365,13 @@ fn get_config_keys_string() -> String {
|
||||
format!(" {} ", keys)
|
||||
}
|
||||
|
||||
fn config_to_bool(value: Option<&str>) -> bool {
|
||||
value
|
||||
.and_then(|s| s.parse::<i32>().ok())
|
||||
.unwrap_or_default()
|
||||
!= 0
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -401,4 +432,41 @@ mod tests {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn test_set_config_bool() -> Result<()> {
|
||||
let t = TestContext::new().await;
|
||||
|
||||
// Regression test for https://github.com/deltachat/deltachat-core-rust/issues/3012
|
||||
// We need some config that defaults to true
|
||||
let c = Config::E2eeEnabled;
|
||||
assert_eq!(t.get_config_bool(c).await?, true);
|
||||
t.set_config_bool(c, false).await?;
|
||||
assert_eq!(t.get_config_bool(c).await?, false);
|
||||
|
||||
// Test that OnlyFetchMvbox==true implies MvboxMove==true and SentboxWatch==false
|
||||
t.set_config_bool(Config::SentboxWatch, true).await?;
|
||||
|
||||
t.set_config_bool(Config::OnlyFetchMvbox, true).await?;
|
||||
assert_eq!(t.get_config_bool(Config::SentboxWatch).await?, false);
|
||||
assert_eq!(t.get_config_bool(Config::OnlyFetchMvbox).await?, true);
|
||||
|
||||
t.set_config_bool(Config::MvboxMove, false).await?;
|
||||
assert_eq!(t.get_config_bool(Config::MvboxMove).await?, false);
|
||||
assert_eq!(t.get_config_bool(Config::OnlyFetchMvbox).await?, false);
|
||||
|
||||
t.set_config_bool(Config::SentboxWatch, true).await?;
|
||||
assert_eq!(t.get_config_bool(Config::SentboxWatch).await?, true);
|
||||
|
||||
t.set_config_bool(Config::OnlyFetchMvbox, true).await?;
|
||||
assert_eq!(t.get_config_bool(Config::SentboxWatch).await?, false);
|
||||
assert_eq!(t.get_config_bool(Config::MvboxMove).await?, true);
|
||||
assert_eq!(t.get_config_bool(Config::OnlyFetchMvbox).await?, true);
|
||||
|
||||
t.set_config_bool(Config::SentboxWatch, true).await?;
|
||||
assert_eq!(t.get_config_bool(Config::SentboxWatch).await?, true);
|
||||
assert_eq!(t.get_config_bool(Config::OnlyFetchMvbox).await?, false);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -358,6 +358,7 @@ impl Context {
|
||||
let sentbox_watch = self.get_config_int(Config::SentboxWatch).await?;
|
||||
let mvbox_move = self.get_config_int(Config::MvboxMove).await?;
|
||||
let sentbox_move = self.get_config_int(Config::SentboxMove).await?;
|
||||
let only_fetch_mvbox = self.get_config_int(Config::OnlyFetchMvbox).await?;
|
||||
let folders_configured = self
|
||||
.sql
|
||||
.get_raw_config_int("folders_configured")
|
||||
@@ -422,6 +423,7 @@ impl Context {
|
||||
res.insert("sentbox_watch", sentbox_watch.to_string());
|
||||
res.insert("mvbox_move", mvbox_move.to_string());
|
||||
res.insert("sentbox_move", sentbox_move.to_string());
|
||||
res.insert("only_fetch_mvbox", only_fetch_mvbox.to_string());
|
||||
res.insert("folders_configured", folders_configured.to_string());
|
||||
res.insert("configured_sentbox_folder", configured_sentbox_folder);
|
||||
res.insert("configured_mvbox_folder", configured_mvbox_folder);
|
||||
|
||||
13
src/imap.rs
13
src/imap.rs
@@ -671,6 +671,11 @@ impl Imap {
|
||||
folder: &str,
|
||||
fetch_existing_msgs: bool,
|
||||
) -> Result<bool> {
|
||||
if should_ignore_folder(context, folder).await? {
|
||||
info!(context, "Not fetching from {}", folder);
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
let new_emails = self.select_with_uidvalidity(context, folder).await?;
|
||||
|
||||
if !new_emails && !fetch_existing_msgs {
|
||||
@@ -2076,6 +2081,14 @@ pub async fn get_config_last_seen_uid(context: &Context, folder: &str) -> Result
|
||||
}
|
||||
}
|
||||
|
||||
async fn should_ignore_folder(context: &Context, folder: &str) -> Result<bool> {
|
||||
Ok(context.get_config_bool(Config::OnlyFetchMvbox).await?
|
||||
&& context.is_mvbox(folder).await?
|
||||
// Even if OnlyFetchMvbox is set, we have a look at the spam folder
|
||||
// in case an answer to a known message was put into spam:
|
||||
&& context.is_spam_folder(folder).await?)
|
||||
}
|
||||
|
||||
/// Builds a list of sequence/uid sets. The returned sets have each no more than around 1000
|
||||
/// characters because according to <https://tools.ietf.org/html/rfc2683#section-3.2.1.5>
|
||||
/// command lines should not be much more than 1000 chars (servers should allow at least 8000 chars)
|
||||
|
||||
@@ -157,7 +157,6 @@ impl Imap {
|
||||
// in anything. If so, we behave as if IDLE had data but
|
||||
// will have already fetched the messages so perform_*_fetch
|
||||
// will not find any new.
|
||||
|
||||
match self.fetch_new_messages(context, &watch_folder, false).await {
|
||||
Ok(res) => {
|
||||
info!(context, "fetch_new_messages returned {:?}", res);
|
||||
|
||||
@@ -423,7 +423,8 @@ async fn imex_inner(
|
||||
export_backup(context, path, passphrase.unwrap_or_default()).await
|
||||
}
|
||||
ImexMode::ImportBackup => {
|
||||
import_backup(context, path, passphrase.unwrap_or_default()).await
|
||||
import_backup(context, path, passphrase.unwrap_or_default()).await?;
|
||||
context.sql.run_migrations(context).await
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,6 +215,12 @@ impl Sql {
|
||||
conn.pragma_update(None, "synchronous", &"NORMAL".to_string())?;
|
||||
}
|
||||
|
||||
self.run_migrations(context).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn run_migrations(&self, context: &Context) -> Result<()> {
|
||||
// (1) update low-level database structure.
|
||||
// this should be done before updates that use high-level objects that
|
||||
// rely themselves on the low-level structure.
|
||||
|
||||
Reference in New Issue
Block a user