bump matrix-sdk to ebcb2024d14614b8c984c5b95de5df04eec7933b

Get an updated ruma to handle push rules.
This commit is contained in:
Kévin Commaille 2021-04-12 16:00:18 +02:00 committed by Julian Sparber
parent bde79fcc85
commit 1aff564e7c
24 changed files with 454 additions and 521 deletions

501
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -79,5 +79,5 @@ features = ["serde"]
[dependencies.matrix-sdk]
git = "https://github.com/matrix-org/matrix-rust-sdk.git"
rev = "e437aea01213338d7f11787411a025b6133efcff"
rev = "ebcb2024d14614b8c984c5b95de5df04eec7933b"
features = ["unstable-synapse-quirks", "socks"]

View file

@ -12,7 +12,6 @@ use matrix_sdk::{
},
identifiers::{RoomId, UserId},
};
use url::Url;
#[derive(Debug, Clone, Copy)]
pub enum SearchType {
@ -47,11 +46,7 @@ impl AppOp {
}
MembershipState::Join => {
let m = Member {
avatar: ev
.content
.avatar_url
.and_then(|u| Url::parse(&u).ok())
.map(Either::Left),
avatar: ev.content.avatar_url.map(Either::Left),
alias: ev.content.displayname,
uid: sender,
};

View file

@ -616,7 +616,7 @@ async fn attach_file(session_client: MatrixClient, mut msg: Message) -> Result<(
let thumb_url = extra_content.clone().and_then(|c| c.info.thumbnail_url);
match (msg.url.clone(), msg.local_path.as_ref(), thumb_url) {
(Some(url), _, Some(thumb)) if url.scheme() == "mxc" && thumb.scheme() == "mxc" => {
(Some(_), _, Some(_)) => {
send_msg_and_manage(session_client, msg).await;
Ok(())
@ -625,7 +625,7 @@ async fn attach_file(session_client: MatrixClient, mut msg: Message) -> Result<(
if let Some(ref local_path_thumb) = msg.local_path_thumb {
let response = room::upload_file(session_client.clone(), local_path_thumb)
.await
.and_then(|response| Url::parse(&response.content_uri).map_err(Into::into));
.map(|response| response.content_uri);
match response {
Ok(thumb_uri) => {
@ -648,7 +648,7 @@ async fn attach_file(session_client: MatrixClient, mut msg: Message) -> Result<(
let query = room::upload_file(session_client.clone(), &local_path)
.await
.and_then(|response| {
msg.url = Some(Url::parse(&response.content_uri)?);
msg.url = Some(response.content_uri);
RUNTIME.spawn(send_msg_and_manage(session_client, msg.clone()));
Ok(msg)

View file

@ -1,12 +1,11 @@
use crate::backend::room;
use crate::util::i18n::{i18n, i18n_k, ni18n_f};
use log::{error, warn};
use matrix_sdk::events::EventType;
use matrix_sdk::identifiers::RoomId;
use matrix_sdk::{events::EventType, identifiers::MxcUri};
use std::convert::TryInto;
use std::fs::remove_file;
use std::os::unix::fs;
use url::Url;
use gtk::prelude::*;
@ -442,7 +441,7 @@ impl AppOp {
}
}
pub fn set_room_avatar(&mut self, room_id: RoomId, avatar: Option<Url>) {
pub fn set_room_avatar(&mut self, room_id: RoomId, avatar: Option<MxcUri>) {
let login_data = unwrap_or_unit_return!(self.login_data.clone());
if avatar.is_none() {
if let Ok(dest) = cache_dir_path(None, &room_id.to_string()) {

View file

@ -1,7 +1,7 @@
use matrix_sdk::identifiers::{Error as IdentifierError, ServerName};
use matrix_sdk::Client as MatrixClient;
use matrix_sdk::Error as MatrixError;
use std::convert::{TryFrom, TryInto};
use std::convert::TryFrom;
use url::ParseError as UrlError;
use crate::globals;
@ -112,8 +112,8 @@ pub async fn room_search(
let rooms = response
.chunk
.into_iter()
.map(TryInto::try_into)
.collect::<Result<Vec<Room>, UrlError>>()?;
.map(Into::into)
.collect::<Vec<Room>>();
for room in &rooms {
if let Some(avatar) = room.avatar.as_ref() {

View file

@ -1,10 +1,9 @@
use super::MediaError;
use crate::globals;
use matrix_sdk::identifiers::{EventId, RoomId};
use matrix_sdk::identifiers::{EventId, MxcUri, RoomId};
use matrix_sdk::{Client as MatrixClient, Error as MatrixError};
use std::convert::TryInto;
use std::path::PathBuf;
use url::Url;
use crate::model::message::Message;
use matrix_sdk::api::r0::filter::{RoomEventFilter, UrlFilter};
@ -16,7 +15,7 @@ use super::{dw_media, get_prev_batch_from, ContentType};
pub type MediaResult = Result<PathBuf, MediaError>;
pub type MediaList = (Vec<Message>, String);
pub async fn get_thumb(session_client: MatrixClient, media: &Url) -> MediaResult {
pub async fn get_thumb(session_client: MatrixClient, media: &MxcUri) -> MediaResult {
dw_media(
session_client,
media,
@ -26,7 +25,7 @@ pub async fn get_thumb(session_client: MatrixClient, media: &Url) -> MediaResult
.await
}
pub async fn get_media(session_client: MatrixClient, media: &Url) -> MediaResult {
pub async fn get_media(session_client: MatrixClient, media: &MxcUri) -> MediaResult {
dw_media(session_client, media, ContentType::Download, None).await
}
@ -74,7 +73,11 @@ async fn get_room_media_list(
})),
});
let response = session_client.room_messages(request).await?;
let room = unwrap_or_notfound_return!(
session_client.get_room(room_id),
format!("Could not find room: {}", room_id)
);
let response = room.messages(request).await?;
let prev_batch = response.end.unwrap_or_default();

View file

@ -1,16 +1,14 @@
use lazy_static::lazy_static;
use log::error;
use matrix_sdk::identifiers::{EventId, RoomId, ServerName};
use matrix_sdk::identifiers::{Error as IdentifierError, EventId, MxcUri, RoomId};
use matrix_sdk::{
api::{error::ErrorKind as RumaErrorKind, Error as RumaClientError},
Client as MatrixClient, Error as MatrixError, FromHttpResponseError, HttpError, ServerError,
};
use regex::Regex;
use std::convert::TryFrom;
use std::fmt::Debug;
use std::io::Error as IoError;
use std::path::PathBuf;
use url::Url;
use crate::client::Client;
use crate::util::cache_dir_path;
@ -68,7 +66,6 @@ pub async fn get_prev_batch_from(
#[derive(Debug)]
pub enum MediaError {
MalformedMxcUrl,
Io(IoError),
Matrix(MatrixError),
}
@ -89,38 +86,21 @@ impl HandleError for MediaError {}
pub async fn dw_media(
session_client: MatrixClient,
mxc: &Url,
mxc: &MxcUri,
media_type: ContentType,
dest: Option<PathBuf>,
) -> Result<PathBuf, MediaError> {
if mxc.scheme() != "mxc" {
return Err(MediaError::MalformedMxcUrl);
if !mxc.is_valid() {
return Err(MatrixError::from(IdentifierError::InvalidMxcUri).into());
}
let server_name = mxc
.host()
.as_ref()
.map(ToString::to_string)
.and_then(|host| {
<&ServerName>::try_from(host.as_str())
.map(ToOwned::to_owned)
.ok()
})
.ok_or(MediaError::MalformedMxcUrl)?;
let media_id = mxc
.path_segments()
.and_then(|mut ps| ps.next())
.filter(|s| !s.is_empty())
.ok_or(MediaError::MalformedMxcUrl)?;
let default_fname = || {
let dir = if media_type.is_thumbnail() {
"thumbs"
} else {
"medias"
};
cache_dir_path(Some(dir), &media_id)
cache_dir_path(Some(dir), mxc.media_id().unwrap())
};
let fname = dest.clone().map_or_else(default_fname, Ok)?;
@ -137,18 +117,17 @@ pub async fn dw_media(
}
let media = if let ContentType::Thumbnail(width, height) = media_type {
let request = assign!(GetContentThumbnailRequest::new(
&media_id,
&server_name,
let request = assign!(GetContentThumbnailRequest::from_url(
mxc,
width.into(),
height.into(),
), {
).unwrap(), {
method: Some(Method::Crop),
});
session_client.send(request, None).await?.file
} else {
let request = GetContentRequest::new(&media_id, &server_name);
let request = GetContentRequest::from_url(mxc).unwrap();
session_client.send(request, None).await?.file
};

View file

@ -3,16 +3,15 @@ use serde_json::json;
use matrix_sdk::{
api::error::ErrorKind as RumaErrorKind,
identifiers::{EventId, RoomId, RoomIdOrAliasId, UserId},
identifiers::{EventId, MxcUri, RoomId, RoomIdOrAliasId, UserId},
Client as MatrixClient, Error as MatrixError, FromHttpResponseError, HttpError, ServerError,
};
use serde::Serialize;
use std::io::Error as IoError;
use std::path::Path;
use url::{ParseError as UrlError, Url};
use url::ParseError as UrlError;
use std::convert::{TryFrom, TryInto};
use std::time::Duration;
use crate::globals;
@ -42,10 +41,9 @@ use matrix_sdk::api::r0::room::create_room::Request as CreateRoomRequest;
use matrix_sdk::api::r0::room::create_room::RoomPreset;
use matrix_sdk::api::r0::room::Visibility;
use matrix_sdk::api::r0::state::get_state_events_for_key::Request as GetStateEventForKeyRequest;
use matrix_sdk::api::r0::state::send_state_event_for_key::Request as SendStateEventForKeyRequest;
use matrix_sdk::api::r0::state::send_state_event::Request as SendStateEventForKeyRequest;
use matrix_sdk::api::r0::tag::create_tag::Request as CreateTagRequest;
use matrix_sdk::api::r0::tag::delete_tag::Request as DeleteTagRequest;
use matrix_sdk::api::r0::typing::create_typing_event::Typing;
use matrix_sdk::assign;
use matrix_sdk::events::room::avatar::AvatarEventContent;
use matrix_sdk::events::room::history_visibility::HistoryVisibility;
@ -154,7 +152,7 @@ impl HandleError for RoomAvatarError {}
pub async fn get_room_avatar(
session_client: MatrixClient,
room_id: RoomId,
) -> Result<(RoomId, Option<Url>), RoomAvatarError> {
) -> Result<(RoomId, Option<MxcUri>), RoomAvatarError> {
let request = GetStateEventForKeyRequest::new(&room_id, EventType::RoomAvatar, "");
let response = match session_client.send(request, None).await {
@ -166,7 +164,7 @@ pub async fn get_room_avatar(
let avatar = if let Some(res) = response {
serde_json::to_value(&res.content)?["url"]
.as_str()
.and_then(|s| Url::parse(s).ok())
.and_then(|s| MxcUri::try_from(s).ok())
} else {
None
};
@ -213,11 +211,7 @@ pub async fn get_room_members(
let request = JoinedMembersRequest::new(&room_id);
let response = session_client.send(request, None).await?;
let ms = response
.joined
.into_iter()
.map(Member::try_from)
.collect::<Result<_, UrlError>>()?;
let ms = response.joined.into_iter().map(Into::into).collect();
Ok((room_id, ms))
}
@ -254,7 +248,11 @@ pub async fn get_room_messages(
})),
});
let response = session_client.room_messages(request).await?;
let room = unwrap_or_notfound_return!(
session_client.get_room(&room_id),
format!("Could not find room: {}", room_id)
);
let response = room.messages(request).await?;
let prev_batch = response.end;
let list: Vec<Message> = response
@ -365,9 +363,9 @@ pub async fn send_msg(session_client: MatrixClient, msg: Message) -> Result<Even
#[derive(Debug)]
pub struct SendTypingError(MatrixError);
impl From<MatrixError> for SendTypingError {
fn from(err: MatrixError) -> Self {
Self(err)
impl<T: Into<MatrixError>> From<T> for SendTypingError {
fn from(err: T) -> Self {
Self(err.into())
}
}
@ -377,9 +375,11 @@ pub async fn send_typing(
session_client: MatrixClient,
room_id: &RoomId,
) -> Result<(), SendTypingError> {
session_client
.typing_notice(room_id, Typing::Yes(Duration::from_secs(4)))
.await?;
let room = unwrap_or_notfound_return!(
session_client.get_joined_room(room_id),
format!("Could not find room: {}", room_id)
);
room.typing_notice(true).await?;
Ok(())
}
@ -459,9 +459,9 @@ pub async fn join_room(
#[derive(Debug)]
pub struct LeaveRoomError(MatrixError);
impl From<MatrixError> for LeaveRoomError {
fn from(err: MatrixError) -> Self {
Self(err)
impl<T: Into<MatrixError>> From<T> for LeaveRoomError {
fn from(err: T) -> Self {
Self(err.into())
}
}
@ -471,7 +471,11 @@ pub async fn leave_room(
session_client: MatrixClient,
room_id: &RoomId,
) -> Result<(), LeaveRoomError> {
session_client.leave_room(room_id).await?;
let room = unwrap_or_notfound_return!(
session_client.get_joined_room(room_id),
format!("Could not find room: {}", room_id)
);
room.leave().await?;
Ok(())
}
@ -479,9 +483,9 @@ pub async fn leave_room(
#[derive(Debug)]
pub struct MarkedAsReadError(MatrixError);
impl From<MatrixError> for MarkedAsReadError {
fn from(err: MatrixError) -> Self {
Self(err)
impl<T: Into<MatrixError>> From<T> for MarkedAsReadError {
fn from(err: T) -> Self {
Self(err.into())
}
}
@ -492,9 +496,11 @@ pub async fn mark_as_read(
room_id: RoomId,
event_id: EventId,
) -> Result<(RoomId, EventId), MarkedAsReadError> {
session_client
.read_marker(&room_id, &event_id, Some(&event_id))
.await?;
let room = unwrap_or_notfound_return!(
session_client.get_joined_room(&room_id),
format!("Could not find room: {}", room_id)
);
room.read_marker(&event_id, Some(&event_id)).await?;
Ok((room_id, event_id))
}
@ -841,9 +847,9 @@ pub async fn add_to_fav(
#[derive(Debug)]
pub struct InviteError(MatrixError);
impl From<MatrixError> for InviteError {
fn from(err: MatrixError) -> Self {
Self(err)
impl<T: Into<MatrixError>> From<T> for InviteError {
fn from(err: T) -> Self {
Self(err.into())
}
}
@ -854,7 +860,11 @@ pub async fn invite(
room_id: &RoomId,
user_id: &UserId,
) -> Result<(), InviteError> {
session_client.invite_user_by_id(room_id, user_id).await?;
let room = unwrap_or_notfound_return!(
session_client.get_joined_room(room_id),
format!("Could not find room: {}", room_id)
);
room.invite_user_by_id(user_id).await?;
Ok(())
}

View file

@ -11,7 +11,6 @@ use crate::appop::UserInfoCache;
use crate::backend::HTTP_CLIENT;
use crate::util::cache_dir_path;
use log::error;
use std::convert::TryInto;
use std::path::PathBuf;
use super::room::AttachedFileError;
@ -496,12 +495,7 @@ pub async fn search(
let request = UserDirectoryRequest::new(search_term);
let response = session_client.send(request, None).await?;
response
.results
.into_iter()
.map(TryInto::try_into)
.collect::<Result<_, UrlError>>()
.map_err(Into::into)
Ok(response.results.into_iter().map(Into::into).collect())
}
#[derive(Debug)]
@ -538,16 +532,12 @@ pub async fn get_user_avatar(
let request = GetProfileRequest::new(user_id);
let response = session_client.send(request, None).await?;
let img = match response
.avatar_url
.map(|url| Url::parse(&url))
.transpose()?
.map(|url| {
(
url,
cache_dir_path(None, user_id.as_str()).map_err(MediaError::from),
)
}) {
let img = match response.avatar_url.map(|url| {
(
url,
cache_dir_path(None, user_id.as_str()).map_err(MediaError::from),
)
}) {
Some((url, Ok(dest))) => {
dw_media(
session_client,

View file

@ -5,13 +5,12 @@ use async_trait::async_trait;
use gio::prelude::*;
use matrix_sdk::{
reqwest, Client as MatrixClient, ClientConfig as MatrixClientConfig, Error as MatrixSdkError,
HttpError, HttpSend,
HttpError, HttpSend, RequestConfig,
};
use url::Url;
use std::convert::TryInto;
use std::sync::{Arc, Mutex};
use std::time::Duration;
// Special URI used by gio to indicate no proxy
const PROXY_DIRECT_URI: &str = "direct://";
@ -133,9 +132,9 @@ impl HttpSend for Client {
async fn send_request(
&self,
req: http::Request<Vec<u8>>,
duration: Option<Duration>,
config: RequestConfig,
) -> Result<http::Response<Vec<u8>>, HttpError> {
self.get_client().send_request(req, duration).await
self.get_client().send_request(req, config).await
}
}

View file

@ -2,15 +2,15 @@
#[macro_use]
extern crate glib;
#[macro_use]
mod util;
mod api;
mod backend;
mod cache;
mod client;
mod config;
mod error;
mod globals;
#[macro_use]
mod util;
mod cache;
mod model;
mod passwd;
mod ui;

View file

@ -1,10 +1,10 @@
use matrix_sdk::identifiers::MxcUri;
use serde::{Deserialize, Serialize};
use serde_json::Value as JsonValue;
use url::Url;
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Info {
pub thumbnail_url: Option<Url>,
pub thumbnail_url: Option<MxcUri>,
pub thumbnail_info: Option<JsonValue>,
pub w: Option<u32>,
pub h: Option<u32>,

View file

@ -1,17 +1,15 @@
use either::Either;
use matrix_sdk::api::r0::membership::joined_members::RoomMember;
use matrix_sdk::api::r0::user_directory::search_users::User;
use matrix_sdk::identifiers::UserId;
use matrix_sdk::{api::r0::membership::joined_members::RoomMember, identifiers::MxcUri};
use std::collections::HashMap;
use std::convert::TryFrom;
use std::path::PathBuf;
use url::{ParseError as UrlError, Url};
#[derive(Debug, Clone)]
pub struct Member {
pub uid: UserId,
pub alias: Option<String>,
pub avatar: Option<Either<Url, PathBuf>>,
pub avatar: Option<Either<MxcUri, PathBuf>>,
}
impl Member {
@ -31,37 +29,23 @@ impl PartialEq for Member {
}
}
impl TryFrom<User> for Member {
type Error = UrlError;
fn try_from(user: User) -> Result<Self, Self::Error> {
Ok(Self {
impl From<User> for Member {
fn from(user: User) -> Self {
Self {
uid: user.user_id,
alias: user.display_name,
avatar: user
.avatar_url
.filter(|a| !a.is_empty())
.map(|url| Url::parse(&url))
.transpose()?
.map(Either::Left),
})
avatar: user.avatar_url.map(Either::Left),
}
}
}
impl TryFrom<(UserId, RoomMember)> for Member {
type Error = UrlError;
fn try_from((uid, roommember): (UserId, RoomMember)) -> Result<Self, Self::Error> {
Ok(Member {
impl From<(UserId, RoomMember)> for Member {
fn from((uid, roommember): (UserId, RoomMember)) -> Self {
Self {
uid,
alias: roommember.display_name,
avatar: roommember
.avatar_url
.filter(|url| !url.is_empty())
.map(|url| Url::parse(&url))
.transpose()?
.map(Either::Left),
})
avatar: roommember.avatar_url.map(Either::Left),
}
}
}

View file

@ -2,19 +2,18 @@ use chrono::prelude::*;
use chrono::DateTime;
use matrix_sdk::{
events::{
room::message::{MessageEventContent, RedactedMessageEventContent, Relation},
room::message::{MessageEventContent, MessageType, RedactedMessageEventContent, Relation},
sticker::{RedactedStickerEventContent, StickerEventContent},
AnyMessageEvent, AnyRedactedMessageEvent, AnyRedactedSyncMessageEvent, AnyRoomEvent,
AnySyncMessageEvent, AnySyncRoomEvent, EventContent, MessageEvent, RedactedMessageEvent,
},
identifiers::{EventId, RoomId, UserId},
identifiers::{EventId, MxcUri, RoomId, UserId},
};
use serde_json::Value as JsonValue;
use std::cmp::Ordering;
use std::collections::HashMap;
use std::convert::TryFrom;
use std::path::PathBuf;
use url::Url;
//FIXME make properties private
#[derive(Debug, Clone)]
@ -24,9 +23,9 @@ pub struct Message {
pub body: String,
pub date: DateTime<Local>,
pub room: RoomId,
pub thumb: Option<Url>,
pub thumb: Option<MxcUri>,
pub local_path_thumb: Option<PathBuf>,
pub url: Option<Url>,
pub url: Option<MxcUri>,
pub local_path: Option<PathBuf>,
// FIXME: This should be a required field but it is mandatory
// to do it this way because because this struct is used both
@ -105,71 +104,68 @@ impl From<MessageEvent<MessageEventContent>> for Message {
extra_content: None,
};
match msg.content {
MessageEventContent::Audio(content) => Self {
match msg.content.msgtype {
MessageType::Audio(content) => Self {
mtype: String::from("m.audio"),
body: content.body,
url: content.url.and_then(|u| Url::parse(&u).ok()),
url: content.url,
..initial_message
},
MessageEventContent::File(content) => {
let url = content.url.and_then(|u| Url::parse(&u).ok());
Self {
mtype: String::from("m.file"),
body: content.body,
url: url.clone(),
thumb: content
.info
.and_then(|c_info| Url::parse(&c_info.thumbnail_url?).ok())
.or(url),
..initial_message
}
}
MessageEventContent::Image(content) => {
let url = content.url.and_then(|u| Url::parse(&u).ok());
Self {
mtype: String::from("m.image"),
body: content.body,
url: url.clone(),
thumb: content
.info
.and_then(|c_info| Url::parse(&c_info.thumbnail_url?).ok())
.or(url),
..initial_message
}
}
MessageEventContent::Video(content) => {
let url = content.url.and_then(|u| Url::parse(&u).ok());
Self {
mtype: String::from("m.video"),
body: content.body,
url: url.clone(),
thumb: content
.info
.and_then(|c_info| Url::parse(&c_info.thumbnail_url?).ok())
.or(url),
..initial_message
}
}
MessageEventContent::Text(content) => {
MessageType::File(content) => Self {
mtype: String::from("m.file"),
body: content.body,
url: content.url.clone(),
thumb: content
.info
.map(|i| i.thumbnail_url.filter(|u| u.is_valid()))
.flatten()
.or(content.url),
..initial_message
},
MessageType::Image(content) => Self {
mtype: String::from("m.image"),
body: content.body,
url: content.url.clone(),
thumb: content
.info
.map(|i| i.thumbnail_url.filter(|u| u.is_valid()))
.flatten()
.or(content.url),
..initial_message
},
MessageType::Video(content) => Self {
mtype: String::from("m.video"),
body: content.body,
url: content.url.clone(),
thumb: content
.info
.map(|i| i.thumbnail_url.filter(|u| u.is_valid()))
.flatten()
.or(content.url),
..initial_message
},
MessageType::Text(content) => {
let (in_reply_to, replace) =
content.relates_to.map_or(Default::default(), |r| match r {
Relation::Replacement(rep) => (None, Some(rep.event_id)),
Relation::Reply { in_reply_to } => (Some(in_reply_to.event_id), None),
_ => (None, None),
});
let (body, formatted, in_reply_to) = content
msg.content
.relates_to
.map_or(Default::default(), |r| match r {
Relation::Replacement(rep) => (None, Some(rep.event_id)),
Relation::Reply { in_reply_to } => (Some(in_reply_to.event_id), None),
_ => (None, None),
});
let (body, formatted, in_reply_to) = msg
.content
.new_content
.and_then(|nc| {
// FIXME: this could go wrong if a text message wasn't replaced with a text
// message.
if let MessageEventContent::Text(nc) = *nc {
if let MessageType::Text(c) = nc.msgtype {
let in_reply_to = nc.relates_to.and_then(|r| match r {
Relation::Reply { in_reply_to } => Some(in_reply_to.event_id),
_ => None,
});
Some((nc.body, nc.formatted, in_reply_to))
Some((c.body, c.formatted, in_reply_to))
} else {
None
}
@ -189,7 +185,7 @@ impl From<MessageEvent<MessageEventContent>> for Message {
..initial_message
}
}
MessageEventContent::Emote(content) => {
MessageType::Emote(content) => {
let (formatted_body, format): (Option<String>, Option<String>) =
content.formatted.map_or((None, None), |f| {
(Some(f.body), Some(f.format.as_str().into()))
@ -202,30 +198,33 @@ impl From<MessageEvent<MessageEventContent>> for Message {
..initial_message
}
}
MessageEventContent::Location(content) => Self {
MessageType::Location(content) => Self {
mtype: String::from("m.location"),
body: content.body,
..initial_message
},
MessageEventContent::Notice(content) => {
MessageType::Notice(content) => {
let (in_reply_to, replace) =
content.relates_to.map_or(Default::default(), |r| match r {
Relation::Replacement(rep) => (None, Some(rep.event_id)),
Relation::Reply { in_reply_to } => (Some(in_reply_to.event_id), None),
_ => (None, None),
});
let (body, formatted, in_reply_to) = content
msg.content
.relates_to
.map_or(Default::default(), |r| match r {
Relation::Replacement(rep) => (None, Some(rep.event_id)),
Relation::Reply { in_reply_to } => (Some(in_reply_to.event_id), None),
_ => (None, None),
});
let (body, formatted, in_reply_to) = msg
.content
.new_content
.and_then(|nc| {
// FIXME: this could go wrong if a notice message wasn't replaced with a
// notice message.
if let MessageEventContent::Notice(nc) = *nc {
if let MessageType::Notice(c) = nc.msgtype {
let in_reply_to = nc.relates_to.and_then(|r| match r {
Relation::Reply { in_reply_to } => Some(in_reply_to.event_id),
_ => None,
});
Some((nc.body, nc.formatted, in_reply_to))
Some((c.body, c.formatted, in_reply_to))
} else {
None
}
@ -245,7 +244,7 @@ impl From<MessageEvent<MessageEventContent>> for Message {
..initial_message
}
}
MessageEventContent::ServerNotice(content) => Self {
MessageType::ServerNotice(content) => Self {
mtype: String::from("m.server_notice"),
body: content.body,
..initial_message
@ -287,7 +286,6 @@ impl From<RedactedMessageEvent<RedactedMessageEventContent>> for Message {
impl From<MessageEvent<StickerEventContent>> for Message {
fn from(msg: MessageEvent<StickerEventContent>) -> Self {
let source = serde_json::to_string_pretty(&msg).ok();
let url = Url::parse(&msg.content.url).ok();
Self {
sender: msg.sender,
@ -298,14 +296,14 @@ impl From<MessageEvent<StickerEventContent>> for Message {
id: Some(msg.event_id),
mtype: String::from(msg.content.event_type()),
body: msg.content.body,
url: url.clone(),
url: Some(msg.content.url.clone()),
local_path: None,
thumb: msg
.content
.info
.thumbnail_url
.and_then(|thumb| Url::parse(&thumb).ok())
.or(url),
.filter(|u| u.is_valid())
.or(Some(msg.content.url)),
local_path_thumb: None,
formatted_body: None,
format: None,

View file

@ -7,7 +7,6 @@ use chrono::DateTime;
use chrono::Utc;
use either::Either;
use log::{debug, info};
use matrix_sdk::deserialized_responses::SyncResponse;
use matrix_sdk::directory::PublicRoomsChunk;
use matrix_sdk::events::{
room::member::{MemberEventContent, MembershipState},
@ -15,11 +14,11 @@ use matrix_sdk::events::{
AnySyncEphemeralRoomEvent, AnySyncRoomEvent, AnySyncStateEvent, SyncStateEvent,
};
use matrix_sdk::identifiers::{EventId, RoomAliasId, RoomId, UserId};
use matrix_sdk::{deserialized_responses::SyncResponse, identifiers::MxcUri};
use serde::{Deserialize, Serialize};
use serde_json::value::Value;
use std::collections::{BTreeMap, HashMap, HashSet};
use std::convert::{TryFrom, TryInto};
use url::{ParseError as UrlError, Url};
#[derive(Debug, Clone, PartialEq)]
pub enum RoomMembership {
@ -114,7 +113,7 @@ struct CustomDirectEvent {
#[derive(Debug, Clone)]
pub struct Room {
pub id: RoomId,
pub avatar: Option<Url>,
pub avatar: Option<MxcUri>,
pub name: Option<String>,
pub topic: Option<String>,
pub alias: Option<RoomAliasId>,
@ -227,12 +226,10 @@ impl Room {
avatar: stevents
.iter()
.find_map(|event| match event {
AnySyncStateEvent::RoomAvatar(ev) => Some(ev.content.url.as_deref()),
AnySyncStateEvent::RoomAvatar(ev) => Some(ev.content.url.clone()),
_ => None,
})
.flatten()
.map(Url::parse)
.and_then(Result::ok),
.flatten(),
alias: stevents
.iter()
.find_map(|event| match event {
@ -280,7 +277,11 @@ impl Room {
AnyBasicEvent::Custom(ev)
if ev.content.event_type == "org.gnome.fractal.language" =>
{
ev.content.json["input_language"].as_str()
ev.content
.data
.get("input_language")
.map(|v| v.as_str())
.flatten()
}
_ => None,
})
@ -360,7 +361,7 @@ impl Room {
let kicker = message.sender().clone();
if kicker != user_id {
if let AnyMessageEventContent::Custom(message) = message.content() {
if let Value::String(kick_reason) = &message.json["reason"] {
if let Some(Value::String(kick_reason)) = &message.data.get("reason") {
let reason = Reason::Kicked(kick_reason.clone(), kicker);
return Self::new(k.clone(), RoomMembership::Left(reason));
}
@ -416,14 +417,10 @@ impl Room {
avatar: stevents
.iter()
.find_map(|event| match event {
AnyStrippedStateEvent::RoomAvatar(ev) => {
Some(ev.content.url.as_deref())
}
AnyStrippedStateEvent::RoomAvatar(ev) => Some(ev.content.url.clone()),
_ => None,
})
.flatten()
.map(Url::parse)
.and_then(Result::ok),
.flatten(),
alias: stevents
.iter()
.find_map(|event| match event {
@ -457,24 +454,18 @@ impl Room {
}
}
impl TryFrom<PublicRoomsChunk> for Room {
type Error = UrlError;
fn try_from(input: PublicRoomsChunk) -> Result<Self, Self::Error> {
Ok(Self {
impl From<PublicRoomsChunk> for Room {
fn from(input: PublicRoomsChunk) -> Self {
Self {
alias: input.canonical_alias,
name: input.name,
avatar: input
.avatar_url
.filter(|url| !url.is_empty())
.map(|url| Url::parse(&url))
.transpose()?,
avatar: input.avatar_url,
topic: input.topic,
n_members: input.num_joined_members.into(),
world_readable: input.world_readable,
guest_can_join: input.guest_can_join,
..Self::new(input.room_id, RoomMembership::None)
})
}
}
}
@ -526,14 +517,7 @@ fn parse_room_member(msg: &SyncStateEvent<MemberEventContent>) -> Option<Member>
Some(Member {
uid: msg.sender.clone(),
alias: msg.content.displayname.clone(),
avatar: msg
.content
.avatar_url
.as_ref()
.map(String::as_str)
.map(Url::parse)
.and_then(Result::ok)
.map(Either::Left),
avatar: msg.content.avatar_url.clone().map(Either::Left),
})
} else {
None

View file

@ -280,7 +280,7 @@ impl AccountSettings {
1,
);
}
Medium::MSISDN => {
Medium::Msisdn => {
let s = if first_phone {
empty_phone.update(Some(item.address));
first_phone = false;

View file

@ -81,6 +81,15 @@ macro_rules! unwrap_or_unit_return {
};
}
macro_rules! unwrap_or_notfound_return {
($x:expr, $msg:expr) => {
match $x {
Some(a) => a,
None => return Err(::std::io::Error::new(::std::io::ErrorKind::NotFound, $msg).into()),
}
};
}
pub trait ResultExpectLog {
fn expect_log(&self, log: &str);
}

View file

@ -11,14 +11,13 @@ use glib::source::Continue;
use gtk::prelude::*;
use gtk::DrawingArea;
use log::error;
use matrix_sdk::Client as MatrixClient;
use matrix_sdk::{identifiers::MxcUri, Client as MatrixClient};
use std::path::{Path, PathBuf};
use std::sync::{Arc, Mutex};
use url::Url;
#[derive(Clone, Debug)]
pub struct Image {
pub path: Either<Url, PathBuf>,
pub path: Either<MxcUri, PathBuf>,
pub local_path: Arc<Mutex<Option<PathBuf>>>,
pub max_size: Option<(i32, i32)>,
pub widget: DrawingArea,
@ -45,7 +44,7 @@ impl Image {
/// .size(Some((50, 50)))
/// .build();
/// ```
pub fn new(path: Either<Url, PathBuf>) -> Image {
pub fn new(path: Either<MxcUri, PathBuf>) -> Image {
let da = DrawingArea::new();
da.add_events(gdk::EventMask::ENTER_NOTIFY_MASK);
da.add_events(gdk::EventMask::LEAVE_NOTIFY_MASK);
@ -266,8 +265,8 @@ impl Image {
/// in the `image` widget scaled to size
pub fn load_async(&self, session_client: MatrixClient) {
match self.path.as_ref() {
Either::Left(url) if url.scheme() == "mxc" => {
let mxc = url.clone();
Either::Left(mxc) => {
let mxc = mxc.clone();
// asyn load
let response = if self.thumb {
RUNTIME.spawn(async move { media::get_thumb(session_client, &mxc).await })
@ -302,7 +301,6 @@ impl Image {
&path,
);
}
_ => error!("The resource URL doesn't have the scheme mxc:"),
}
}
}

View file

@ -40,7 +40,7 @@ use std::ops::Deref;
use std::path::PathBuf;
use std::rc::Rc;
use matrix_sdk::Client as MatrixClient;
use matrix_sdk::{identifiers::MxcUri, Client as MatrixClient};
use url::Url;
use crate::app::RUNTIME;
@ -53,7 +53,7 @@ pub trait PlayerExt {
fn initialize_stream(
player: Rc<Self>,
session_client: MatrixClient,
media_url: Url,
media_url: MxcUri,
bx: gtk::Box,
start_playing: bool,
);
@ -499,7 +499,7 @@ impl<T: MediaPlayer + 'static> PlayerExt for T {
fn initialize_stream(
player: Rc<Self>,
session_client: MatrixClient,
media_url: Url,
media_url: MxcUri,
bx: gtk::Box,
start_playing: bool,
) {

View file

@ -15,9 +15,8 @@ use glib::source::Continue;
use gtk::prelude::*;
use gtk::Overlay;
use libhandy::HeaderBarExt;
use matrix_sdk::identifiers::UserId;
use matrix_sdk::identifiers::{MxcUri, UserId};
use matrix_sdk::Client as MatrixClient;
use url::Url;
use crate::model::{message::Message, room::Room};
@ -343,7 +342,7 @@ impl Data {
self.set_nav_btn_visibility();
}
fn create_video_widget(&self, session_client: MatrixClient, url: Url) -> VideoWidget {
fn create_video_widget(&self, session_client: MatrixClient, url: MxcUri) -> VideoWidget {
let with_controls = true;
let player = VideoPlayerWidget::new(with_controls);
let bx = gtk::Box::new(gtk::Orientation::Vertical, 0);

View file

@ -696,7 +696,6 @@ fn build_room_msg_image(session_client: MatrixClient, msg: &Message) -> BodyAndT
.msg
.thumb
.clone()
.filter(|m| m.scheme() == "mxc" || m.scheme().starts_with("http"))
.or_else(|| msg.msg.url.clone())
.map(Either::Left)
.or_else(|| Some(Either::Right(msg.msg.local_path.clone()?)));

View file

@ -1,6 +1,6 @@
use crate::util::i18n::i18n;
use glib::clone;
use matrix_sdk::identifiers::RoomId;
use matrix_sdk::identifiers::{MxcUri, RoomId};
use gtk::prelude::*;
use log::info;
@ -225,7 +225,7 @@ impl RoomListGroup {
});
}
pub fn set_room_avatar(&mut self, room_id: RoomId, av: Option<Url>) {
pub fn set_room_avatar(&mut self, room_id: RoomId, av: Option<MxcUri>) {
if let Some(r) = self.rooms.get_mut(&room_id) {
r.set_avatar(av.clone());
}
@ -635,7 +635,7 @@ impl RoomList {
});
}
pub fn set_room_avatar(&mut self, room_id: RoomId, av: Option<Url>) {
pub fn set_room_avatar(&mut self, room_id: RoomId, av: Option<MxcUri>) {
run_in_group!(self, &room_id, set_room_avatar, room_id, av);
}

View file

@ -1,5 +1,5 @@
use gtk::prelude::*;
use url::Url;
use matrix_sdk::identifiers::MxcUri;
use crate::model::room::Room;
@ -117,7 +117,7 @@ impl RoomRow {
self.text.set_text(&name);
}
pub fn set_avatar(&mut self, avatar: Option<Url>) {
pub fn set_avatar(&mut self, avatar: Option<MxcUri>) {
self.room.avatar = avatar;
let name = self.room.name.clone().unwrap_or_else(|| "...".to_string());