diff --git a/Cargo.lock b/Cargo.lock index 83de4b26..3f3bed77 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -191,6 +191,12 @@ dependencies = [ "zbus", ] +[[package]] +name = "assert_matches2" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15832d94c458da98cac0ffa6eca52cc19c2a3c6c951058500a5ae8f01f0fdf56" + [[package]] name = "assign" version = "1.1.1" @@ -701,9 +707,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.101" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac367972e516d45567c7eafc73d24e1c193dcf200a8d94e9db7b3d38b349572d" +checksum = "779e6b7d17797c0b42023d417228c02889300190e700cb074c3438d9c541d332" dependencies = [ "jobserver", "libc", @@ -1405,7 +1411,6 @@ version = "7.0.0" dependencies = [ "ashpd", "djb_hash", - "eyeball-im", "futures-channel", "futures-util", "geo-uri", @@ -1898,6 +1903,18 @@ dependencies = [ "system-deps", ] +[[package]] +name = "growable-bloom-filter" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c669fa03050eb3445343f215d62fc1ab831e8098bc9a55f26e9724faff11075c" +dependencies = [ + "serde", + "serde_bytes", + "serde_derive", + "xxhash-rust", +] + [[package]] name = "gsk4" version = "0.8.2" @@ -2885,9 +2902,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.21" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "loop9" @@ -3030,7 +3047,7 @@ dependencies = [ [[package]] name = "matrix-sdk" version = "0.7.1" -source = "git+https://github.com/matrix-org/matrix-rust-sdk.git?rev=64c5a83e3368b33e53f17d167d8bc3aa646438cc#64c5a83e3368b33e53f17d167d8bc3aa646438cc" +source = "git+https://github.com/matrix-org/matrix-rust-sdk.git?rev=38a18c3c8e3be2951967d463ade1f6607228e6a7#38a18c3c8e3be2951967d463ade1f6607228e6a7" dependencies = [ "anymap2", "aquamarine", @@ -3045,7 +3062,6 @@ dependencies = [ "event-listener", "eyeball", "eyeball-im", - "eyeball-im-util", "futures-core", "futures-util", "gloo-timers", @@ -3075,13 +3091,14 @@ dependencies = [ "tracing", "url", "urlencoding", + "vodozemac", "zeroize", ] [[package]] name = "matrix-sdk-base" version = "0.7.0" -source = "git+https://github.com/matrix-org/matrix-rust-sdk.git?rev=64c5a83e3368b33e53f17d167d8bc3aa646438cc#64c5a83e3368b33e53f17d167d8bc3aa646438cc" +source = "git+https://github.com/matrix-org/matrix-rust-sdk.git?rev=38a18c3c8e3be2951967d463ade1f6607228e6a7#38a18c3c8e3be2951967d463ade1f6607228e6a7" dependencies = [ "as_variant", "async-trait", @@ -3089,6 +3106,7 @@ dependencies = [ "eyeball", "eyeball-im", "futures-util", + "growable-bloom-filter", "matrix-sdk-common", "matrix-sdk-crypto", "matrix-sdk-store-encryption", @@ -3104,7 +3122,7 @@ dependencies = [ [[package]] name = "matrix-sdk-common" version = "0.7.0" -source = "git+https://github.com/matrix-org/matrix-rust-sdk.git?rev=64c5a83e3368b33e53f17d167d8bc3aa646438cc#64c5a83e3368b33e53f17d167d8bc3aa646438cc" +source = "git+https://github.com/matrix-org/matrix-rust-sdk.git?rev=38a18c3c8e3be2951967d463ade1f6607228e6a7#38a18c3c8e3be2951967d463ade1f6607228e6a7" dependencies = [ "async-trait", "futures-core", @@ -3125,11 +3143,12 @@ dependencies = [ [[package]] name = "matrix-sdk-crypto" -version = "0.7.0" -source = "git+https://github.com/matrix-org/matrix-rust-sdk.git?rev=64c5a83e3368b33e53f17d167d8bc3aa646438cc#64c5a83e3368b33e53f17d167d8bc3aa646438cc" +version = "0.7.1" +source = "git+https://github.com/matrix-org/matrix-rust-sdk.git?rev=38a18c3c8e3be2951967d463ade1f6607228e6a7#38a18c3c8e3be2951967d463ade1f6607228e6a7" dependencies = [ "aes", "as_variant", + "assert_matches2", "async-trait", "bs58", "byteorder", @@ -3167,13 +3186,14 @@ dependencies = [ [[package]] name = "matrix-sdk-indexeddb" version = "0.7.0" -source = "git+https://github.com/matrix-org/matrix-rust-sdk.git?rev=64c5a83e3368b33e53f17d167d8bc3aa646438cc#64c5a83e3368b33e53f17d167d8bc3aa646438cc" +source = "git+https://github.com/matrix-org/matrix-rust-sdk.git?rev=38a18c3c8e3be2951967d463ade1f6607228e6a7#38a18c3c8e3be2951967d463ade1f6607228e6a7" dependencies = [ "anyhow", "async-trait", "base64", "getrandom", "gloo-utils", + "hkdf", "indexed_db_futures", "js-sys", "matrix-sdk-crypto", @@ -3182,17 +3202,19 @@ dependencies = [ "serde", "serde-wasm-bindgen", "serde_json", + "sha2", "thiserror", "tokio", "tracing", "wasm-bindgen", "web-sys", + "zeroize", ] [[package]] name = "matrix-sdk-qrcode" version = "0.7.0" -source = "git+https://github.com/matrix-org/matrix-rust-sdk.git?rev=64c5a83e3368b33e53f17d167d8bc3aa646438cc#64c5a83e3368b33e53f17d167d8bc3aa646438cc" +source = "git+https://github.com/matrix-org/matrix-rust-sdk.git?rev=38a18c3c8e3be2951967d463ade1f6607228e6a7#38a18c3c8e3be2951967d463ade1f6607228e6a7" dependencies = [ "byteorder", "qrcode", @@ -3204,7 +3226,7 @@ dependencies = [ [[package]] name = "matrix-sdk-sqlite" version = "0.7.0" -source = "git+https://github.com/matrix-org/matrix-rust-sdk.git?rev=64c5a83e3368b33e53f17d167d8bc3aa646438cc#64c5a83e3368b33e53f17d167d8bc3aa646438cc" +source = "git+https://github.com/matrix-org/matrix-rust-sdk.git?rev=38a18c3c8e3be2951967d463ade1f6607228e6a7#38a18c3c8e3be2951967d463ade1f6607228e6a7" dependencies = [ "async-trait", "deadpool-sqlite", @@ -3226,7 +3248,7 @@ dependencies = [ [[package]] name = "matrix-sdk-store-encryption" version = "0.7.0" -source = "git+https://github.com/matrix-org/matrix-rust-sdk.git?rev=64c5a83e3368b33e53f17d167d8bc3aa646438cc#64c5a83e3368b33e53f17d167d8bc3aa646438cc" +source = "git+https://github.com/matrix-org/matrix-rust-sdk.git?rev=38a18c3c8e3be2951967d463ade1f6607228e6a7#38a18c3c8e3be2951967d463ade1f6607228e6a7" dependencies = [ "base64", "blake3", @@ -3245,7 +3267,7 @@ dependencies = [ [[package]] name = "matrix-sdk-ui" version = "0.7.0" -source = "git+https://github.com/matrix-org/matrix-rust-sdk.git?rev=64c5a83e3368b33e53f17d167d8bc3aa646438cc#64c5a83e3368b33e53f17d167d8bc3aa646438cc" +source = "git+https://github.com/matrix-org/matrix-rust-sdk.git?rev=38a18c3c8e3be2951967d463ade1f6607228e6a7#38a18c3c8e3be2951967d463ade1f6607228e6a7" dependencies = [ "as_variant", "async-once-cell", @@ -3260,6 +3282,7 @@ dependencies = [ "futures-core", "futures-util", "fuzzy-matcher", + "growable-bloom-filter", "imbl", "indexmap", "itertools 0.12.1", @@ -3275,7 +3298,6 @@ dependencies = [ "tokio", "tracing", "unicode-normalization", - "url", ] [[package]] @@ -3317,9 +3339,9 @@ checksum = "a1a85a5069ebd40e64b1985773cc81addbe9d90d7ecf60e7b5475a57ad584c70" [[package]] name = "mime_guess" -version = "2.0.4" +version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" dependencies = [ "mime", "unicase", @@ -3447,9 +3469,9 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c165a9ab64cf766f73521c0dd2cfdff64f488b8f0b3e621face3462d3db536d7" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ "num-integer", "num-traits", @@ -3580,9 +3602,9 @@ dependencies = [ [[package]] name = "object" -version = "0.36.0" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" +checksum = "081b846d1d56ddfc18fdf1a922e4f6e07a11768ea1b92dec44e42b72712ccfce" dependencies = [ "memchr", ] @@ -4075,9 +4097,9 @@ dependencies = [ [[package]] name = "pulldown-cmark" -version = "0.10.3" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76979bea66e7875e7509c4ec5300112b316af87fa7a252ca91c448b32dfe3993" +checksum = "8746739f11d39ce5ad5c2520a9b75285310dbfe78c541ccf832d38615765aec0" dependencies = [ "bitflags 2.6.0", "getopts", @@ -4088,9 +4110,9 @@ dependencies = [ [[package]] name = "pulldown-cmark-escape" -version = "0.10.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd348ff538bc9caeda7ee8cad2d1d48236a1f443c1fa3913c6a02fe0043b1dd3" +checksum = "007d8adb5ddab6f8e3f491ac63566a7d5002cc7ed73901f72057943fa71ae1ae" [[package]] name = "qoi" @@ -4338,9 +4360,9 @@ dependencies = [ [[package]] name = "rgb" -version = "0.8.37" +version = "0.8.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05aaa8004b64fd573fc9d002f4e632d51ad4f026c2b5ba95fcb6c2f32c2c47d8" +checksum = "a7439be6844e40133eda024efd85bf07f59d0dd2f59b10c00dd6cfb92cc5c741" dependencies = [ "bytemuck", ] @@ -4381,8 +4403,7 @@ dependencies = [ [[package]] name = "ruma" version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a555b3e7ca84892ef6e81eadb42c783b76ffb939d6ad9781a9da7023a501521" +source = "git+https://github.com/ruma/ruma.git?rev=e5a370f7e5fcebb0da6e4945e51c5fafba9aa5f0#e5a370f7e5fcebb0da6e4945e51c5fafba9aa5f0" dependencies = [ "assign", "js_int", @@ -4399,8 +4420,7 @@ dependencies = [ [[package]] name = "ruma-client-api" version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7ec9d6b5fe002fc018b1daa36f888e80a670ffa7f7778d025e90478c0838ad" +source = "git+https://github.com/ruma/ruma.git?rev=e5a370f7e5fcebb0da6e4945e51c5fafba9aa5f0#e5a370f7e5fcebb0da6e4945e51c5fafba9aa5f0" dependencies = [ "as_variant", "assign", @@ -4416,14 +4436,14 @@ dependencies = [ "serde_html_form", "serde_json", "thiserror", + "url", "web-time", ] [[package]] name = "ruma-common" version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ba97203cc4cab8dc10e62fe8156ae5c61d2553f37c3037759fbae601982fb7b" +source = "git+https://github.com/ruma/ruma.git?rev=e5a370f7e5fcebb0da6e4945e51c5fafba9aa5f0#e5a370f7e5fcebb0da6e4945e51c5fafba9aa5f0" dependencies = [ "as_variant", "base64", @@ -4455,8 +4475,7 @@ dependencies = [ [[package]] name = "ruma-events" version = "0.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fddef15eca0faee500016850a8473fb8c07b17b056b2ae5352ef67cf917102e3" +source = "git+https://github.com/ruma/ruma.git?rev=e5a370f7e5fcebb0da6e4945e51c5fafba9aa5f0#e5a370f7e5fcebb0da6e4945e51c5fafba9aa5f0" dependencies = [ "as_variant", "indexmap", @@ -4480,8 +4499,7 @@ dependencies = [ [[package]] name = "ruma-federation-api" version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea43deab72b76655e36305127894249e33f48696a5af3c8aa048dc42d772af45" +source = "git+https://github.com/ruma/ruma.git?rev=e5a370f7e5fcebb0da6e4945e51c5fafba9aa5f0#e5a370f7e5fcebb0da6e4945e51c5fafba9aa5f0" dependencies = [ "js_int", "ruma-common", @@ -4493,8 +4511,7 @@ dependencies = [ [[package]] name = "ruma-html" version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb6d948779da5fb4d1fc2d4c7a3f0cab21453dd14765a72fbee38ef758613d7f" +source = "git+https://github.com/ruma/ruma.git?rev=e5a370f7e5fcebb0da6e4945e51c5fafba9aa5f0#e5a370f7e5fcebb0da6e4945e51c5fafba9aa5f0" dependencies = [ "as_variant", "html5ever", @@ -4507,8 +4524,7 @@ dependencies = [ [[package]] name = "ruma-identifiers-validation" version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa38974f5901ed4e00e10aec57b9ad3b4d6d6c1a1ae683c51b88700b9f4ffba" +source = "git+https://github.com/ruma/ruma.git?rev=e5a370f7e5fcebb0da6e4945e51c5fafba9aa5f0#e5a370f7e5fcebb0da6e4945e51c5fafba9aa5f0" dependencies = [ "js_int", "thiserror", @@ -4517,8 +4533,7 @@ dependencies = [ [[package]] name = "ruma-macros" version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d36857a3350ea611ecc9968dcc4f3d5a03227a6c3fcbb446e8530e3be8852282" +source = "git+https://github.com/ruma/ruma.git?rev=e5a370f7e5fcebb0da6e4945e51c5fafba9aa5f0#e5a370f7e5fcebb0da6e4945e51c5fafba9aa5f0" dependencies = [ "once_cell", "proc-macro-crate", @@ -4533,8 +4548,7 @@ dependencies = [ [[package]] name = "ruma-push-gateway-api" version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42ef562eddab426c4402d004ea577f9034c74cd1714e087e9e0d47e88662ec2" +source = "git+https://github.com/ruma/ruma.git?rev=e5a370f7e5fcebb0da6e4945e51c5fafba9aa5f0#e5a370f7e5fcebb0da6e4945e51c5fafba9aa5f0" dependencies = [ "js_int", "ruma-common", @@ -5553,13 +5567,13 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "vodozemac" version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9858e8b8ff262b4eb95854af3810283f563c9149682b9a2cf85dd003ff912b5c" +source = "git+https://github.com/matrix-org/vodozemac/?rev=4ef989c6a8eba0bc809e285a081c56320a9bbf1e#4ef989c6a8eba0bc809e285a081c56320a9bbf1e" dependencies = [ "aes", "arrayvec", "base64", "cbc", + "chacha20poly1305", "curve25519-dalek", "ed25519-dalek", "getrandom", @@ -5936,6 +5950,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "xxhash-rust" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "927da81e25be1e1a2901d59b81b37dd2efd1fc9c9345a55007f09bf5a2d3ee03" + [[package]] name = "yansi-term" version = "0.1.2" diff --git a/Cargo.toml b/Cargo.toml index 9baf08d2..358cfc21 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,6 @@ codegen-units = 16 # Please keep dependencies sorted. [dependencies] djb_hash = "0.1" -eyeball-im = "0.4" futures-channel = "0.3" futures-util = "0.3" geo-uri = "0.2" @@ -33,7 +32,7 @@ linkify = "0.10.0" mime = "0.3" mime_guess = "2" once_cell = "1" -pulldown-cmark = "0.10" +pulldown-cmark = "0.11" qrcode = "0.14" rand = "0.8" regex = "1" @@ -64,7 +63,7 @@ sourceview = { package = "sourceview5", version = "0.8" } [dependencies.matrix-sdk] git = "https://github.com/matrix-org/matrix-rust-sdk.git" -rev = "64c5a83e3368b33e53f17d167d8bc3aa646438cc" +rev = "38a18c3c8e3be2951967d463ade1f6607228e6a7" features = [ "socks", "sso-login", @@ -75,14 +74,14 @@ features = [ [dependencies.matrix-sdk-ui] git = "https://github.com/matrix-org/matrix-rust-sdk.git" -rev = "64c5a83e3368b33e53f17d167d8bc3aa646438cc" +rev = "38a18c3c8e3be2951967d463ade1f6607228e6a7" default-features = false features = ["e2e-encryption", "native-tls"] [dependencies.ruma] -version = "0.10" -# git = "https://github.com/ruma/ruma.git" -# rev = "b6200c01a120120faf9f744ab4f171ff3beefd72" +# version = "0.10" +git = "https://github.com/ruma/ruma.git" +rev = "e5a370f7e5fcebb0da6e4945e51c5fafba9aa5f0" features = [ "unstable-unspecified", "client-api-c", diff --git a/po/POTFILES.in b/po/POTFILES.in index dbbc4c5d..01ccb128 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -142,7 +142,6 @@ src/session/view/content/room_history/message_row/file.ui src/session/view/content/room_history/message_row/location.rs src/session/view/content/room_history/message_row/location.ui src/session/view/content/room_history/message_row/media.rs -src/session/view/content/room_history/message_row/message_state_stack.rs src/session/view/content/room_history/message_row/message_state_stack.ui src/session/view/content/room_history/message_row/mod.rs src/session/view/content/room_history/message_row/reaction/mod.rs diff --git a/src/session/model/room/event/mod.rs b/src/session/model/room/event/mod.rs index f7286481..48eb3410 100644 --- a/src/session/model/room/event/mod.rs +++ b/src/session/model/room/event/mod.rs @@ -79,20 +79,23 @@ impl FromVariant for EventKey { } #[derive(Debug, Default, Hash, Eq, PartialEq, Clone, Copy, glib::Enum)] -#[repr(u32)] #[enum_type(name = "MessageState")] pub enum MessageState { /// The message has no particular state. #[default] - None = 0, + None, /// The message is being sent. - Sending = 1, - /// An error occurred when sending the message. - Error = 2, - /// Sending the message was cancelled. - Cancelled = 3, + Sending, + /// A transient error occurred when sending the message. + /// + /// The user can try to send it again. + RecoverableError, + /// A permanent error occurred when sending the message. + /// + /// The message can only be cancelled. + PermanentError, /// The message was edited. - Edited = 4, + Edited, } /// A user's read receipt. @@ -604,14 +607,25 @@ impl Event { if let Some(send_state) = item.send_state() { match send_state { EventSendState::NotSentYet => return MessageState::Sending, - EventSendState::SendingFailed { error } => { - if self.state() != MessageState::Error { + EventSendState::SendingFailed { + error, + is_recoverable, + } => { + if !matches!( + self.state(), + MessageState::PermanentError | MessageState::RecoverableError, + ) { error!("Could not send message: {error}"); } - return MessageState::Error; + let new_state = if *is_recoverable { + MessageState::RecoverableError + } else { + MessageState::PermanentError + }; + + return new_state; } - EventSendState::Cancelled => return MessageState::Cancelled, EventSendState::Sent { .. } => {} } } diff --git a/src/session/model/room/mod.rs b/src/session/model/room/mod.rs index 05b58d4b..13ff7145 100644 --- a/src/session/model/room/mod.rs +++ b/src/session/model/room/mod.rs @@ -1213,7 +1213,7 @@ impl Room { /// Load the display name from the SDK. async fn load_display_name(&self) { let matrix_room = self.matrix_room().clone(); - let handle = spawn_tokio!(async move { matrix_room.computed_display_name().await }); + let handle = spawn_tokio!(async move { matrix_room.compute_display_name().await }); // FIXME: We should retry if the request failed match handle.await.unwrap() { diff --git a/src/session/model/room/timeline/mod.rs b/src/session/model/room/timeline/mod.rs index d33a8d30..7d838c10 100644 --- a/src/session/model/room/timeline/mod.rs +++ b/src/session/model/room/timeline/mod.rs @@ -3,13 +3,15 @@ mod virtual_item; use std::{collections::HashMap, sync::Arc}; -use eyeball_im::VectorDiff; use futures_util::StreamExt; use gtk::{gio, glib, glib::clone, prelude::*, subclass::prelude::*}; use matrix_sdk::Error as MatrixError; -use matrix_sdk_ui::timeline::{ - default_event_filter, AnyOtherFullStateEventContent, PaginationStatus, RoomExt, - Timeline as SdkTimeline, TimelineItem as SdkTimelineItem, TimelineItemContent, +use matrix_sdk_ui::{ + eyeball_im::VectorDiff, + timeline::{ + default_event_filter, AnyOtherFullStateEventContent, LiveBackPaginationStatus, RoomExt, + Timeline as SdkTimeline, TimelineItem as SdkTimelineItem, TimelineItemContent, + }, }; use ruma::{ events::{ @@ -48,12 +50,16 @@ pub enum TimelineState { Complete, } -impl From for TimelineState { - fn from(value: PaginationStatus) -> Self { +impl From for TimelineState { + fn from(value: LiveBackPaginationStatus) -> Self { match value { - PaginationStatus::Idle => Self::Ready, - PaginationStatus::Paginating => Self::Loading, - PaginationStatus::TimelineEndReached => Self::Complete, + LiveBackPaginationStatus::Idle { + hit_start_of_timeline: false, + } => Self::Ready, + LiveBackPaginationStatus::Idle { + hit_start_of_timeline: true, + } => Self::Complete, + LiveBackPaginationStatus::Paginating => Self::Loading, } } } @@ -636,12 +642,15 @@ impl Timeline { let room_id = room.room_id().to_owned(); let matrix_timeline = self.matrix_timeline(); - let mut subscriber = matrix_timeline.back_pagination_status(); + let (status, stream) = matrix_timeline + .live_back_pagination_status() + .await + .expect("Timeline should be in live mode"); - self.set_state(subscriber.next_now().into()); + self.set_state(status.into()); let obj_weak = glib::SendWeakRef::from(self.downgrade()); - let fut = subscriber.for_each(move |status| { + let fut = stream.for_each(move |status| { let obj_weak = obj_weak.clone(); let room_id = room_id.clone(); async move { diff --git a/src/session/model/verification/identity_verification.rs b/src/session/model/verification/identity_verification.rs index 1fff6ee0..8935b21f 100644 --- a/src/session/model/verification/identity_verification.rs +++ b/src/session/model/verification/identity_verification.rs @@ -174,9 +174,6 @@ mod imp { /// have access to the camera. #[property(get)] pub camera_paintable: RefCell>, - /// Whether we started the SAS verification. - #[property(get)] - pub we_started_sas: Cell, /// Whether this verification was viewed by the user. #[property(get, set = Self::set_was_viewed, explicit_notify)] pub was_viewed: Cell, @@ -769,13 +766,12 @@ impl IdentityVerification { let imp = self.imp(); match state { + SasState::Created { .. } => {} SasState::Started { .. } => { - if !self.we_started_sas() { - let handle = spawn_tokio!(async move { sas_verification.accept().await }); - if let Err(error) = handle.await.unwrap() { - error!("Could not accept SAS verification: {error}"); - imp.set_state(VerificationState::Error); - } + let handle = spawn_tokio!(async move { sas_verification.accept().await }); + if let Err(error) = handle.await.unwrap() { + error!("Could not accept SAS verification: {error}"); + imp.set_state(VerificationState::Error); } } SasState::Accepted { .. } => {} @@ -821,12 +817,6 @@ impl IdentityVerification { } } - /// Set whether we started the SAS verification. - fn set_we_started_sas(&self, we_started: bool) { - self.imp().we_started_sas.set(we_started); - self.notify_we_started_sas(); - } - /// Try to load the QR Code. /// /// Return `true` if it was successfully loaded, `false` otherwise. @@ -927,25 +917,16 @@ impl IdentityVerification { /// Start a SAS verification. pub async fn start_sas(&self) -> Result<(), ()> { let request = self.request().clone(); - - // We need to set this first, to make sure we have it when we handle the state - // change. - self.set_we_started_sas(true); - let handle = spawn_tokio!(async move { request.start_sas().await }); match handle.await.unwrap() { Ok(Some(_)) => Ok(()), Ok(None) => { error!("Could not start SAS verification: unknown reason"); - // Unset it because it didn't work. - self.set_we_started_sas(false); Err(()) } Err(error) => { error!("Could not start SAS verification: {error}"); - // Unset it because it didn't work. - self.set_we_started_sas(false); Err(()) } } diff --git a/src/session/view/content/room_history/event_actions.ui b/src/session/view/content/room_history/event_actions.ui index ccbad454..5a219944 100644 --- a/src/session/view/content/room_history/event_actions.ui +++ b/src/session/view/content/room_history/event_actions.ui @@ -72,11 +72,6 @@
- - _Try Again - event.retry-send - action-missing - _Discard event.cancel-send @@ -163,11 +158,6 @@
- - _Try Again - event.retry-send - action-missing - _Discard event.cancel-send diff --git a/src/session/view/content/room_history/item_row.rs b/src/session/view/content/room_history/item_row.rs index 4b06539c..7f56548e 100644 --- a/src/session/view/content/room_history/item_row.rs +++ b/src/session/view/content/room_history/item_row.rs @@ -553,7 +553,12 @@ impl ItemRow { } else { let state = event.state(); - if matches!(state, MessageState::Sending | MessageState::Error) { + if matches!( + state, + MessageState::Sending + | MessageState::RecoverableError + | MessageState::PermanentError + ) { // Cancel the event. action_group.add_action_entries([gio::ActionEntry::builder("cancel-send") .activate(clone!( @@ -567,21 +572,6 @@ impl ItemRow { )) .build()]); } - - if state == MessageState::Error { - // Retry to send the event. - action_group.add_action_entries([gio::ActionEntry::builder("retry-send") - .activate(clone!( - #[weak(rename_to = obj)] - self, - move |_, _, _| { - spawn!(async move { - obj.retry_send().await; - }); - } - )) - .build()]); - } } if let TimelineItemContent::Message(message) = event.content() { @@ -1007,41 +997,18 @@ impl ItemRow { let Some(event) = self.item().and_downcast::() else { return; }; - let Some(transaction_id) = event.transaction_id() else { - return; - }; - if !event + if let Err(error) = event .room() .timeline() .matrix_timeline() - .cancel_send(&transaction_id) + .redact(&event.item(), None) .await { + error!("Could not discard local event: {error}"); toast!(self, gettext("Could not discard message")); } } - - /// Retry sending the event of this row. - async fn retry_send(&self) { - let Some(event) = self.item().and_downcast::() else { - return; - }; - let Some(transaction_id) = event.transaction_id() else { - return; - }; - - if event - .room() - .timeline() - .matrix_timeline() - .retry_send(&transaction_id) - .await - .is_err() - { - toast!(self, gettext("Could not retry to send message")); - } - } } // This is only safe because the trait `EventActions` can diff --git a/src/session/view/content/room_history/message_row/message_state_stack.rs b/src/session/view/content/room_history/message_row/message_state_stack.rs index 9f91b0de..5b8bd6c4 100644 --- a/src/session/view/content/room_history/message_row/message_state_stack.rs +++ b/src/session/view/content/room_history/message_row/message_state_stack.rs @@ -1,5 +1,4 @@ use adw::subclass::prelude::*; -use gettextrs::gettext; use gtk::{glib, glib::clone, prelude::*, CompositeTemplate}; use crate::session::model::MessageState; @@ -26,8 +25,6 @@ mod imp { pub state: Cell, #[template_child] pub stack: TemplateChild, - #[template_child] - pub error_image: TemplateChild, } #[glib::object_subclass] @@ -67,7 +64,9 @@ mod imp { MessageState::None => { if matches!( prev_state, - MessageState::Sending | MessageState::Error | MessageState::Cancelled + MessageState::Sending + | MessageState::RecoverableError + | MessageState::PermanentError ) { // Show the sent icon. stack.set_visible_child_name("sent"); @@ -90,23 +89,20 @@ mod imp { stack.set_visible_child_name("sending"); obj.set_visible(true); } - MessageState::Error => { - self.error_image - .set_tooltip_text(Some(&gettext("Could not send the message"))); - stack.set_visible_child_name("error"); + MessageState::RecoverableError => { + stack.set_visible_child_name("warning"); obj.set_visible(true); } - MessageState::Cancelled => { - self.error_image.set_tooltip_text(Some(&gettext( - "An error occurred with the sending queue", - ))); + MessageState::PermanentError => { stack.set_visible_child_name("error"); obj.set_visible(true); } MessageState::Edited => { if matches!( prev_state, - MessageState::Sending | MessageState::Error | MessageState::Cancelled + MessageState::Sending + | MessageState::RecoverableError + | MessageState::PermanentError ) { // Show the sent icon. stack.set_visible_child_name("sent"); diff --git a/src/session/view/content/room_history/message_row/message_state_stack.ui b/src/session/view/content/room_history/message_row/message_state_stack.ui index e1197e0a..9a4c491e 100644 --- a/src/session/view/content/room_history/message_row/message_state_stack.ui +++ b/src/session/view/content/room_history/message_row/message_state_stack.ui @@ -20,13 +20,29 @@ + + + warning + + + center + warning-symbolic + Temporary Error Sending Message + + + + + error - + center error-symbolic + Message Cannot Be Sent diff --git a/src/session/view/content/room_history/message_row/text/widgets.rs b/src/session/view/content/room_history/message_row/text/widgets.rs index 625dbddd..98fb0f7e 100644 --- a/src/session/view/content/room_history/message_row/text/widgets.rs +++ b/src/session/view/content/room_history/message_row/text/widgets.rs @@ -222,7 +222,7 @@ fn widget_for_html_block( w.add_css_class("quote"); w } - MatrixElement::P | MatrixElement::Div | MatrixElement::Li | MatrixElement::Summary => { + MatrixElement::P | MatrixElement::Div(_) | MatrixElement::Li | MatrixElement::Summary => { widget_for_html_nodes(node.children(), config, add_ellipsis, sender_name)? } MatrixElement::Ul => { diff --git a/src/session/view/content/room_history/message_toolbar/mod.rs b/src/session/view/content/room_history/message_toolbar/mod.rs index cb893d36..49ed3f4d 100644 --- a/src/session/view/content/room_history/message_toolbar/mod.rs +++ b/src/session/view/content/room_history/message_toolbar/mod.rs @@ -8,10 +8,12 @@ use gtk::{ glib::{self, clone}, CompositeTemplate, }; +use image::ImageFormat; use matrix_sdk::attachment::{ generate_image_thumbnail, AttachmentConfig, AttachmentInfo, BaseFileInfo, BaseImageInfo, - Thumbnail, + ThumbnailFormat, }; +use matrix_sdk_ui::timeline::{EditInfo, RepliedToInfo}; use ruma::{ events::{ room::message::{ @@ -540,6 +542,20 @@ impl MessageToolbar { imp.message_entry.grab_focus(); } + /// The relation to send with the current message. + fn send_relation(&self) -> Option { + let related_event_item = self.related_event()?.item(); + match self.related_event_type() { + RelatedEventType::None => None, + RelatedEventType::Reply => Some(SendRelation::Reply( + related_event_item.replied_to_info().ok()?, + )), + RelatedEventType::Edit => { + Some(SendRelation::Edit(related_event_item.edit_info().ok()?)) + } + } + } + /// Get an iterator over chunks of the message entry's text between the /// given start and end, split by mentions. fn split_buffer_mentions(&self, start: gtk::TextIter, end: gtk::TextIter) -> SplitMentions { @@ -636,35 +652,36 @@ impl MessageToolbar { let matrix_timeline = room.timeline().matrix_timeline(); // Send event depending on relation. - match self - .related_event() - .map(|event| (self.related_event_type(), event.item())) - { - Some((RelatedEventType::Reply, reply_item)) => { + match self.send_relation() { + Some(SendRelation::Reply(replied_to_info)) => { let handle = spawn_tokio!(async move { matrix_timeline - .send_reply(content, &reply_item, ForwardThread::Yes) + .send_reply(content, replied_to_info, ForwardThread::Yes) .await }); if let Err(error) = handle.await.unwrap() { error!("Could not send reply: {error}"); + toast!(self, gettext("Could not send reply")); } } - Some((RelatedEventType::Edit, edit_item)) => { + Some(SendRelation::Edit(edit_info)) => { let handle = - spawn_tokio!(async move { matrix_timeline.edit(content, &edit_item).await }); + spawn_tokio!(async move { matrix_timeline.edit(content, edit_info).await }); if let Err(error) = handle.await.unwrap() { error!("Could not send edit: {error}"); + toast!(self, gettext("Could not send edit")); } } _ => { - spawn_tokio!(async move { + let handle = spawn_tokio!(async move { matrix_timeline .send(content.with_relation(None).into()) .await - }) - .await - .unwrap(); + }); + if let Err(error) = handle.await.unwrap() { + error!("Could not send message: {error}"); + toast!(self, gettext("Could not send message")); + } } } @@ -785,9 +802,12 @@ impl MessageToolbar { .add_mentions(Mentions::default()); let matrix_timeline = room.timeline().matrix_timeline(); - spawn_tokio!(async move { matrix_timeline.send(content.into()).await }) - .await - .unwrap(); + let handle = spawn_tokio!(async move { matrix_timeline.send(content.into()).await }); + + if let Err(error) = handle.await.unwrap() { + error!("Could not send location: {error}"); + toast!(self, gettext("Could not send location")) + } } /// Show a toast for the given location error; @@ -818,14 +838,13 @@ impl MessageToolbar { let handle = spawn_tokio!(async move { // The method will filter compatible mime types so we don't need to, // since we ignore errors. - let thumbnail = match generate_image_thumbnail(&mime, Cursor::new(&bytes), None) { - Ok((data, info)) => Some(Thumbnail { - data, - content_type: mime.clone(), - info: Some(info), - }), - _ => None, - }; + let thumbnail = generate_image_thumbnail( + &mime, + Cursor::new(&bytes), + None, + ThumbnailFormat::Fallback(ImageFormat::Jpeg), + ) + .ok(); let config = if let Some(thumbnail) = thumbnail { AttachmentConfig::with_thumbnail(thumbnail) @@ -840,7 +859,8 @@ impl MessageToolbar { }); if let Err(error) = handle.await.unwrap() { - error!("Failed to send attachment: {error}"); + error!("Could not send file: {error}"); + toast!(self, gettext("Could not send file")); } } @@ -1177,3 +1197,13 @@ impl SplitMentions { } } } + +/// The possible relations to send with a message. +#[derive(Debug)] +enum SendRelation { + /// Send a reply with the given replied to info. + Reply(RepliedToInfo), + + /// Send an edit with the given edit info. + Edit(EditInfo), +}