[fractal] API: Use RoomId from ruma-identifiers for stronger validation
- From: Daniel Garcia Moreno <danigm src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [fractal] API: Use RoomId from ruma-identifiers for stronger validation
- Date: Wed, 26 Feb 2020 07:12:10 +0000 (UTC)
commit d39244aaa06114b69df9e66ea23aa405a4bc8e3f
Author: Alejandro Domínguez <adomu net-c com>
Date: Fri Dec 27 06:10:09 2019 +0100
API: Use RoomId from ruma-identifiers for stronger validation
fractal-gtk/src/actions/global.rs | 8 +-
fractal-gtk/src/actions/room_history.rs | 10 +-
fractal-gtk/src/actions/room_settings.rs | 9 +-
fractal-gtk/src/appop/invite.rs | 11 +-
fractal-gtk/src/appop/member.rs | 12 +-
fractal-gtk/src/appop/message.rs | 15 +-
fractal-gtk/src/appop/mod.rs | 9 +-
fractal-gtk/src/appop/notifications.rs | 13 +-
fractal-gtk/src/appop/notify.rs | 3 +-
fractal-gtk/src/appop/room.rs | 311 +++++++++++-----------
fractal-gtk/src/appop/start_chat.rs | 15 +-
fractal-gtk/src/appop/state.rs | 6 +-
fractal-gtk/src/widgets/room.rs | 8 +-
fractal-gtk/src/widgets/room_history.rs | 3 +-
fractal-gtk/src/widgets/room_settings.rs | 6 +-
fractal-gtk/src/widgets/roomlist.rs | 165 ++++++------
fractal-gtk/src/widgets/roomrow.rs | 8 +-
fractal-gtk/src/widgets/scroll_widget.rs | 7 +-
fractal-matrix-api/src/backend/directory.rs | 2 +-
fractal-matrix-api/src/backend/media.rs | 13 +-
fractal-matrix-api/src/backend/mod.rs | 126 +++++----
fractal-matrix-api/src/backend/room.rs | 364 +++++++++++---------------
fractal-matrix-api/src/backend/sync.rs | 12 +-
fractal-matrix-api/src/backend/types.rs | 68 ++---
fractal-matrix-api/src/model/event.rs | 3 +-
fractal-matrix-api/src/model/message.rs | 78 +++---
fractal-matrix-api/src/model/room.rs | 31 ++-
fractal-matrix-api/src/r0/sync/sync_events.rs | 7 +-
fractal-matrix-api/src/util.rs | 5 +-
29 files changed, 668 insertions(+), 660 deletions(-)
---
diff --git a/fractal-gtk/src/actions/global.rs b/fractal-gtk/src/actions/global.rs
index fcf6742f..ae8aaaba 100644
--- a/fractal-gtk/src/actions/global.rs
+++ b/fractal-gtk/src/actions/global.rs
@@ -1,6 +1,7 @@
use fractal_api::clone;
use log::{debug, info};
use std::cell::RefCell;
+use std::convert::TryInto;
use std::rc::Rc;
use std::sync::{Arc, Mutex};
@@ -8,6 +9,7 @@ use crate::appop::AppOp;
use crate::i18n::i18n;
use crate::widgets::FileDialog::open;
use crate::App;
+use fractal_api::identifiers::RoomId;
use fractal_api::types::Message;
use gio::prelude::*;
use gio::SimpleAction;
@@ -224,7 +226,7 @@ pub fn new(app: >k::Application, op: &Arc<Mutex<AppOp>>) {
let back_weak = Rc::downgrade(&back_history);
open_room.connect_activate(clone!(op => move |_, data| {
if let Some(id) = get_room_id(data) {
- op.lock().unwrap().set_active_room_by_id(id.to_string());
+ op.lock().unwrap().set_active_room_by_id(id);
/* This does nothing if fractal is already in focus */
op.lock().unwrap().activate();
}
@@ -321,8 +323,8 @@ pub fn new(app: >k::Application, op: &Arc<Mutex<AppOp>>) {
//op.lock().unwrap().mark_active_room_messages();
}
-fn get_room_id(data: Option<&glib::Variant>) -> Option<&str> {
- data?.get_str()
+fn get_room_id(data: Option<&glib::Variant>) -> Option<RoomId> {
+ data?.get_str().and_then(|rid| rid.try_into().ok())
}
fn get_message(data: Option<&glib::Variant>) -> Option<Message> {
diff --git a/fractal-gtk/src/actions/room_history.rs b/fractal-gtk/src/actions/room_history.rs
index 1308ff63..eb9e0bdd 100644
--- a/fractal-gtk/src/actions/room_history.rs
+++ b/fractal-gtk/src/actions/room_history.rs
@@ -1,6 +1,8 @@
use fractal_api::clone;
+use fractal_api::identifiers::RoomId;
use fractal_api::r0::AccessToken;
use log::error;
+use std::convert::TryFrom;
use std::fs;
use std::sync::mpsc::channel;
use std::sync::mpsc::TryRecvError;
@@ -215,15 +217,17 @@ fn get_message_by_id(id: &str) -> Option<Message> {
op.get_message_by_id(room_id, id)
}
-fn get_room_id(data: Option<&glib::Variant>) -> Option<String> {
- data.as_ref()?.get_str().map(|s| s.to_string())
+fn get_room_id(data: Option<&glib::Variant>) -> Option<RoomId> {
+ data.as_ref()?
+ .get_str()
+ .and_then(|rid| RoomId::try_from(rid).ok())
}
fn request_more_messages(
backend: &Sender<BKCommand>,
server_url: Url,
access_token: AccessToken,
- id: Option<String>,
+ id: Option<RoomId>,
) -> Option<()> {
let op = App::get_op()?;
let op = op.lock().unwrap();
diff --git a/fractal-gtk/src/actions/room_settings.rs b/fractal-gtk/src/actions/room_settings.rs
index eaac18c4..07c294db 100644
--- a/fractal-gtk/src/actions/room_settings.rs
+++ b/fractal-gtk/src/actions/room_settings.rs
@@ -1,3 +1,4 @@
+use fractal_api::identifiers::RoomId;
use fractal_api::r0::AccessToken;
use fractal_api::url::Url;
use gio::prelude::*;
@@ -6,6 +7,7 @@ use gio::SimpleActionGroup;
use glib;
use gtk;
use gtk::prelude::*;
+use std::convert::TryFrom;
use std::sync::mpsc::Sender;
use crate::backend::BKCommand;
@@ -36,7 +38,10 @@ pub fn new(
let window_weak = window.downgrade();
let backend = backend.clone();
change_avatar.connect_activate(move |a, data| {
- if let Some(id) = data.as_ref().and_then(|x| x.get_str()) {
+ if let Some(id) = data
+ .and_then(|x| x.get_str())
+ .and_then(|rid| RoomId::try_from(rid).ok())
+ {
let window = upgrade_weak!(window_weak);
let filter = gtk::FileFilter::new();
filter.set_name(Some(i18n("Images").as_str()));
@@ -47,7 +52,7 @@ pub fn new(
let _ = backend.send(BKCommand::SetRoomAvatar(
server_url.clone(),
access_token.clone(),
- id.to_string(),
+ id,
file.to_string(),
));
} else {
diff --git a/fractal-gtk/src/appop/invite.rs b/fractal-gtk/src/appop/invite.rs
index aa5bd09c..d1e467a4 100644
--- a/fractal-gtk/src/appop/invite.rs
+++ b/fractal-gtk/src/appop/invite.rs
@@ -1,5 +1,6 @@
use crate::i18n::{i18n, i18n_k};
+use fractal_api::identifiers::RoomId;
use gtk;
use gtk::prelude::*;
@@ -209,15 +210,14 @@ impl AppOp {
dialog.resize(300, 200);
}
- pub fn remove_inv(&mut self, roomid: String) {
- self.rooms.remove(&roomid);
- self.roomlist.remove_room(roomid);
+ pub fn remove_inv(&mut self, room_id: RoomId) {
+ self.rooms.remove(&room_id);
+ self.roomlist.remove_room(room_id);
}
pub fn accept_inv(&mut self, accept: bool) {
let login_data = unwrap_or_unit_return!(self.login_data.clone());
- let rid = self.invitation_roomid.clone();
- if let Some(rid) = rid {
+ if let Some(rid) = self.invitation_roomid.take() {
if accept {
self.backend
.send(BKCommand::AcceptInv(
@@ -237,7 +237,6 @@ impl AppOp {
}
self.remove_inv(rid);
}
- self.invitation_roomid = None;
}
/* FIXME: move to a widget */
diff --git a/fractal-gtk/src/appop/member.rs b/fractal-gtk/src/appop/member.rs
index 9e60ccc3..c638337b 100644
--- a/fractal-gtk/src/appop/member.rs
+++ b/fractal-gtk/src/appop/member.rs
@@ -1,4 +1,5 @@
use fractal_api::clone;
+use fractal_api::identifiers::RoomId;
use gtk;
use gtk::prelude::*;
@@ -23,8 +24,9 @@ pub enum SearchType {
impl AppOp {
pub fn member_level(&self, member: &Member) -> i32 {
if let Some(r) = self
- .rooms
- .get(&self.active_room.clone().unwrap_or_default())
+ .active_room
+ .as_ref()
+ .and_then(|a_room| self.rooms.get(a_room))
{
if let Some(level) = r.admins.get(&member.uid) {
return *level;
@@ -33,15 +35,15 @@ impl AppOp {
0
}
- pub fn set_room_members(&mut self, roomid: String, members: Vec<Member>) {
- if let Some(r) = self.rooms.get_mut(&roomid) {
+ pub fn set_room_members(&mut self, room_id: RoomId, members: Vec<Member>) {
+ if let Some(r) = self.rooms.get_mut(&room_id) {
r.members = HashMap::new();
for m in members {
r.members.insert(m.uid.clone(), m);
}
}
- self.recalculate_room_name(roomid.clone());
+ self.recalculate_room_name(room_id.clone());
/* FIXME: update the current room settings insteat of creating a new one */
if self.room_settings.is_some() && self.state == AppState::RoomSettings {
diff --git a/fractal-gtk/src/appop/message.rs b/fractal-gtk/src/appop/message.rs
index d1c8365a..a56952a4 100644
--- a/fractal-gtk/src/appop/message.rs
+++ b/fractal-gtk/src/appop/message.rs
@@ -1,4 +1,5 @@
use comrak::{markdown_to_html, ComrakOptions};
+use fractal_api::identifiers::RoomId;
use gdk_pixbuf::Pixbuf;
use gio::prelude::FileExt;
use gtk;
@@ -29,7 +30,7 @@ pub struct TmpMsg {
}
impl AppOp {
- pub fn get_message_by_id(&self, room_id: &str, id: &str) -> Option<Message> {
+ pub fn get_message_by_id(&self, room_id: &RoomId, id: &str) -> Option<Message> {
let room = self.rooms.get(room_id)?;
room.messages
.iter()
@@ -401,18 +402,18 @@ impl AppOp {
pub fn show_room_messages_top(
&mut self,
msgs: Vec<Message>,
- roomid: String,
+ room_id: RoomId,
prev_batch: Option<String>,
) {
- if let Some(r) = self.rooms.get_mut(&roomid) {
+ if let Some(r) = self.rooms.get_mut(&room_id) {
r.prev_batch = prev_batch;
}
- let active_room = self.active_room.clone().unwrap_or_default();
+ let active_room = self.active_room.as_ref();
let mut list = vec![];
for item in msgs.iter().rev() {
/* create a list of new messages to load to the history */
- if item.room == active_room && !item.redacted {
+ if active_room.map_or(false, |a_room| item.room == *a_room) && !item.redacted {
if let Some(ui_msg) = self.create_new_room_message(item) {
list.push(ui_msg);
}
@@ -428,8 +429,8 @@ impl AppOp {
}
}
- pub fn remove_message(&mut self, room: String, id: String) -> Option<()> {
- let message = self.get_message_by_id(&room, &id);
+ pub fn remove_message(&mut self, room_id: RoomId, id: String) -> Option<()> {
+ let message = self.get_message_by_id(&room_id, &id);
if let Some(msg) = message {
self.remove_room_message(&msg);
diff --git a/fractal-gtk/src/appop/mod.rs b/fractal-gtk/src/appop/mod.rs
index 82168aaf..6fab3629 100644
--- a/fractal-gtk/src/appop/mod.rs
+++ b/fractal-gtk/src/appop/mod.rs
@@ -3,6 +3,7 @@ use std::collections::HashMap;
use std::rc::Rc;
use std::sync::mpsc::Sender;
+use fractal_api::identifiers::RoomId;
use fractal_api::r0::AccessToken;
use gtk;
@@ -66,20 +67,20 @@ pub struct AppOp {
pub login_data: Option<LoginData>,
pub device_id: Option<String>,
- pub active_room: Option<String>,
+ pub active_room: Option<RoomId>,
pub rooms: RoomList,
pub room_settings: Option<widgets::RoomSettings>,
pub history: Option<widgets::RoomHistory>,
pub roomlist: widgets::RoomList,
- pub unsent_messages: HashMap<String, (String, i32)>,
- pub typing: HashMap<String, std::time::Instant>,
+ pub unsent_messages: HashMap<RoomId, (String, i32)>,
+ pub typing: HashMap<RoomId, std::time::Instant>,
pub media_viewer: Rc<RefCell<Option<widgets::MediaViewer>>>,
pub state: AppState,
pub since: Option<String>,
- pub invitation_roomid: Option<String>,
+ pub invitation_roomid: Option<RoomId>,
pub md_enabled: bool,
pub invite_list: Vec<(Member, gtk::TextChildAnchor)>,
search_type: SearchType,
diff --git a/fractal-gtk/src/appop/notifications.rs b/fractal-gtk/src/appop/notifications.rs
index feb5d307..fee22e1d 100644
--- a/fractal-gtk/src/appop/notifications.rs
+++ b/fractal-gtk/src/appop/notifications.rs
@@ -1,17 +1,18 @@
use crate::appop::AppOp;
+use fractal_api::identifiers::RoomId;
impl AppOp {
- pub fn clear_room_notifications(&mut self, r: String) {
- self.set_room_notifications(r.clone(), 0, 0);
- self.roomlist.set_bold(r, false);
+ pub fn clear_room_notifications(&mut self, room_id: RoomId) {
+ self.set_room_notifications(room_id.clone(), 0, 0);
+ self.roomlist.set_bold(room_id, false);
}
- pub fn set_room_notifications(&mut self, roomid: String, n: i32, h: i32) {
- if let Some(r) = self.rooms.get_mut(&roomid) {
+ pub fn set_room_notifications(&mut self, room_id: RoomId, n: i32, h: i32) {
+ if let Some(r) = self.rooms.get_mut(&room_id) {
r.notifications = n;
r.highlight = h;
self.roomlist
- .set_room_notifications(roomid, r.notifications, r.highlight);
+ .set_room_notifications(room_id, r.notifications, r.highlight);
}
}
}
diff --git a/fractal-gtk/src/appop/notify.rs b/fractal-gtk/src/appop/notify.rs
index ed964c9b..4f2c1594 100644
--- a/fractal-gtk/src/appop/notify.rs
+++ b/fractal-gtk/src/appop/notify.rs
@@ -1,3 +1,4 @@
+use fractal_api::identifiers::RoomId;
use gio::ApplicationExt;
use gio::FileExt;
use gio::Notification;
@@ -40,7 +41,7 @@ impl AppOp {
inapp.set_reveal_child(false);
}
- pub fn notify(&self, app: gtk::Application, room_id: &str, id: &str) -> Option<()> {
+ pub fn notify(&self, app: gtk::Application, room_id: &RoomId, id: &str) -> Option<()> {
let server_url = self.login_data.clone()?.server_url;
let msg = self.get_message_by_id(room_id, id)?;
let r = self.rooms.get(room_id)?;
diff --git a/fractal-gtk/src/appop/room.rs b/fractal-gtk/src/appop/room.rs
index b2cb88b9..3e146e54 100644
--- a/fractal-gtk/src/appop/room.rs
+++ b/fractal-gtk/src/appop/room.rs
@@ -1,6 +1,8 @@
use crate::i18n::{i18n, i18n_k, ni18n_f};
+use fractal_api::identifiers::RoomId;
use fractal_api::url::Url;
use log::{error, warn};
+use std::convert::TryFrom;
use std::fs::remove_file;
use std::os::unix::fs;
@@ -11,6 +13,7 @@ use crate::appop::AppOp;
use crate::backend;
use crate::backend::BKCommand;
+use crate::backend::BKResponse;
use fractal_api::util::cache_dir_path;
use crate::actions;
@@ -22,9 +25,6 @@ use crate::types::{Member, Reason, Room, RoomMembership, RoomTag};
use crate::util::markup_text;
-use rand::distributions::Alphanumeric;
-use rand::{thread_rng, Rng};
-
use glib::functions::markup_escape_text;
// The TextBufferExt alias is necessary to avoid conflict with gtk's TextBufferExt
@@ -35,27 +35,25 @@ use std::time::Instant;
pub struct Force(pub bool);
impl AppOp {
- pub fn remove_room(&mut self, id: String) {
+ pub fn remove_room(&mut self, id: RoomId) {
self.rooms.remove(&id);
self.unsent_messages.remove(&id);
self.roomlist.remove_room(id);
}
- pub fn set_rooms(&mut self, mut rooms: Vec<Room>, clear_room_list: bool) {
+ pub fn set_rooms(&mut self, rooms: Vec<Room>, clear_room_list: bool) {
let login_data = unwrap_or_unit_return!(self.login_data.clone());
if clear_room_list {
self.rooms.clear();
}
let mut roomlist = vec![];
- while let Some(room) = rooms.pop() {
- if room.membership.is_left() {
- // removing left rooms
- if let RoomMembership::Left(kicked) = room.membership.clone() {
- if let Reason::Kicked(reason, kicker) = kicked {
- if let Some(r) = self.rooms.get(&room.id) {
- let room_name = r.name.clone().unwrap_or_default();
- self.kicked_room(room_name, reason, kicker.alias.unwrap_or_default());
- }
+ for room in rooms {
+ // removing left rooms
+ if let RoomMembership::Left(kicked) = room.membership.clone() {
+ if let Reason::Kicked(reason, kicker) = kicked {
+ if let Some(r) = self.rooms.get(&room.id) {
+ let room_name = r.name.clone().unwrap_or_default();
+ self.kicked_room(room_name, reason, kicker.alias.unwrap_or_default());
}
}
if self.active_room.as_ref().map_or(false, |x| x == &room.id) {
@@ -63,9 +61,8 @@ impl AppOp {
} else {
self.remove_room(room.id);
}
- } else if self.rooms.contains_key(&room.id) {
+ } else if let Some(update_room) = self.rooms.get_mut(&room.id) {
// TODO: update the existing rooms
- let update_room = self.rooms.get_mut(&room.id).unwrap();
if room.language.is_some() {
update_room.language = room.language.clone();
};
@@ -156,7 +153,7 @@ impl AppOp {
self.set_state(AppState::NoRoom);
}
- pub fn set_active_room_by_id(&mut self, id: String) {
+ pub fn set_active_room_by_id(&mut self, id: RoomId) {
let login_data = unwrap_or_unit_return!(self.login_data.clone());
if let Some(room) = self.rooms.get(&id) {
if let Some(language) = room.language.clone() {
@@ -280,9 +277,11 @@ impl AppOp {
self.update_typing_notification();
}
+ // FIXME: This should be a special case in a generic
+ // function that leaves any room in any state.
pub fn really_leave_active_room(&mut self) {
let login_data = unwrap_or_unit_return!(self.login_data.clone());
- let r = self.active_room.clone().unwrap_or_default();
+ let r = unwrap_or_unit_return!(self.active_room.clone());
self.backend
.send(BKCommand::LeaveRoom(
login_data.server_url,
@@ -299,26 +298,24 @@ impl AppOp {
}
pub fn leave_active_room(&self) {
+ let active_room = unwrap_or_unit_return!(self.active_room.clone());
+ let r = unwrap_or_unit_return!(self.rooms.get(&active_room));
+
let dialog = self
.ui
.builder
.get_object::<gtk::MessageDialog>("leave_room_dialog")
.expect("Can't find leave_room_dialog in ui file.");
- if let Some(r) = self
- .rooms
- .get(&self.active_room.clone().unwrap_or_default())
- {
- let text = i18n_k(
- "Leave {room_name}?",
- &[("room_name", &r.name.clone().unwrap_or_default())],
- );
- dialog.set_property_text(Some(text.as_str()));
- dialog.present();
- }
+ let text = i18n_k(
+ "Leave {room_name}?",
+ &[("room_name", &r.name.clone().unwrap_or_default())],
+ );
+ dialog.set_property_text(Some(text.as_str()));
+ dialog.present();
}
- pub fn kicked_room(&self, roomid: String, reason: String, kicker: String) {
+ pub fn kicked_room(&self, room_name: String, reason: String, kicker: String) {
let parent: gtk::Window = self
.ui
.builder
@@ -328,7 +325,7 @@ impl AppOp {
let parent = upgrade_weak!(parent_weak);
let viewer = widgets::KickedDialog::new();
viewer.set_parent_window(&parent);
- viewer.show(&roomid, &reason, &kicker);
+ viewer.show(&room_name, &reason, &kicker);
}
pub fn create_new_room(&mut self) {
@@ -354,7 +351,8 @@ impl AppOp {
backend::RoomType::Public
};
- let internal_id: String = thread_rng().sample_iter(&Alphanumeric).take(10).collect();
+ let internal_id = RoomId::new(&login_data.server_url.to_string())
+ .expect("The server domain should have been validated");
self.backend
.send(BKCommand::NewRoom(
login_data.server_url,
@@ -365,8 +363,11 @@ impl AppOp {
))
.unwrap();
- let mut fakeroom = Room::new(internal_id.clone(), RoomMembership::Joined(RoomTag::None));
- fakeroom.name = Some(n);
+ let fakeroom = Room {
+ name: Some(n),
+ ..Room::new(internal_id.clone(), RoomMembership::Joined(RoomTag::None))
+ };
+
self.new_room(fakeroom, None);
self.set_active_room_by_id(internal_id);
self.set_state(AppState::Room);
@@ -386,8 +387,8 @@ impl AppOp {
};
}
- pub fn set_room_detail(&mut self, roomid: String, key: String, value: Option<String>) {
- if let Some(r) = self.rooms.get_mut(&roomid) {
+ pub fn set_room_detail(&mut self, room_id: RoomId, key: String, value: Option<String>) {
+ if let Some(r) = self.rooms.get_mut(&room_id) {
let k: &str = &key;
match k {
"m.room.name" => {
@@ -400,26 +401,30 @@ impl AppOp {
};
}
- if roomid == self.active_room.clone().unwrap_or_default() {
+ if self
+ .active_room
+ .as_ref()
+ .map_or(false, |a_room| *a_room == room_id)
+ {
self.set_current_room_detail(key, value);
}
}
- pub fn set_room_avatar(&mut self, roomid: String, avatar: Option<Url>) {
+ pub fn set_room_avatar(&mut self, room_id: RoomId, avatar: Option<Url>) {
let login_data = unwrap_or_unit_return!(self.login_data.clone());
if avatar.is_none() {
- if let Ok(dest) = cache_dir_path(None, &roomid) {
+ if let Ok(dest) = cache_dir_path(None, &room_id.to_string()) {
let _ = remove_file(dest);
}
}
- if let Some(r) = self.rooms.get_mut(&roomid) {
+ if let Some(r) = self.rooms.get_mut(&room_id) {
if avatar.is_none() && r.members.len() == 2 {
for m in r.members.keys() {
if *m != login_data.uid {
//FIXME: Find a better solution
// create a symlink from user avatar to room avatar (works only on unix)
if let Ok(source) = cache_dir_path(None, m) {
- if let Ok(dest) = cache_dir_path(None, &roomid) {
+ if let Ok(dest) = cache_dir_path(None, &room_id.to_string()) {
let _ = fs::symlink(source, dest);
}
}
@@ -428,7 +433,7 @@ impl AppOp {
}
r.avatar = avatar.map(|s| s.into_string());
self.roomlist
- .set_room_avatar(roomid.clone(), r.avatar.clone());
+ .set_room_avatar(room_id.clone(), r.avatar.clone());
}
}
@@ -490,24 +495,31 @@ impl AppOp {
.ui
.builder
.get_object::<gtk::Entry>("join_room_name")
- .expect("Can't find join_room_name in ui file.");
-
- let n = name
+ .expect("Can't find join_room_name in ui file.")
.get_text()
- .map_or(String::new(), |gstr| gstr.to_string())
- .trim()
- .to_string();
+ .map_or(String::new(), |gstr| gstr.to_string());
- self.backend
- .send(BKCommand::JoinRoom(
- login_data.server_url,
- login_data.access_token,
- n.clone(),
- ))
- .unwrap();
+ match RoomId::try_from(name.trim()) {
+ Ok(room_id) => {
+ self.backend
+ .send(BKCommand::JoinRoom(
+ login_data.server_url,
+ login_data.access_token,
+ room_id,
+ ))
+ .unwrap();
+ }
+ Err(err) => {
+ self.backend
+ .send(BKCommand::SendBKResponse(BKResponse::JoinRoom(Err(
+ err.into()
+ ))))
+ .unwrap();
+ }
+ }
}
- pub fn new_room(&mut self, r: Room, internal_id: Option<String>) {
+ pub fn new_room(&mut self, r: Room, internal_id: Option<RoomId>) {
if let Some(id) = internal_id {
self.remove_room(id);
}
@@ -522,8 +534,8 @@ impl AppOp {
self.set_active_room_by_id(r.id);
}
- pub fn added_to_fav(&mut self, roomid: String, tofav: bool) {
- if let Some(ref mut r) = self.rooms.get_mut(&roomid) {
+ pub fn added_to_fav(&mut self, room_id: RoomId, tofav: bool) {
+ if let Some(ref mut r) = self.rooms.get_mut(&room_id) {
let tag = if tofav {
RoomTag::Favourite
} else {
@@ -536,60 +548,48 @@ impl AppOp {
/// This method calculate the room name when there's no room name event
/// For this we use the members in the room. If there's only one member we'll return that
/// member name, if there's more than one we'll return the first one and others
- pub fn recalculate_room_name(&mut self, roomid: String) {
+ pub fn recalculate_room_name(&mut self, room_id: RoomId) {
let login_data = unwrap_or_unit_return!(self.login_data.clone());
- if !self.rooms.contains_key(&roomid) {
+ let r = unwrap_or_unit_return!(self.rooms.get_mut(&room_id));
+
+ // we should do nothing if this room has room name
+ if r.name.is_some() {
return;
}
- let rname;
- {
- let r = self.rooms.get_mut(&roomid).unwrap();
- // we should do nothing it this room has room name
- if let Some(_) = r.name {
- return;
- }
-
- // removing one because the user should be in the room
- let n = r.members.len() - 1;
- let suid = login_data.uid;
- let mut members = r.members.iter().filter(|&(uid, _)| uid != &suid);
-
- let m1 = match members.next() {
- Some((_uid, m)) => m.get_alias(),
- None => String::new(),
- };
-
- let m2 = match members.next() {
- Some((_uid, m)) => m.get_alias(),
- None => String::new(),
- };
-
- let name = match n {
- 0 => i18n("EMPTY ROOM"),
- 1 => String::from(m1),
- 2 => i18n_k("{m1} and {m2}", &[("m1", &m1), ("m2", &m2)]),
- _ => i18n_k("{m1} and Others", &[("m1", &m1)]),
- };
+ // removing one because the user should be in the room
+ let n = r.members.len() - 1;
+ let suid = login_data.uid;
+ let mut members = r
+ .members
+ .iter()
+ .filter(|&(uid, _)| uid != &suid)
+ .map(|(_uid, m)| m.get_alias());
+
+ let m1 = members.next().unwrap_or_default();
+ let m2 = members.next().unwrap_or_default();
+
+ let name = match n {
+ 0 => i18n("EMPTY ROOM"),
+ 1 => String::from(m1),
+ 2 => i18n_k("{m1} and {m2}", &[("m1", &m1), ("m2", &m2)]),
+ _ => i18n_k("{m1} and Others", &[("m1", &m1)]),
+ };
- r.name = Some(name);
- rname = r.name.clone();
- }
+ r.name = Some(name.clone());
- self.room_name_change(roomid, rname);
+ self.room_name_change(room_id, Some(name));
}
- pub fn room_name_change(&mut self, roomid: String, name: Option<String>) {
- if !self.rooms.contains_key(&roomid) {
- return;
- }
+ pub fn room_name_change(&mut self, room_id: RoomId, name: Option<String>) {
+ let r = unwrap_or_unit_return!(self.rooms.get_mut(&room_id));
+ r.name = name.clone();
+ if self
+ .active_room
+ .as_ref()
+ .map_or(false, |a_room| a_room == &room_id)
{
- let r = self.rooms.get_mut(&roomid).unwrap();
- r.name = name.clone();
- }
-
- if roomid == self.active_room.clone().unwrap_or_default() {
self.ui
.builder
.get_object::<gtk::Label>("room_name")
@@ -597,20 +597,18 @@ impl AppOp {
.set_text(&name.clone().unwrap_or_default());
}
- self.roomlist.rename_room(roomid.clone(), name);
+ self.roomlist.rename_room(room_id, name);
}
- pub fn room_topic_change(&mut self, roomid: String, topic: Option<String>) {
- if !self.rooms.contains_key(&roomid) {
- return;
- }
+ pub fn room_topic_change(&mut self, room_id: RoomId, topic: Option<String>) {
+ let r = unwrap_or_unit_return!(self.rooms.get_mut(&room_id));
+ r.topic = topic.clone();
+ if self
+ .active_room
+ .as_ref()
+ .map_or(false, |a_room| *a_room == room_id)
{
- let r = self.rooms.get_mut(&roomid).unwrap();
- r.topic = topic.clone();
- }
-
- if roomid == self.active_room.clone().unwrap_or_default() {
self.set_room_topic_label(topic);
}
}
@@ -647,9 +645,9 @@ impl AppOp {
};
}
- pub fn new_room_avatar(&self, roomid: String) {
+ pub fn new_room_avatar(&self, room_id: RoomId) {
let login_data = unwrap_or_unit_return!(self.login_data.clone());
- if !self.rooms.contains_key(&roomid) {
+ if !self.rooms.contains_key(&room_id) {
return;
}
@@ -657,62 +655,59 @@ impl AppOp {
.send(BKCommand::GetRoomAvatar(
login_data.server_url,
login_data.access_token,
- roomid,
+ room_id,
))
.unwrap();
}
pub fn update_typing_notification(&mut self) {
- if let Some(active_room) = &self
- .rooms
- .get(&self.active_room.clone().unwrap_or_default())
- {
- if let Some(ref mut history) = self.history {
- let typing_users = &active_room.typing_users;
- if typing_users.len() == 0 {
- history.typing_notification("");
- } else if typing_users.len() > 2 {
- history.typing_notification(&i18n("Several users are typing…"));
- } else {
- let typing_string = ni18n_f(
- "<b>{}</b> is typing…",
- "<b>{}</b> and <b>{}</b> are typing…",
- typing_users.len() as u32,
- typing_users
- .iter()
- .map(|user| markup_escape_text(&user.get_alias()).to_string())
- .collect::<Vec<String>>()
- .iter()
- .map(std::ops::Deref::deref)
- .collect::<Vec<&str>>()
- .as_slice(),
- );
- history.typing_notification(&typing_string);
- }
- }
+ let active_room_id = unwrap_or_unit_return!(self.active_room.clone());
+ let active_room = unwrap_or_unit_return!(self.rooms.get(&active_room_id));
+ let history = unwrap_or_unit_return!(self.history.as_mut());
+
+ let typing_users = &active_room.typing_users;
+ if typing_users.len() == 0 {
+ history.typing_notification("");
+ } else if typing_users.len() > 2 {
+ history.typing_notification(&i18n("Several users are typing…"));
+ } else {
+ let typing_string = ni18n_f(
+ "<b>{}</b> is typing…",
+ "<b>{}</b> and <b>{}</b> are typing…",
+ typing_users.len() as u32,
+ typing_users
+ .iter()
+ .map(|user| markup_escape_text(&user.get_alias()).to_string())
+ .collect::<Vec<String>>()
+ .iter()
+ .map(std::ops::Deref::deref)
+ .collect::<Vec<&str>>()
+ .as_slice(),
+ );
+ history.typing_notification(&typing_string);
}
}
pub fn send_typing(&mut self) {
let login_data = unwrap_or_unit_return!(self.login_data.clone());
- if let Some(ref active_room) = self.active_room {
- let now = Instant::now();
- if let Some(last_typing) = self.typing.get(active_room) {
- let time_passed = now.duration_since(*last_typing);
- if time_passed.as_secs() < 3 {
- return;
- }
+ let active_room = unwrap_or_unit_return!(self.active_room.as_ref());
+
+ let now = Instant::now();
+ if let Some(last_typing) = self.typing.get(active_room) {
+ let time_passed = now.duration_since(*last_typing);
+ if time_passed.as_secs() < 3 {
+ return;
}
- self.typing.insert(active_room.clone(), now);
- self.backend
- .send(BKCommand::SendTyping(
- login_data.server_url,
- login_data.access_token,
- login_data.uid,
- active_room.clone(),
- ))
- .unwrap();
}
+ self.typing.insert(active_room.clone(), now);
+ self.backend
+ .send(BKCommand::SendTyping(
+ login_data.server_url,
+ login_data.access_token,
+ login_data.uid,
+ active_room.clone(),
+ ))
+ .unwrap();
}
pub fn set_language(&self, lang_code: String) {
diff --git a/fractal-gtk/src/appop/start_chat.rs b/fractal-gtk/src/appop/start_chat.rs
index f4edc7d1..3cba7936 100644
--- a/fractal-gtk/src/appop/start_chat.rs
+++ b/fractal-gtk/src/appop/start_chat.rs
@@ -1,3 +1,4 @@
+use fractal_api::identifiers::RoomId;
use gtk;
use gtk::prelude::*;
@@ -8,9 +9,6 @@ use crate::appop::SearchType;
use crate::backend::BKCommand;
use crate::types::{Room, RoomMembership, RoomTag};
-use rand::distributions::Alphanumeric;
-use rand::{thread_rng, Rng};
-
impl AppOp {
pub fn start_chat(&mut self) {
if self.invite_list.len() != 1 {
@@ -20,7 +18,8 @@ impl AppOp {
let login_data = unwrap_or_unit_return!(self.login_data.clone());
let user = self.invite_list[0].clone();
- let internal_id: String = thread_rng().sample_iter(&Alphanumeric).take(10).collect();
+ let internal_id = RoomId::new(&login_data.server_url.to_string())
+ .expect("The server domain should have been validated");
self.backend
.send(BKCommand::DirectChat(
login_data.server_url,
@@ -32,9 +31,11 @@ impl AppOp {
.unwrap();
self.close_direct_chat_dialog();
- let mut fakeroom = Room::new(internal_id.clone(), RoomMembership::Joined(RoomTag::None));
- fakeroom.name = user.0.alias;
- fakeroom.direct = true;
+ let fakeroom = Room {
+ name: user.0.alias,
+ direct: true,
+ ..Room::new(internal_id.clone(), RoomMembership::Joined(RoomTag::None))
+ };
self.new_room(fakeroom, None);
self.set_active_room_by_id(internal_id);
diff --git a/fractal-gtk/src/appop/state.rs b/fractal-gtk/src/appop/state.rs
index 7c9699ea..b08fb9b6 100644
--- a/fractal-gtk/src/appop/state.rs
+++ b/fractal-gtk/src/appop/state.rs
@@ -89,10 +89,10 @@ impl AppOp {
self.ui.sventry.view.grab_focus();
- let active_room_id = self.active_room.clone().unwrap_or_default();
let msg = self
- .unsent_messages
- .get(&active_room_id)
+ .active_room
+ .as_ref()
+ .and_then(|active_room_id| self.unsent_messages.get(active_room_id))
.cloned()
.unwrap_or_default();
if let Some(buffer) = self.ui.sventry.view.get_buffer() {
diff --git a/fractal-gtk/src/widgets/room.rs b/fractal-gtk/src/widgets/room.rs
index 109f9ba3..daac0982 100644
--- a/fractal-gtk/src/widgets/room.rs
+++ b/fractal-gtk/src/widgets/room.rs
@@ -48,7 +48,13 @@ impl<'a> RoomBox<'a> {
let room = self.room;
let avatar = widgets::Avatar::avatar_new(Some(AVATAR_SIZE));
- avatar.circle(room.id.clone(), room.name.clone(), AVATAR_SIZE, None, None);
+ avatar.circle(
+ room.id.to_string(),
+ room.name.clone(),
+ AVATAR_SIZE,
+ None,
+ None,
+ );
widget_box.pack_start(&avatar, false, false, 18);
let details_box = gtk::Box::new(gtk::Orientation::Vertical, 6);
diff --git a/fractal-gtk/src/widgets/room_history.rs b/fractal-gtk/src/widgets/room_history.rs
index 12cbe094..3f8b32a4 100644
--- a/fractal-gtk/src/widgets/room_history.rs
+++ b/fractal-gtk/src/widgets/room_history.rs
@@ -18,6 +18,7 @@ use crate::uitypes::RowType;
use crate::globals;
use crate::widgets;
use crate::widgets::{PlayerExt, VideoPlayerWidget};
+use fractal_api::identifiers::RoomId;
use fractal_api::url::Url;
use gio::ActionMapExt;
use gio::SimpleActionGroup;
@@ -259,7 +260,7 @@ pub struct RoomHistory {
}
impl RoomHistory {
- pub fn new(actions: SimpleActionGroup, room_id: String, op: &AppOp) -> Option<RoomHistory> {
+ pub fn new(actions: SimpleActionGroup, room_id: RoomId, op: &AppOp) -> Option<RoomHistory> {
let history_container = op
.ui
.builder
diff --git a/fractal-gtk/src/widgets/room_settings.rs b/fractal-gtk/src/widgets/room_settings.rs
index 10891fe0..8f10f602 100644
--- a/fractal-gtk/src/widgets/room_settings.rs
+++ b/fractal-gtk/src/widgets/room_settings.rs
@@ -168,7 +168,7 @@ impl RoomSettings {
if let Some(action) = self.actions.lookup_action("change-avatar") {
action.bind_button_state(&avatar_btn);
- let data = glib::Variant::from(&self.room.id);
+ let data = glib::Variant::from(&self.room.id.to_string());
avatar_btn.set_action_target_value(Some(&data));
avatar_btn.set_action_name(Some("room-settings.change-avatar"));
let avatar_spinner = self
@@ -428,7 +428,7 @@ impl RoomSettings {
let image = widgets::Avatar::avatar_new(Some(100));
let data = image.circle(
- self.room.id.clone(),
+ self.room.id.to_string(),
self.room.name.clone(),
100,
None,
@@ -437,7 +437,7 @@ impl RoomSettings {
download_to_cache(
self.backend.clone(),
self.server_url.clone(),
- self.room.id.clone(),
+ self.room.id.to_string(),
data,
);
diff --git a/fractal-gtk/src/widgets/roomlist.rs b/fractal-gtk/src/widgets/roomlist.rs
index 86d637af..2d118cec 100644
--- a/fractal-gtk/src/widgets/roomlist.rs
+++ b/fractal-gtk/src/widgets/roomlist.rs
@@ -1,5 +1,6 @@
use crate::i18n::i18n;
use fractal_api::clone;
+use fractal_api::identifiers::RoomId;
use gdk;
use glib;
@@ -13,6 +14,7 @@ use std::collections::HashMap;
use crate::globals;
use crate::types::{Room, RoomTag};
use crate::widgets::roomrow::RoomRow;
+use std::convert::TryFrom;
use std::sync::{Arc, Mutex, MutexGuard};
use chrono::prelude::*;
@@ -45,7 +47,7 @@ pub enum RoomListType {
}
pub struct RoomListGroup {
- pub rooms: HashMap<String, RoomRow>,
+ pub rooms: HashMap<RoomId, RoomRow>,
pub baseu: Url,
pub list: gtk::ListBox,
rev: gtk::Revealer,
@@ -173,27 +175,27 @@ impl RoomListGroup {
self.show();
}
- pub fn set_bold(&mut self, room: String, bold: bool) {
- if let Some(ref mut r) = self.rooms.get_mut(&room) {
+ pub fn set_bold(&mut self, room_id: RoomId, bold: bool) {
+ if let Some(ref mut r) = self.rooms.get_mut(&room_id) {
r.set_bold(bold);
}
}
- pub fn set_room_notifications(&mut self, room: String, n: i32, h: i32) {
- if let Some(ref mut r) = self.rooms.get_mut(&room) {
+ pub fn set_room_notifications(&mut self, room_id: RoomId, n: i32, h: i32) {
+ if let Some(ref mut r) = self.rooms.get_mut(&room_id) {
r.set_notifications(n, h);
}
- self.edit_room(&room, move |rv| {
+ self.edit_room(&room_id, move |rv| {
rv.room.notifications = n;
rv.room.highlight = h;
});
}
- pub fn remove_room(&mut self, room: String) -> Option<RoomUpdated> {
- self.rooms.remove(&room);
+ pub fn remove_room(&mut self, room_id: RoomId) -> Option<RoomUpdated> {
+ self.rooms.remove(&room_id);
let mut rv = self.roomvec.lock().unwrap();
- if let Some(idx) = rv.iter().position(|x| x.room.id == room) {
+ if let Some(idx) = rv.iter().position(|x| x.room.id == room_id) {
if let Some(row) = self.list.get_row_at_index(idx as i32) {
self.list.remove(&row);
}
@@ -204,22 +206,22 @@ impl RoomListGroup {
None
}
- pub fn rename_room(&mut self, room: String, newname: Option<String>) {
- if let (Some(r), Some(n)) = (self.rooms.get_mut(&room), newname.clone()) {
+ pub fn rename_room(&mut self, room_id: RoomId, newname: Option<String>) {
+ if let (Some(r), Some(n)) = (self.rooms.get_mut(&room_id), newname.clone()) {
r.set_name(n);
}
- self.edit_room(&room, move |rv| {
+ self.edit_room(&room_id, move |rv| {
rv.room.name = newname.clone();
});
}
- pub fn set_room_avatar(&mut self, room: String, av: Option<String>) {
- if let Some(r) = self.rooms.get_mut(&room) {
+ pub fn set_room_avatar(&mut self, room_id: RoomId, av: Option<String>) {
+ if let Some(r) = self.rooms.get_mut(&room_id) {
r.set_avatar(av.clone());
}
- self.edit_room(&room, move |rv| {
+ self.edit_room(&room_id, move |rv| {
rv.room.avatar = av.clone();
});
}
@@ -271,27 +273,22 @@ impl RoomListGroup {
self.widget.hide();
}
- pub fn get_selected(&self) -> Option<String> {
+ pub fn get_selected(&self) -> Option<RoomId> {
let rv = self.roomvec.lock().unwrap();
- match self.list.get_selected_row() {
- Some(row) => Some(rv[row.get_index() as usize].room.id.clone()),
- None => None,
- }
+ self.list
+ .get_selected_row()
+ .map(|row| rv[row.get_index() as usize].room.id.clone())
}
- pub fn set_selected(&self, room: Option<String>) {
+ pub fn set_selected(&self, room_id: Option<RoomId>) {
self.list.unselect_all();
- if room.is_none() {
- return;
- }
-
- let room = room.unwrap();
-
- let rv = self.roomvec.lock().unwrap();
- if let Some(idx) = rv.iter().position(|x| x.room.id == room) {
- if let Some(ref row) = self.list.get_row_at_index(idx as i32) {
- self.list.select_row(Some(row));
+ if let Some(room_id) = room_id {
+ let rv = self.roomvec.lock().unwrap();
+ if let Some(idx) = rv.iter().position(|x| x.room.id == room_id) {
+ if let Some(ref row) = self.list.get_row_at_index(idx as i32) {
+ self.list.select_row(Some(row));
+ }
}
}
}
@@ -306,20 +303,20 @@ impl RoomListGroup {
/// # Return value
///
/// `(Room id if found, go to previous group, go to next group)`
- fn sibling_id(&self, unread_only: bool, direction: i32) -> (Option<String>, bool, bool) {
+ fn sibling_id(&self, unread_only: bool, direction: i32) -> (Option<RoomId>, bool, bool) {
match self.list.get_selected_row() {
Some(row) => {
let rv = self.roomvec.lock().unwrap();
let mut idx = row.get_index() + direction;
while unread_only
- && 0 <= idx
+ && idx >= 0
&& (idx as usize) < rv.len()
&& rv[idx as usize].room.notifications == 0
{
idx += direction;
}
- if 0 <= idx && (idx as usize) < rv.len() {
+ if idx >= 0 && (idx as usize) < rv.len() {
(Some(rv[idx as usize].room.id.clone()), false, false)
} else {
(None, idx < 0, idx >= 0)
@@ -329,7 +326,7 @@ impl RoomListGroup {
}
}
- fn first_id(&self, unread_only: bool) -> Option<String> {
+ fn first_id(&self, unread_only: bool) -> Option<RoomId> {
self.roomvec
.lock()
.unwrap()
@@ -345,7 +342,7 @@ impl RoomListGroup {
.map(|r| r.room.id.clone())
}
- fn last_id(&self, unread_only: bool) -> Option<String> {
+ fn last_id(&self, unread_only: bool) -> Option<RoomId> {
self.roomvec
.lock()
.unwrap()
@@ -372,13 +369,13 @@ impl RoomListGroup {
}
}
- pub fn moveup(&mut self, room: String) {
+ pub fn moveup(&mut self, room_id: RoomId) {
let s = self.get_selected();
- self.edit_room(&room, move |rv| {
+ self.edit_room(&room_id, move |rv| {
rv.up();
});
- if let Some(r) = self.remove_room(room) {
+ if let Some(r) = self.remove_room(room_id) {
self.add_room_up(r);
}
@@ -393,9 +390,9 @@ impl RoomListGroup {
}
}
- fn edit_room<F: Fn(&mut RoomUpdated) + 'static>(&mut self, room: &str, cb: F) {
+ fn edit_room<F: Fn(&mut RoomUpdated) + 'static>(&mut self, room_id: &RoomId, cb: F) {
let mut rv = self.roomvec.lock().unwrap();
- if let Some(idx) = rv.iter().position(|x| x.room.id == room) {
+ if let Some(idx) = rv.iter().position(|x| x.room.id == *room_id) {
if let Some(ref mut m) = rv.get_mut(idx) {
cb(m);
}
@@ -454,10 +451,10 @@ pub struct RoomList {
}
macro_rules! run_in_group {
- ($self: expr, $roomid: expr, $fn: ident, $($arg: expr),*) => {{
- if $self.inv.get().rooms.contains_key($roomid) {
+ ($self: expr, $room_id: expr, $fn: ident, $($arg: expr),*) => {{
+ if $self.inv.get().rooms.contains_key($room_id) {
$self.inv.get().$fn($($arg),*)
- } else if $self.fav.get().rooms.contains_key($roomid) {
+ } else if $self.fav.get().rooms.contains_key($room_id) {
$self.fav.get().$fn($($arg),*)
} else {
$self.rooms.get().$fn($($arg),*)
@@ -498,16 +495,15 @@ impl RoomList {
rl
}
- pub fn select(&self, r: &str) {
- //FIXME don't use to_string(), pass &str
- run_in_group!(self, &r.to_string(), set_selected, Some(r.to_string()));
+ pub fn select(&self, room_id: &RoomId) {
+ run_in_group!(self, room_id, set_selected, Some(room_id.clone()));
}
- fn sibling_id_inv(&self, unread_only: bool, direction: i32) -> Option<String> {
- let (room, _, next) = self.inv.get().sibling_id(unread_only, direction);
+ fn sibling_id_inv(&self, unread_only: bool, direction: i32) -> Option<RoomId> {
+ let (room_id, _, next) = self.inv.get().sibling_id(unread_only, direction);
- if let Some(room) = room {
- Some(room)
+ if let Some(room_id) = room_id {
+ Some(room_id)
} else if next {
self.fav.get().first_id(unread_only)
} else {
@@ -515,11 +511,11 @@ impl RoomList {
}
}
- fn sibling_id_fav(&self, unread_only: bool, direction: i32) -> Option<String> {
- let (room, prev, next) = self.fav.get().sibling_id(unread_only, direction);
+ fn sibling_id_fav(&self, unread_only: bool, direction: i32) -> Option<RoomId> {
+ let (room_id, prev, next) = self.fav.get().sibling_id(unread_only, direction);
- if let Some(room) = room {
- Some(room)
+ if let Some(room_id) = room_id {
+ Some(room_id)
} else if prev {
self.inv.get().last_id(unread_only)
} else if next {
@@ -529,11 +525,11 @@ impl RoomList {
}
}
- fn sibling_id_rooms(&self, unread_only: bool, direction: i32) -> Option<String> {
- let (room, prev, _) = self.rooms.get().sibling_id(unread_only, direction);
+ fn sibling_id_rooms(&self, unread_only: bool, direction: i32) -> Option<RoomId> {
+ let (room_id, prev, _) = self.rooms.get().sibling_id(unread_only, direction);
- if let Some(room) = room {
- Some(room)
+ if let Some(room_id) = room_id {
+ Some(room_id)
} else if prev {
self.fav.get().last_id(unread_only)
} else {
@@ -541,27 +537,27 @@ impl RoomList {
}
}
- fn sibling_id(&self, unread_only: bool, direction: i32) -> Option<String> {
+ fn sibling_id(&self, unread_only: bool, direction: i32) -> Option<RoomId> {
self.sibling_id_inv(unread_only, direction)
}
- pub fn next_id(&self) -> Option<String> {
+ pub fn next_id(&self) -> Option<RoomId> {
self.sibling_id(false, 1)
}
- pub fn prev_id(&self) -> Option<String> {
+ pub fn prev_id(&self) -> Option<RoomId> {
self.sibling_id(false, -1)
}
- pub fn next_unread_id(&self) -> Option<String> {
+ pub fn next_unread_id(&self) -> Option<RoomId> {
self.sibling_id(true, 1)
}
- pub fn prev_unread_id(&self) -> Option<String> {
+ pub fn prev_unread_id(&self) -> Option<RoomId> {
self.sibling_id(true, -1)
}
- pub fn first_id(&self) -> Option<String> {
+ pub fn first_id(&self) -> Option<RoomId> {
self.inv
.get()
.first_id(false)
@@ -569,7 +565,7 @@ impl RoomList {
.or_else(|| self.rooms.get().first_id(false))
}
- pub fn last_id(&self) -> Option<String> {
+ pub fn last_id(&self) -> Option<RoomId> {
self.rooms
.get()
.last_id(false)
@@ -615,8 +611,8 @@ impl RoomList {
let r = self.rooms.clone();
let f = self.fav.clone();
let cb = acb.clone();
- self.connect_drop(favw, move |roomid| {
- if let Some(room) = r.get().remove_room(roomid) {
+ self.connect_drop(favw, move |room_id| {
+ if let Some(room) = r.get().remove_room(room_id) {
cb(room.room.clone(), true);
f.get().add_room_up(room);
}
@@ -634,22 +630,22 @@ impl RoomList {
});
}
- pub fn set_room_avatar(&mut self, room: String, av: Option<String>) {
- run_in_group!(self, &room, set_room_avatar, room, av);
+ pub fn set_room_avatar(&mut self, room_id: RoomId, av: Option<String>) {
+ run_in_group!(self, &room_id, set_room_avatar, room_id, av);
}
- pub fn set_room_notifications(&mut self, room: String, n: i32, h: i32) {
- run_in_group!(self, &room, set_room_notifications, room, n, h);
+ pub fn set_room_notifications(&mut self, room_id: RoomId, n: i32, h: i32) {
+ run_in_group!(self, &room_id, set_room_notifications, room_id, n, h);
}
- pub fn remove_room(&mut self, room: String) -> Option<RoomUpdated> {
- let ret = run_in_group!(self, &room, remove_room, room);
+ pub fn remove_room(&mut self, room_id: RoomId) -> Option<RoomUpdated> {
+ let ret = run_in_group!(self, &room_id, remove_room, room_id);
self.show_and_hide();
ret
}
- pub fn set_bold(&mut self, room: String, bold: bool) {
- run_in_group!(self, &room, set_bold, room, bold)
+ pub fn set_bold(&mut self, room_id: RoomId, bold: bool) {
+ run_in_group!(self, &room_id, set_bold, room_id, bold)
}
pub fn add_room(&mut self, r: Room) {
@@ -665,12 +661,12 @@ impl RoomList {
self.show_and_hide();
}
- pub fn rename_room(&mut self, room: String, newname: Option<String>) {
- run_in_group!(self, &room, rename_room, room, newname);
+ pub fn rename_room(&mut self, room_id: RoomId, newname: Option<String>) {
+ run_in_group!(self, &room_id, rename_room, room_id, newname);
}
- pub fn moveup(&mut self, room: String) {
- run_in_group!(self, &room, moveup, room);
+ pub fn moveup(&mut self, room_id: RoomId) {
+ run_in_group!(self, &room_id, moveup, room_id);
}
// Roomlist widget
@@ -732,7 +728,7 @@ impl RoomList {
});
}
- pub fn connect_drop<F: Fn(String) + 'static>(&self, widget: gtk::EventBox, cb: F) {
+ pub fn connect_drop<F: Fn(RoomId) + 'static>(&self, widget: gtk::EventBox, cb: F) {
let flags = gtk::DestDefaults::empty();
let action = gdk::DragAction::all();
widget.drag_dest_set(flags, &[], action);
@@ -748,8 +744,11 @@ impl RoomList {
glib::signal::Inhibit(true)
});
widget.connect_drag_data_received(move |_w, _ctx, _x, _y, data, _info, _time| {
- if let Some(roomid) = data.get_text() {
- cb(roomid.to_string());
+ if let Some(room_id) = data
+ .get_text()
+ .and_then(|rid| RoomId::try_from(rid.as_str()).ok())
+ {
+ cb(room_id);
}
});
}
diff --git a/fractal-gtk/src/widgets/roomrow.rs b/fractal-gtk/src/widgets/roomrow.rs
index e5cf62ed..f0907e65 100644
--- a/fractal-gtk/src/widgets/roomrow.rs
+++ b/fractal-gtk/src/widgets/roomrow.rs
@@ -63,7 +63,7 @@ impl RoomRow {
notifications.hide();
}
- icon.circle(room.id.clone(), Some(name), ICON_SIZE, None, None);
+ icon.circle(room.id.to_string(), Some(name), ICON_SIZE, None, None);
let rr = RoomRow {
room,
@@ -126,7 +126,7 @@ impl RoomRow {
let name = self.room.name.clone().unwrap_or("...".to_string());
self.icon
- .circle(self.room.id.clone(), Some(name), ICON_SIZE, None, None);
+ .circle(self.room.id.to_string(), Some(name), ICON_SIZE, None, None);
}
pub fn widget(&self) -> gtk::ListBoxRow {
@@ -155,7 +155,7 @@ impl RoomRow {
let row = gtk::ListBoxRow::new();
row.add(&self.widget);
- let data = glib::Variant::from(&self.room.id);
+ let data = glib::Variant::from(&self.room.id.to_string());
row.set_action_target_value(Some(&data));
row.set_action_name(Some("app.open-room"));
@@ -186,7 +186,7 @@ impl RoomRow {
ctx.drag_set_icon_surface(&image);
});
- let id = self.room.id.clone();
+ let id = self.room.id.to_string();
self.widget
.connect_drag_data_get(move |_w, _, data, _x, _y| {
data.set_text(&id);
diff --git a/fractal-gtk/src/widgets/scroll_widget.rs b/fractal-gtk/src/widgets/scroll_widget.rs
index 08c5090e..bb9233c5 100644
--- a/fractal-gtk/src/widgets/scroll_widget.rs
+++ b/fractal-gtk/src/widgets/scroll_widget.rs
@@ -1,6 +1,7 @@
use std::cell::Cell;
use std::rc::Rc;
+use fractal_api::identifiers::RoomId;
use gio::Action;
use gio::ActionExt;
use gtk;
@@ -117,7 +118,7 @@ impl Widgets {
}
impl ScrollWidget {
- pub fn new(action: Option<Action>, room_id: String) -> ScrollWidget {
+ pub fn new(action: Option<Action>, room_id: RoomId) -> ScrollWidget {
let builder = gtk::Builder::new();
builder
@@ -149,7 +150,7 @@ impl ScrollWidget {
}
/* Keep the same position if new messages are added */
- pub fn connect(&mut self, action: Option<Action>, room_id: String) -> Option<()> {
+ pub fn connect(&mut self, action: Option<Action>, room_id: RoomId) -> Option<()> {
let adj = self.widgets.view.get_vadjustment()?;
let upper = Rc::downgrade(&self.upper);
let balance = Rc::downgrade(&self.balance);
@@ -217,7 +218,7 @@ impl ScrollWidget {
if adj.get_value() < adj.get_page_size() * 2.0 {
/* Load more messages once the user is nearly at the end of the history */
spinner.start();
- let data = glib::Variant::from(&room_id);
+ let data = glib::Variant::from(&room_id.to_string());
action.activate(Some(&data));
request_sent.set(true);
}
diff --git a/fractal-matrix-api/src/backend/directory.rs b/fractal-matrix-api/src/backend/directory.rs
index 675bf519..f9796b71 100644
--- a/fractal-matrix-api/src/backend/directory.rs
+++ b/fractal-matrix-api/src/backend/directory.rs
@@ -114,7 +114,7 @@ pub fn room_search(
.map(Into::into)
.inspect(|r: &Room| {
if let Some(avatar) = r.avatar.clone() {
- if let Ok(dest) = cache_dir_path(None, &r.id) {
+ if let Ok(dest) = cache_dir_path(None, &r.id.to_string()) {
let _ =
dw_media(&base, &avatar, ContentType::Download, Some(&dest));
}
diff --git a/fractal-matrix-api/src/backend/media.rs b/fractal-matrix-api/src/backend/media.rs
index 8a5f56b5..83d3ce3c 100644
--- a/fractal-matrix-api/src/backend/media.rs
+++ b/fractal-matrix-api/src/backend/media.rs
@@ -1,6 +1,7 @@
use crate::backend::types::Backend;
use crate::error::Error;
use crate::globals;
+use ruma_identifiers::RoomId;
use serde_json::json;
use std::str::Split;
use std::sync::mpsc::Sender;
@@ -39,7 +40,7 @@ pub fn get_media_list_async(
bk: &Backend,
baseu: Url,
access_token: AccessToken,
- roomid: String,
+ room_id: RoomId,
first_media_id: Option<String>,
prev_batch: Option<String>,
tx: Sender<(Vec<Message>, String)>,
@@ -48,7 +49,7 @@ pub fn get_media_list_async(
let media_list = get_room_media_list(
&baseu,
&access_token,
- &roomid,
+ &room_id,
globals::PAGE_LIMIT,
first_media_id,
&prev_batch,
@@ -76,7 +77,7 @@ pub fn get_file_async(url: Url, tx: Sender<String>) -> Result<(), Error> {
fn get_room_media_list(
baseu: &Url,
tk: &AccessToken,
- roomid: &str,
+ room_id: &RoomId,
limit: i32,
first_media_id: Option<String>,
prev_batch: &Option<String>,
@@ -100,12 +101,12 @@ fn get_room_media_list(
Some(ref pb) => params.push(("from", pb.clone())),
None => {
if let Some(id) = first_media_id {
- params.push(("from", get_prev_batch_from(baseu, tk, &roomid, &id)?))
+ params.push(("from", get_prev_batch_from(baseu, tk, room_id, &id)?))
}
}
};
- let path = format!("rooms/{}/messages", roomid);
+ let path = format!("rooms/{}/messages", room_id);
let url = client_url(baseu, &path, ¶ms)?;
let r = json_q("get", url, &json!(null))?;
@@ -116,7 +117,7 @@ fn get_room_media_list(
}
let evs = array.unwrap().iter().rev();
- let media_list = Message::from_json_events_iter(roomid, evs);
+ let media_list = Message::from_json_events_iter(room_id, evs);
Ok((media_list, prev_batch))
}
diff --git a/fractal-matrix-api/src/backend/mod.rs b/fractal-matrix-api/src/backend/mod.rs
index 92b2c020..02aefcd9 100644
--- a/fractal-matrix-api/src/backend/mod.rs
+++ b/fractal-matrix-api/src/backend/mod.rs
@@ -37,7 +37,7 @@ impl Backend {
pub fn new(tx: Sender<BKResponse>) -> Backend {
let data = BackendData {
rooms_since: String::new(),
- join_to_room: String::new(),
+ join_to_room: None,
m_direct: HashMap::new(),
};
Backend {
@@ -221,16 +221,19 @@ impl Backend {
}
// Room module
- Ok(BKCommand::GetRoomMembers(server, access_token, room)) => {
- let r = room::get_room_members(self, server, access_token, room);
- bkerror2!(r, tx, BKResponse::RoomMembers);
+ Ok(BKCommand::GetRoomMembers(server, access_token, room_id)) => {
+ thread::spawn(move || {
+ let query = room::get_room_members(server, access_token, room_id);
+ tx.send(BKResponse::RoomMembers(query))
+ .expect_log("Connection closed");
+ });
}
- Ok(BKCommand::GetRoomMessages(server, access_token, room, from)) => {
- let r = room::get_room_messages(self, server, access_token, room, from);
+ Ok(BKCommand::GetRoomMessages(server, access_token, room_id, from)) => {
+ let r = room::get_room_messages(self, server, access_token, room_id, from);
bkerror2!(r, tx, BKResponse::RoomMessagesTo);
}
- Ok(BKCommand::GetRoomMessagesFromMsg(server, access_token, room, from)) => {
- room::get_room_messages_from_msg(self, server, access_token, room, from)
+ Ok(BKCommand::GetRoomMessagesFromMsg(server, access_token, room_id, from)) => {
+ room::get_room_messages_from_msg(self, server, access_token, room_id, from)
}
Ok(BKCommand::GetMessageContext(server, access_token, message)) => {
let r = room::get_message_context(self, server, access_token, message);
@@ -244,86 +247,103 @@ impl Backend {
let r = room::redact_msg(self, server, access_token, &msg);
bkerror2!(r, tx, BKResponse::SentMsgRedaction);
}
- Ok(BKCommand::SendTyping(server, access_token, uid, room)) => {
- let r = room::send_typing(self, server, access_token, uid, room);
- bkerror!(r, tx, BKResponse::SendTypingError);
+ Ok(BKCommand::SendTyping(server, access_token, uid, room_id)) => {
+ thread::spawn(move || {
+ let query = room::send_typing(server, access_token, uid, room_id);
+ if let Err(err) = query {
+ tx.send(BKResponse::SendTypingError(err))
+ .expect_log("Connection closed");
+ }
+ });
}
- Ok(BKCommand::SetRoom(server, access_token, id)) => {
- let r = room::set_room(self, server, access_token, id);
+ Ok(BKCommand::SetRoom(server, access_token, room_id)) => {
+ let r = room::set_room(self, server, access_token, room_id);
bkerror!(r, tx, BKResponse::SetRoomError);
}
- Ok(BKCommand::GetRoomAvatar(server, access_token, room)) => {
- let r = room::get_room_avatar(self, server, access_token, room);
+ Ok(BKCommand::GetRoomAvatar(server, access_token, room_id)) => {
+ let r = room::get_room_avatar(self, server, access_token, room_id);
bkerror2!(r, tx, BKResponse::RoomAvatar);
}
- Ok(BKCommand::JoinRoom(server, access_token, roomid)) => {
- let r = room::join_room(self, server, access_token, roomid);
- bkerror2!(r, tx, BKResponse::JoinRoom);
+ Ok(BKCommand::JoinRoom(server, access_token, room_id)) => {
+ room::join_room(self, server, access_token, room_id)
}
- Ok(BKCommand::LeaveRoom(server, access_token, roomid)) => {
- let r = room::leave_room(self, server, access_token, roomid);
- bkerror2!(r, tx, BKResponse::LeaveRoom);
+ Ok(BKCommand::LeaveRoom(server, access_token, room_id)) => {
+ thread::spawn(move || {
+ let query = room::leave_room(server, access_token, room_id);
+ tx.send(BKResponse::LeaveRoom(query))
+ .expect_log("Connection closed");
+ });
}
- Ok(BKCommand::MarkAsRead(server, access_token, roomid, evid)) => {
- let r = room::mark_as_read(self, server, access_token, roomid, evid);
+ Ok(BKCommand::MarkAsRead(server, access_token, room_id, evid)) => {
+ let r = room::mark_as_read(self, server, access_token, room_id, evid);
bkerror2!(r, tx, BKResponse::MarkedAsRead);
}
- Ok(BKCommand::SetRoomName(server, access_token, roomid, name)) => {
- let r = room::set_room_name(self, server, access_token, roomid, name);
+ Ok(BKCommand::SetRoomName(server, access_token, room_id, name)) => {
+ let r = room::set_room_name(self, server, access_token, room_id, name);
bkerror2!(r, tx, BKResponse::SetRoomName);
}
- Ok(BKCommand::SetRoomTopic(server, access_token, roomid, topic)) => {
- let r = room::set_room_topic(self, server, access_token, roomid, topic);
+ Ok(BKCommand::SetRoomTopic(server, access_token, room_id, topic)) => {
+ let r = room::set_room_topic(self, server, access_token, room_id, topic);
bkerror2!(r, tx, BKResponse::SetRoomTopic);
}
- Ok(BKCommand::SetRoomAvatar(server, access_token, roomid, fname)) => {
- let r = room::set_room_avatar(self, server, access_token, roomid, fname);
+ Ok(BKCommand::SetRoomAvatar(server, access_token, room_id, fname)) => {
+ let r = room::set_room_avatar(self, server, access_token, room_id, fname);
bkerror2!(r, tx, BKResponse::SetRoomAvatar);
}
Ok(BKCommand::AttachFile(server, access_token, msg)) => {
let r = room::attach_file(self, server, access_token, msg);
bkerror2!(r, tx, BKResponse::AttachedFile);
}
- Ok(BKCommand::NewRoom(server, access_token, name, privacy, internalid)) => {
+ Ok(BKCommand::NewRoom(server, access_token, name, privacy, internal_id)) => {
let r = room::new_room(
self,
server,
access_token,
name,
privacy,
- internalid.clone(),
+ internal_id.clone(),
);
if let Err(e) = r {
- tx.send(BKResponse::NewRoom(Err(e), internalid))
+ tx.send(BKResponse::NewRoom(Err(e), internal_id))
.expect_log("Connection closed");
}
}
- Ok(BKCommand::DirectChat(server, access_token, uid, user, internalid)) => {
+ Ok(BKCommand::DirectChat(server, access_token, uid, user, internal_id)) => {
let r =
- room::direct_chat(self, server, access_token, uid, user, internalid.clone());
+ room::direct_chat(self, server, access_token, uid, user, internal_id.clone());
if let Err(e) = r {
- tx.send(BKResponse::NewRoom(Err(e), internalid))
+ tx.send(BKResponse::NewRoom(Err(e), internal_id))
.expect_log("Connection closed");
}
}
- Ok(BKCommand::AddToFav(server, access_token, uid, roomid, tofav)) => {
- let r = room::add_to_fav(self, server, access_token, uid, roomid, tofav);
- bkerror2!(r, tx, BKResponse::AddedToFav);
+ Ok(BKCommand::AddToFav(server, access_token, uid, room_id, tofav)) => {
+ thread::spawn(move || {
+ let query = room::add_to_fav(server, access_token, uid, room_id, tofav);
+ tx.send(BKResponse::AddedToFav(query))
+ .expect_log("Connection closed");
+ });
}
- Ok(BKCommand::AcceptInv(server, access_token, roomid)) => {
- let r = room::join_room(self, server, access_token, roomid);
- bkerror2!(r, tx, BKResponse::JoinRoom);
+ Ok(BKCommand::AcceptInv(server, access_token, room_id)) => {
+ room::join_room(self, server, access_token, room_id)
}
- Ok(BKCommand::RejectInv(server, access_token, roomid)) => {
- let r = room::leave_room(self, server, access_token, roomid);
- bkerror2!(r, tx, BKResponse::LeaveRoom);
+ Ok(BKCommand::RejectInv(server, access_token, room_id)) => {
+ thread::spawn(move || {
+ let query = room::leave_room(server, access_token, room_id);
+ tx.send(BKResponse::LeaveRoom(query))
+ .expect_log("Connection closed");
+ });
}
- Ok(BKCommand::Invite(server, access_token, room, userid)) => {
- let r = room::invite(self, server, access_token, room, userid);
- bkerror!(r, tx, BKResponse::InviteError);
+ Ok(BKCommand::Invite(server, access_token, room_id, userid)) => {
+ thread::spawn(move || {
+ let query = room::invite(server, access_token, room_id, userid);
+ if let Err(err) = query {
+ tx.send(BKResponse::InviteError(err))
+ .expect_log("Connection closed");
+ }
+ });
}
- Ok(BKCommand::ChangeLanguage(access_token, server, uid, room, lang)) => {
- let r = room::set_language(self, access_token, server, uid, room, lang);
+ Ok(BKCommand::ChangeLanguage(access_token, server, uid, room_id, lang)) => {
+ let r = room::set_language(self, access_token, server, uid, room_id, lang);
bkerror2!(r, tx, BKResponse::ChangeLanguage);
}
@@ -337,7 +357,7 @@ impl Backend {
Ok(BKCommand::GetMediaListAsync(
server,
access_token,
- roomid,
+ room_id,
first_media_id,
prev_batch,
ctx,
@@ -345,7 +365,7 @@ impl Backend {
self,
server,
access_token,
- roomid,
+ room_id,
first_media_id,
prev_batch,
ctx,
@@ -391,6 +411,10 @@ impl Backend {
}
// Internal commands
+ Ok(BKCommand::SendBKResponse(response)) => {
+ tx.send(response).expect_log("Connection closed");
+ }
+
Ok(BKCommand::ShutDown) => {
tx.send(BKResponse::ShutDown)
.expect_log("Connection closed");
diff --git a/fractal-matrix-api/src/backend/room.rs b/fractal-matrix-api/src/backend/room.rs
index dea519a6..d031afe3 100644
--- a/fractal-matrix-api/src/backend/room.rs
+++ b/fractal-matrix-api/src/backend/room.rs
@@ -3,12 +3,12 @@ use serde_json::json;
use ruma_identifiers::RoomId;
use ruma_identifiers::RoomIdOrAliasId;
-use std::convert::TryFrom;
use std::fs;
use std::sync::mpsc::Sender;
use url::Url;
use std::collections::HashMap;
+use std::convert::TryFrom;
use std::sync::{Arc, Mutex};
use std::time::Duration;
@@ -68,11 +68,17 @@ pub fn set_room(
bk: &Backend,
base: Url,
access_token: AccessToken,
- id: String,
+ room_id: RoomId,
) -> Result<(), Error> {
/* FIXME: remove clone and pass id by reference */
- get_room_avatar(bk, base.clone(), access_token.clone(), id.clone())?;
- get_room_detail(bk, base, access_token, id, String::from("m.room.topic"))?;
+ get_room_avatar(bk, base.clone(), access_token.clone(), room_id.clone())?;
+ get_room_detail(
+ bk,
+ base,
+ access_token,
+ room_id,
+ String::from("m.room.topic"),
+ )?;
Ok(())
}
@@ -81,13 +87,13 @@ pub fn get_room_detail(
bk: &Backend,
base: Url,
access_token: AccessToken,
- roomid: String,
+ room_id: RoomId,
keys: String,
) -> Result<(), Error> {
let url = bk.url(
base,
&access_token,
- &format!("rooms/{}/state/{}", roomid, keys),
+ &format!("rooms/{}/state/{}", room_id, keys),
vec![],
)?;
@@ -98,7 +104,7 @@ pub fn get_room_detail(
let k = keys.split('.').last().unwrap();
let value = r[&k].as_str().map(Into::into).unwrap_or_default();
- tx.send(BKResponse::RoomDetail(Ok((roomid, keys, value))))
+ tx.send(BKResponse::RoomDetail(Ok((room_id, keys, value))))
.expect_log("Connection closed");
},
|err| {
@@ -114,12 +120,12 @@ pub fn get_room_avatar(
bk: &Backend,
baseu: Url,
access_token: AccessToken,
- roomid: String,
+ room_id: RoomId,
) -> Result<(), Error> {
let url = bk.url(
baseu.clone(),
&access_token,
- &format!("rooms/{}/state/m.room.avatar", roomid),
+ &format!("rooms/{}/state/m.room.avatar", room_id),
vec![],
)?;
let tx = bk.tx.clone();
@@ -127,7 +133,7 @@ pub fn get_room_avatar(
url,
|r: JsonValue| {
let avatar = r["url"].as_str().and_then(|s| Url::parse(s).ok());
- let dest = cache_dir_path(None, &roomid).ok();
+ let dest = cache_dir_path(None, &room_id.to_string()).ok();
if let Some(ref avatar) = avatar {
let _ = dw_media(
&baseu,
@@ -136,14 +142,14 @@ pub fn get_room_avatar(
dest.as_ref().map(String::as_str),
);
}
- tx.send(BKResponse::RoomAvatar(Ok((roomid, avatar))))
+ tx.send(BKResponse::RoomAvatar(Ok((room_id, avatar))))
.expect_log("Connection closed");
},
|err: Error| match err {
Error::MatrixError(ref js)
if js["errcode"].as_str().unwrap_or_default() == "M_NOT_FOUND" =>
{
- tx.send(BKResponse::RoomAvatar(Ok((roomid, None))))
+ tx.send(BKResponse::RoomAvatar(Ok((room_id, None))))
.expect_log("Connection closed");
}
_ => {
@@ -157,37 +163,26 @@ pub fn get_room_avatar(
}
pub fn get_room_members(
- bk: &Backend,
base: Url,
access_token: AccessToken,
- roomid: String,
-) -> Result<(), Error> {
- let tx = bk.tx.clone();
-
- let room_id = RoomId::try_from(roomid.as_str())?;
+ room_id: RoomId,
+) -> Result<(RoomId, Vec<Member>), Error> {
let params = JoinedMembersParameters { access_token };
- thread::spawn(move || {
- let query = get_joined_members(base, &room_id, ¶ms)
- .map_err(Into::into)
- .and_then(|request| {
- HTTP_CLIENT
- .get_client()?
- .execute(request)?
- .json::<JoinedMembersResponse>()
- .map_err(Into::into)
- })
- .map(|response| {
- let ms = response.joined.into_iter().map(Member::from).collect();
-
- (room_id.to_string(), ms)
- });
-
- tx.send(BKResponse::RoomMembers(query))
- .expect_log("Connection closed");
- });
+ get_joined_members(base, &room_id, ¶ms)
+ .map_err(Into::into)
+ .and_then(|request| {
+ HTTP_CLIENT
+ .get_client()?
+ .execute(request)?
+ .json::<JoinedMembersResponse>()
+ .map_err(Into::into)
+ })
+ .map(|response| {
+ let ms = response.joined.into_iter().map(Member::from).collect();
- Ok(())
+ (room_id, ms)
+ })
}
/* Load older messages starting by prev_batch
@@ -197,7 +192,7 @@ pub fn get_room_messages(
bk: &Backend,
base: Url,
access_token: AccessToken,
- roomid: String,
+ room_id: RoomId,
from: String,
) -> Result<(), Error> {
let params = vec![
@@ -216,7 +211,7 @@ pub fn get_room_messages(
let url = bk.url(
base,
&access_token,
- &format!("rooms/{}/messages", roomid),
+ &format!("rooms/{}/messages", room_id),
params,
)?;
let tx = bk.tx.clone();
@@ -225,9 +220,9 @@ pub fn get_room_messages(
|r: JsonValue| {
let array = r["chunk"].as_array();
let evs = array.unwrap().iter().rev();
- let list = Message::from_json_events_iter(&roomid, evs);
+ let list = Message::from_json_events_iter(&room_id, evs);
let prev_batch = r["end"].as_str().map(String::from);
- tx.send(BKResponse::RoomMessagesTo(Ok((list, roomid, prev_batch))))
+ tx.send(BKResponse::RoomMessagesTo(Ok((list, room_id, prev_batch))))
.expect_log("Connection closed");
},
|err| {
@@ -243,7 +238,7 @@ pub fn get_room_messages_from_msg(
bk: &Backend,
baseu: Url,
tk: AccessToken,
- roomid: String,
+ room_id: RoomId,
msg: Message,
) {
// first of all, we calculate the from param using the context api, then we call the
@@ -251,9 +246,9 @@ pub fn get_room_messages_from_msg(
let itx = bk.internal_tx.clone();
thread::spawn(move || {
- if let Ok(from) = get_prev_batch_from(&baseu, &tk, &roomid, &msg.id) {
+ if let Ok(from) = get_prev_batch_from(&baseu, &tk, &room_id, &msg.id) {
if let Some(t) = itx {
- t.send(BKCommand::GetRoomMessages(baseu, tk, roomid, from))
+ t.send(BKCommand::GetRoomMessages(baseu, tk, room_id, from))
.expect_log("Connection closed");
}
}
@@ -264,13 +259,13 @@ fn parse_context(
tx: Sender<BKResponse>,
tk: AccessToken,
baseu: Url,
- roomid: String,
+ room_id: RoomId,
eid: &str,
limit: i32,
) -> Result<(), Error> {
let url = client_url(
&baseu,
- &format!("rooms/{}/context/{}", roomid, eid),
+ &format!("rooms/{}/context/{}", room_id, eid),
&[
("limit", format!("{}", limit)),
("access_token", tk.to_string()),
@@ -293,20 +288,20 @@ fn parse_context(
continue;
}
- let m = Message::parse_room_message(&roomid, msg);
+ let m = Message::parse_room_message(&room_id, msg);
ms.push(m);
}
if ms.is_empty() && id.is_some() {
// there's no messages so we'll try with a bigger context
if let Err(err) =
- parse_context(tx.clone(), tk, baseu, roomid, &id.unwrap(), limit * 2)
+ parse_context(tx.clone(), tk, baseu, room_id, &id.unwrap(), limit * 2)
{
tx.send(BKResponse::RoomMessagesTo(Err(err)))
.expect_log("Connection closed");
}
} else {
- tx.send(BKResponse::RoomMessagesTo(Ok((ms, roomid, None))))
+ tx.send(BKResponse::RoomMessagesTo(Ok((ms, room_id, None))))
.expect_log("Connection closed");
}
},
@@ -326,9 +321,9 @@ pub fn get_message_context(
msg: Message,
) -> Result<(), Error> {
let tx = bk.tx.clone();
- let roomid = msg.room.clone();
+ let room_id: RoomId = msg.room.clone();
- parse_context(tx, tk, baseu, roomid, &msg.id, globals::PAGE_LIMIT)?;
+ parse_context(tx, tk, baseu, room_id, &msg.id, globals::PAGE_LIMIT)?;
Ok(())
}
@@ -339,12 +334,12 @@ pub fn send_msg(
access_token: AccessToken,
msg: Message,
) -> Result<(), Error> {
- let roomid = msg.room.clone();
+ let room_id: RoomId = msg.room.clone();
let url = bk.url(
base,
&access_token,
- &format!("rooms/{}/send/m.room.message/{}", roomid, msg.id),
+ &format!("rooms/{}/send/m.room.message/{}", room_id, msg.id),
vec![],
)?;
@@ -371,8 +366,7 @@ pub fn send_msg(
}
let tx = bk.tx.clone();
- query!(
- "put",
+ put!(
url,
&attrs,
move |js: JsonValue| {
@@ -390,38 +384,23 @@ pub fn send_msg(
}
pub fn send_typing(
- bk: &Backend,
base: Url,
access_token: AccessToken,
userid: String,
- roomid: String,
+ room_id: RoomId,
) -> Result<(), Error> {
- let tx = bk.tx.clone();
-
- let room_id = RoomId::try_from(roomid.as_str())?;
let params = TypingNotificationParameters { access_token };
let body = TypingNotificationBody::Typing(Duration::from_secs(4));
- thread::spawn(move || {
- let query = send_typing_notification(base, &room_id, &userid, ¶ms, &body)
- .map_err(Into::into)
- .and_then(|request| {
- HTTP_CLIENT
- .get_client()?
- .execute(request)
- .map_err(Into::into)
- });
-
- match query {
- Err(err) => {
- tx.send(BKResponse::SendTypingError(err))
- .expect_log("Connection closed");
- }
- _ => (),
- }
- });
-
- Ok(())
+ send_typing_notification(base, &room_id, &userid, ¶ms, &body)
+ .map_err(Into::into)
+ .and_then(|request| {
+ HTTP_CLIENT
+ .get_client()?
+ .execute(request)
+ .map_err(Into::into)
+ })
+ .and(Ok(()))
}
pub fn redact_msg(
@@ -430,13 +409,13 @@ pub fn redact_msg(
access_token: AccessToken,
msg: &Message,
) -> Result<(), Error> {
- let roomid = msg.room.clone();
+ let room_id: RoomId = msg.room.clone();
let txnid = msg.id.clone();
let url = bk.url(
base,
&access_token,
- &format!("rooms/{}/redact/{}/{}", roomid, msg.id, txnid),
+ &format!("rooms/{}/redact/{}/{}", room_id, msg.id, txnid),
vec![],
)?;
@@ -446,8 +425,7 @@ pub fn redact_msg(
let msgid = msg.id.clone();
let tx = bk.tx.clone();
- query!(
- "put",
+ put!(
url,
&attrs,
move |js: JsonValue| {
@@ -466,16 +444,12 @@ pub fn redact_msg(
Ok(())
}
-pub fn join_room(
- bk: &Backend,
- base: Url,
- access_token: AccessToken,
- roomid: String,
-) -> Result<(), Error> {
+pub fn join_room(bk: &Backend, base: Url, access_token: AccessToken, room_id: RoomId) {
let tx = bk.tx.clone();
let data = bk.data.clone();
- let room_id_or_alias_id = RoomIdOrAliasId::try_from(roomid.as_str())?;
+ let room_id_or_alias_id = RoomIdOrAliasId::RoomId(room_id.clone());
+
let params = JoinRoomParameters {
access_token,
server_name: Default::default(),
@@ -490,61 +464,46 @@ pub fn join_room(
.execute(request)
.map_err(Into::into)
})
- .map(|_| {
- data.lock().unwrap().join_to_room = room_id_or_alias_id.to_string();
- });
+ .and(Ok(()));
+
+ if let Ok(_) = query {
+ data.lock().unwrap().join_to_room = Some(room_id);
+ }
tx.send(BKResponse::JoinRoom(query))
.expect_log("Connection closed");
});
-
- Ok(())
}
-pub fn leave_room(
- bk: &Backend,
- base: Url,
- access_token: AccessToken,
- roomid: String,
-) -> Result<(), Error> {
- let tx = bk.tx.clone();
-
- let room_id = RoomId::try_from(roomid.as_str())?;
+pub fn leave_room(base: Url, access_token: AccessToken, room_id: RoomId) -> Result<(), Error> {
let params = LeaveRoomParameters { access_token };
- thread::spawn(move || {
- let query = leave_room_req(base, &room_id, ¶ms)
- .map_err(Into::into)
- .and_then(|request| {
- HTTP_CLIENT
- .get_client()?
- .execute(request)
- .map_err(Into::into)
- })
- .and(Ok(()));
-
- tx.send(BKResponse::LeaveRoom(query))
- .expect_log("Connection closed");
- });
-
- Ok(())
+ leave_room_req(base, &room_id, ¶ms)
+ .map_err(Into::into)
+ .and_then(|request| {
+ HTTP_CLIENT
+ .get_client()?
+ .execute(request)
+ .map_err(Into::into)
+ })
+ .and(Ok(()))
}
pub fn mark_as_read(
bk: &Backend,
base: Url,
access_token: AccessToken,
- roomid: String,
+ room_id: RoomId,
eventid: String,
) -> Result<(), Error> {
let url = bk.url(
base.clone(),
&access_token,
- &format!("rooms/{}/receipt/m.read/{}", roomid, eventid),
+ &format!("rooms/{}/receipt/m.read/{}", room_id, eventid),
vec![],
)?;
- let r = roomid.clone();
+ let r = room_id.clone();
let e = eventid.clone();
let tx = bk.tx.clone();
post!(
@@ -566,7 +525,7 @@ pub fn mark_as_read(
let url = bk.url(
base,
&access_token,
- &format!("rooms/{}/read_markers", roomid),
+ &format!("rooms/{}/read_markers", room_id),
vec![],
)?;
let attrs = json!({
@@ -582,13 +541,13 @@ pub fn set_room_name(
bk: &Backend,
base: Url,
access_token: AccessToken,
- roomid: String,
+ room_id: RoomId,
name: String,
) -> Result<(), Error> {
let url = bk.url(
base,
&access_token,
- &format!("rooms/{}/state/m.room.name", roomid),
+ &format!("rooms/{}/state/m.room.name", room_id),
vec![],
)?;
@@ -597,8 +556,7 @@ pub fn set_room_name(
});
let tx = bk.tx.clone();
- query!(
- "put",
+ put!(
url,
&attrs,
|_| {
@@ -618,13 +576,13 @@ pub fn set_room_topic(
bk: &Backend,
base: Url,
access_token: AccessToken,
- roomid: String,
+ room_id: RoomId,
topic: String,
) -> Result<(), Error> {
let url = bk.url(
base,
&access_token,
- &format!("rooms/{}/state/m.room.topic", roomid),
+ &format!("rooms/{}/state/m.room.topic", room_id),
vec![],
)?;
@@ -633,8 +591,7 @@ pub fn set_room_topic(
});
let tx = bk.tx.clone();
- query!(
- "put",
+ put!(
url,
&attrs,
|_| {
@@ -654,13 +611,13 @@ pub fn set_room_avatar(
bk: &Backend,
baseu: Url,
tk: AccessToken,
- roomid: String,
+ room_id: RoomId,
avatar: String,
) -> Result<(), Error> {
let roomurl = bk.url(
baseu.clone(),
&tk,
- &format!("rooms/{}/state/m.room.avatar", roomid),
+ &format!("rooms/{}/state/m.room.avatar", room_id),
vec![],
)?;
@@ -777,7 +734,7 @@ pub fn new_room(
access_token: AccessToken,
name: String,
privacy: RoomType,
- internal_id: String,
+ internal_id: RoomId,
) -> Result<(), Error> {
let url = bk.url(base, &access_token, "createRoom", vec![])?;
let attrs = json!({
@@ -800,10 +757,14 @@ pub fn new_room(
url,
&attrs,
move |r: JsonValue| {
- let id = String::from(r["room_id"].as_str().unwrap_or_default());
- let mut r = Room::new(id, RoomMembership::Joined(RoomTag::None));
- r.name = Some(name);
- tx.send(BKResponse::NewRoom(Ok(r), internal_id))
+ let room_res = RoomId::try_from(r["room_id"].as_str().unwrap_or_default())
+ .map_err(Into::into)
+ .map(|room_id| Room {
+ name: Some(name),
+ ..Room::new(room_id, RoomMembership::Joined(RoomTag::None))
+ });
+
+ tx.send(BKResponse::NewRoom(room_res, internal_id))
.expect_log("Connection closed");
},
|err| {
@@ -814,7 +775,7 @@ pub fn new_room(
Ok(())
}
-pub fn update_direct_chats(url: Url, data: Arc<Mutex<BackendData>>, user: String, room: String) {
+pub fn update_direct_chats(url: Url, data: Arc<Mutex<BackendData>>, user: String, room_id: RoomId) {
get!(
url.clone(),
|r: JsonValue| {
@@ -833,10 +794,10 @@ pub fn update_direct_chats(url: Url, data: Arc<Mutex<BackendData>>, user: String
if directs.contains_key(&user) {
if let Some(v) = directs.get_mut(&user) {
- v.push(room)
+ v.push(room_id.to_string())
};
} else {
- directs.insert(user, vec![room]);
+ directs.insert(user, vec![room_id.to_string()]);
}
data.lock().unwrap().m_direct = directs.clone();
@@ -855,7 +816,7 @@ pub fn direct_chat(
access_token: AccessToken,
userid: String,
user: Member,
- internal_id: String,
+ internal_id: RoomId,
) -> Result<(), Error> {
let url = bk.url(base.clone(), &access_token, "createRoom", vec![])?;
let attrs = json!({
@@ -885,14 +846,24 @@ pub fn direct_chat(
url,
&attrs,
move |r: JsonValue| {
- let id = String::from(r["room_id"].as_str().unwrap_or_default());
- let mut r = Room::new(id.clone(), RoomMembership::Joined(RoomTag::None));
- r.name = user.alias.clone();
- r.direct = true;
- tx.send(BKResponse::NewRoom(Ok(r), internal_id))
- .expect_log("Connection closed");
+ match RoomId::try_from(r["room_id"].as_str().unwrap_or_default()) {
+ Ok(room_id) => {
+ let r = Room {
+ name: user.alias.clone(),
+ direct: true,
+ ..Room::new(room_id.clone(), RoomMembership::Joined(RoomTag::None))
+ };
+
+ tx.send(BKResponse::NewRoom(Ok(r), internal_id))
+ .expect_log("Connection closed");
- update_direct_chats(direct_url, data, user.uid.clone(), id);
+ update_direct_chats(direct_url, data, user.uid.clone(), room_id);
+ }
+ Err(err) => {
+ tx.send(BKResponse::NewRoom(Err(err.into()), internal_id))
+ .expect_log("Connection closed");
+ }
+ }
},
|err| {
tx.send(BKResponse::NewRoom(Err(err), internal_id))
@@ -904,76 +875,50 @@ pub fn direct_chat(
}
pub fn add_to_fav(
- bk: &Backend,
base: Url,
access_token: AccessToken,
userid: String,
- roomid: String,
+ room_id: RoomId,
tofav: bool,
-) -> Result<(), Error> {
- let tx = bk.tx.clone();
-
- let room_id = RoomId::try_from(roomid.as_str())?;
-
- thread::spawn(move || {
- let request_res = if tofav {
- let params = CreateTagParameters { access_token };
- let body = CreateTagBody { order: Some(0.5) };
- create_tag(base, &userid, &room_id, "m.favourite", ¶ms, &body)
- } else {
- let params = DeleteTagParameters { access_token };
- delete_tag(base, &userid, &room_id, "m.favourite", ¶ms)
- };
-
- let query = request_res
- .map_err(Into::into)
- .and_then(|request| {
- HTTP_CLIENT
- .get_client()?
- .execute(request)
- .map_err(Into::into)
- })
- .and(Ok((room_id.to_string(), tofav)));
-
- tx.send(BKResponse::AddedToFav(query))
- .expect_log("Connection closed");
- });
+) -> Result<(RoomId, bool), Error> {
+ let request_res = if tofav {
+ let params = CreateTagParameters { access_token };
+ let body = CreateTagBody { order: Some(0.5) };
+ create_tag(base, &userid, &room_id, "m.favourite", ¶ms, &body)
+ } else {
+ let params = DeleteTagParameters { access_token };
+ delete_tag(base, &userid, &room_id, "m.favourite", ¶ms)
+ };
- Ok(())
+ request_res
+ .map_err(Into::into)
+ .and_then(|request| {
+ HTTP_CLIENT
+ .get_client()?
+ .execute(request)
+ .map_err(Into::into)
+ })
+ .and(Ok((room_id, tofav)))
}
pub fn invite(
- bk: &Backend,
base: Url,
access_token: AccessToken,
- roomid: String,
+ room_id: RoomId,
user_id: String,
) -> Result<(), Error> {
- let tx = bk.tx.clone();
-
- let room_id = RoomId::try_from(roomid.as_str())?;
let params = InviteUserParameters { access_token };
let body = InviteUserBody { user_id };
- thread::spawn(move || {
- let query = invite_user(base, &room_id, ¶ms, &body)
- .map_err(Into::into)
- .and_then(|request| {
- HTTP_CLIENT
- .get_client()?
- .execute(request)
- .map_err(Into::into)
- });
-
- match query {
- Err(err) => {
- let _ = tx.send(BKResponse::InviteError(err));
- }
- _ => (),
- }
- });
-
- Ok(())
+ invite_user(base, &room_id, ¶ms, &body)
+ .map_err(Into::into)
+ .and_then(|request| {
+ HTTP_CLIENT
+ .get_client()?
+ .execute(request)
+ .map_err(Into::into)
+ })
+ .and(Ok(()))
}
pub fn set_language(
@@ -981,7 +926,7 @@ pub fn set_language(
access_token: AccessToken,
server: Url,
userid: String,
- roomid: String,
+ room_id: RoomId,
input_language: String,
) -> Result<(), Error> {
let url = bk.url(
@@ -989,8 +934,7 @@ pub fn set_language(
&access_token,
&format!(
"user/{}/rooms/{}/account_data/org.gnome.fractal.language",
- userid,
- roomid.clone()
+ userid, room_id,
),
vec![],
)?;
diff --git a/fractal-matrix-api/src/backend/sync.rs b/fractal-matrix-api/src/backend/sync.rs
index 30fec620..99625106 100644
--- a/fractal-matrix-api/src/backend/sync.rs
+++ b/fractal-matrix-api/src/backend/sync.rs
@@ -237,12 +237,12 @@ pub fn sync(
data.lock().unwrap().m_direct = parse_m_direct(&response.account_data.events);
let rooms = Room::from_sync_response(&response, &userid, &base);
- let jtr = data.lock().unwrap().join_to_room.clone();
- let def = if !jtr.is_empty() {
- rooms.iter().find(|x| x.id == jtr).cloned()
- } else {
- None
- };
+ let def = data
+ .lock()
+ .unwrap()
+ .join_to_room
+ .as_ref()
+ .and_then(|jtr| rooms.iter().find(|x| x.id == *jtr).cloned());
tx.send(BKResponse::Rooms(rooms, def))
.expect_log("Connection closed");
}
diff --git a/fractal-matrix-api/src/backend/types.rs b/fractal-matrix-api/src/backend/types.rs
index 9c700553..a66cfe45 100644
--- a/fractal-matrix-api/src/backend/types.rs
+++ b/fractal-matrix-api/src/backend/types.rs
@@ -1,3 +1,4 @@
+use ruma_identifiers::RoomId;
use std::collections::HashMap;
use std::sync::mpsc::Sender;
use std::sync::{Arc, Condvar, Mutex};
@@ -37,17 +38,17 @@ pub enum BKCommand {
GetAvatar(Url, String),
SetUserAvatar(Url, AccessToken, String, String),
Sync(Url, AccessToken, String, Option<String>, bool),
- GetRoomMembers(Url, AccessToken, String),
- GetRoomMessages(Url, AccessToken, String, String),
- GetRoomMessagesFromMsg(Url, AccessToken, String, Message),
+ GetRoomMembers(Url, AccessToken, RoomId),
+ GetRoomMessages(Url, AccessToken, RoomId, String),
+ GetRoomMessagesFromMsg(Url, AccessToken, RoomId, Message),
GetMessageContext(Url, AccessToken, Message),
- GetRoomAvatar(Url, AccessToken, String),
+ GetRoomAvatar(Url, AccessToken, RoomId),
GetThumbAsync(Url, String, Sender<Result<String, Error>>),
GetMediaAsync(Url, String, Sender<Result<String, Error>>),
GetMediaListAsync(
Url,
AccessToken,
- String,
+ RoomId,
Option<String>,
Option<String>,
Sender<(Vec<Message>, String)>,
@@ -59,26 +60,27 @@ pub enum BKCommand {
GetUserNameAsync(Url, String, Sender<String>),
SendMsg(Url, AccessToken, Message),
SendMsgRedaction(Url, AccessToken, Message),
- SendTyping(Url, AccessToken, String, String),
- SetRoom(Url, AccessToken, String),
+ SendTyping(Url, AccessToken, String, RoomId),
+ SetRoom(Url, AccessToken, RoomId),
ShutDown,
DirectoryProtocols(Url, AccessToken),
DirectorySearch(Url, AccessToken, String, String, String, bool),
- JoinRoom(Url, AccessToken, String),
- MarkAsRead(Url, AccessToken, String, String),
- LeaveRoom(Url, AccessToken, String),
- SetRoomName(Url, AccessToken, String, String),
- SetRoomTopic(Url, AccessToken, String, String),
- SetRoomAvatar(Url, AccessToken, String, String),
+ JoinRoom(Url, AccessToken, RoomId),
+ MarkAsRead(Url, AccessToken, RoomId, String),
+ LeaveRoom(Url, AccessToken, RoomId),
+ SetRoomName(Url, AccessToken, RoomId, String),
+ SetRoomTopic(Url, AccessToken, RoomId, String),
+ SetRoomAvatar(Url, AccessToken, RoomId, String),
AttachFile(Url, AccessToken, Message),
- NewRoom(Url, AccessToken, String, RoomType, String),
- DirectChat(Url, AccessToken, String, Member, String),
- AddToFav(Url, AccessToken, String, String, bool),
- AcceptInv(Url, AccessToken, String),
- RejectInv(Url, AccessToken, String),
+ NewRoom(Url, AccessToken, String, RoomType, RoomId),
+ DirectChat(Url, AccessToken, String, Member, RoomId),
+ AddToFav(Url, AccessToken, String, RoomId, bool),
+ AcceptInv(Url, AccessToken, RoomId),
+ RejectInv(Url, AccessToken, RoomId),
UserSearch(Url, AccessToken, String),
- Invite(Url, AccessToken, String, String),
- ChangeLanguage(AccessToken, Url, String, String, String),
+ Invite(Url, AccessToken, RoomId, String),
+ ChangeLanguage(AccessToken, Url, String, RoomId, String),
+ SendBKResponse(BKResponse),
}
#[derive(Debug)]
@@ -101,33 +103,33 @@ pub enum BKResponse {
Sync(Result<String, Error>),
Rooms(Vec<Room>, Option<Room>),
UpdateRooms(Vec<Room>),
- RoomDetail(Result<(String, String, String), Error>),
- RoomAvatar(Result<(String, Option<Url>), Error>),
- NewRoomAvatar(String),
+ RoomDetail(Result<(RoomId, String, String), Error>),
+ RoomAvatar(Result<(RoomId, Option<Url>), Error>),
+ NewRoomAvatar(RoomId),
RoomMemberEvent(Event),
RoomMessages(Vec<Message>),
RoomMessagesInit(Vec<Message>),
- RoomMessagesTo(Result<(Vec<Message>, String, Option<String>), Error>),
- RoomMembers(Result<(String, Vec<Member>), Error>),
+ RoomMessagesTo(Result<(Vec<Message>, RoomId, Option<String>), Error>),
+ RoomMembers(Result<(RoomId, Vec<Member>), Error>),
SentMsg(Result<(String, String), Error>),
SentMsgRedaction(Result<(String, String), Error>),
DirectoryProtocols(Result<Vec<ProtocolInstance>, Error>),
DirectorySearch(Result<Vec<Room>, Error>),
JoinRoom(Result<(), Error>),
LeaveRoom(Result<(), Error>),
- MarkedAsRead(Result<(String, String), Error>),
+ MarkedAsRead(Result<(RoomId, String), Error>),
SetRoomName(Result<(), Error>),
SetRoomTopic(Result<(), Error>),
SetRoomAvatar(Result<(), Error>),
- RemoveMessage(Result<(String, String), Error>),
- RoomName(String, String),
- RoomTopic(String, String),
+ RemoveMessage(Result<(RoomId, String), Error>),
+ RoomName(RoomId, String),
+ RoomTopic(RoomId, String),
Media(Result<String, Error>),
MediaUrl(Url),
AttachedFile(Result<Message, Error>),
- NewRoom(Result<Room, Error>, String),
- AddedToFav(Result<(String, bool), Error>),
- RoomNotifications(String, i32, i32),
+ NewRoom(Result<Room, Error>, RoomId),
+ AddedToFav(Result<(RoomId, bool), Error>),
+ RoomNotifications(RoomId, i32, i32),
UserSearch(Result<Vec<Member>, Error>),
//errors
@@ -148,7 +150,7 @@ pub enum RoomType {
pub struct BackendData {
pub rooms_since: String,
- pub join_to_room: String,
+ pub join_to_room: Option<RoomId>,
pub m_direct: HashMap<String, Vec<String>>,
}
diff --git a/fractal-matrix-api/src/model/event.rs b/fractal-matrix-api/src/model/event.rs
index cdd20e64..83bdbf58 100644
--- a/fractal-matrix-api/src/model/event.rs
+++ b/fractal-matrix-api/src/model/event.rs
@@ -1,10 +1,11 @@
+use ruma_identifiers::RoomId;
use serde_json::Value as JsonValue;
#[derive(Debug, Clone)]
pub struct Event {
pub sender: String,
pub stype: String,
- pub room: String,
+ pub room: RoomId,
pub id: String,
pub redacts: String,
pub content: JsonValue,
diff --git a/fractal-matrix-api/src/model/message.rs b/fractal-matrix-api/src/model/message.rs
index 85a79904..884d5dbe 100644
--- a/fractal-matrix-api/src/model/message.rs
+++ b/fractal-matrix-api/src/model/message.rs
@@ -1,6 +1,7 @@
use chrono::prelude::*;
use chrono::DateTime;
use chrono::TimeZone;
+use ruma_identifiers::RoomId;
use serde::{Deserialize, Serialize};
use serde_json::Value as JsonValue;
use std::cmp::Ordering;
@@ -13,7 +14,7 @@ pub struct Message {
pub mtype: String,
pub body: String,
pub date: DateTime<Local>,
- pub room: String,
+ pub room: RoomId,
pub thumb: Option<String>,
pub url: Option<String>,
pub id: String,
@@ -47,7 +48,7 @@ impl PartialOrd for Message {
}
impl Message {
- pub fn new(room: String, sender: String, body: String, mtype: String) -> Self {
+ pub fn new(room: RoomId, sender: String, body: String, mtype: String) -> Self {
let date = Local::now();
Message {
id: get_txn_id(&room, &body, &date.to_string()),
@@ -95,7 +96,7 @@ impl Message {
///
/// * `roomid` - The message room id
/// * `msg` - The message event as Json
- pub fn parse_room_message(roomid: &str, msg: &JsonValue) -> Message {
+ pub fn parse_room_message(room_id: &RoomId, msg: &JsonValue) -> Message {
let sender = msg["sender"].as_str().unwrap_or_default();
let timestamp = msg["origin_server_ts"].as_i64().unwrap_or_default() / 1000;
@@ -109,7 +110,7 @@ impl Message {
let mut message = Message {
sender: sender.to_string(),
date: server_timestamp,
- room: String::from(roomid),
+ room: room_id.clone(),
id: id.to_string(),
mtype: type_.to_string(),
body: String::new(),
@@ -126,78 +127,77 @@ impl Message {
let c = &msg["content"];
match type_ {
- "m.room.message" => Message::parse_m_room_message(&mut message, c),
- "m.sticker" => Message::parse_m_sticker(&mut message, c),
+ "m.room.message" => message.parse_m_room_message(c),
+ "m.sticker" => message.parse_m_sticker(c),
_ => {}
};
message
}
- fn parse_m_room_message(msg: &mut Message, c: &JsonValue) {
- let mtype = c["msgtype"].as_str().unwrap_or_default();
- let body = c["body"].as_str().unwrap_or_default();
+ fn parse_m_room_message(&mut self, c: &JsonValue) {
+ let mtype = c["msgtype"].as_str().map(String::from).unwrap_or_default();
+ let body = c["body"].as_str().map(String::from).unwrap_or_default();
let formatted_body = c["formatted_body"].as_str().map(String::from);
let format = c["format"].as_str().map(String::from);
- match mtype {
+ match mtype.as_str() {
"m.image" | "m.file" | "m.video" | "m.audio" => {
- let url = String::from(c["url"].as_str().unwrap_or_default());
- let mut t = String::from(c["info"]["thumbnail_url"].as_str().unwrap_or_default());
+ let url = c["url"].as_str().map(String::from).unwrap_or_default();
+ let mut t = c["info"]["thumbnail_url"]
+ .as_str()
+ .map(String::from)
+ .unwrap_or_default();
if t.is_empty() && !url.is_empty() {
t = url.clone();
}
- msg.url = Some(url);
- msg.thumb = Some(t);
+ self.url = Some(url);
+ self.thumb = Some(t);
}
"m.text" => {
// Only m.text messages can be replies for backward compatability
// https://matrix.org/docs/spec/client_server/r0.4.0.html#rich-replies
- msg.in_reply_to = c["m.relates_to"]["m.in_reply_to"]["event_id"]
+ self.in_reply_to = c["m.relates_to"]["m.in_reply_to"]["event_id"]
.as_str()
- .map(String::from)
+ .map(String::from);
}
_ => {}
};
- msg.mtype = mtype.to_string();
- msg.body = body.to_string();
- msg.formatted_body = formatted_body;
- msg.format = format;
+ self.mtype = mtype;
+ self.body = body;
+ self.formatted_body = formatted_body;
+ self.format = format;
}
- fn parse_m_sticker(msg: &mut Message, c: &JsonValue) {
- let body = c["body"].as_str().unwrap_or_default();
-
- let url = String::from(c["url"].as_str().unwrap_or_default());
- let mut t = String::from(c["info"]["thumbnail_url"].as_str().unwrap_or_default());
+ fn parse_m_sticker(&mut self, c: &JsonValue) {
+ let url = c["url"].as_str().map(String::from).unwrap_or_default();
+ let mut t = c["info"]["thumbnail_url"]
+ .as_str()
+ .map(String::from)
+ .unwrap_or_default();
if t.is_empty() && !url.is_empty() {
t = url.clone();
}
- msg.body = body.to_string();
- msg.url = Some(url);
- msg.thumb = Some(t);
+ self.body = c["body"].as_str().map(String::from).unwrap_or_default();
+ self.url = Some(url);
+ self.thumb = Some(t);
}
/// Create a vec of Message from a json event list
///
/// * `roomid` - The messages room id
/// * `events` - An iterator to the json events
- pub fn from_json_events_iter<'a, I>(roomid: &str, events: I) -> Vec<Message>
+ pub fn from_json_events_iter<'a, I>(room_id: &RoomId, events: I) -> Vec<Message>
where
I: Iterator<Item = &'a JsonValue>,
{
- let mut ms = vec![];
-
- let evs = events.filter(Message::supported_event);
- for msg in evs {
- let m = Message::parse_room_message(roomid.clone(), msg);
- ms.push(m);
- }
-
- ms
+ events
+ .filter(Message::supported_event)
+ .map(|msg| Message::parse_room_message(&room_id, msg))
+ .collect()
}
pub fn set_receipt(&mut self, receipt: HashMap<String, i64>) {
@@ -209,7 +209,7 @@ impl Message {
/// message body and the date.
///
https://matrix.org/docs/spec/client_server/r0.3.0.html#put-matrix-client-r0-rooms-roomid-send-eventtype-txnid
-pub fn get_txn_id(room: &str, body: &str, date: &str) -> String {
+pub fn get_txn_id(room: &RoomId, body: &str, date: &str) -> String {
let msg = format!("{}{}{}", room, body, date);
let digest = md5::compute(msg.as_bytes());
format!("{:x}", digest)
diff --git a/fractal-matrix-api/src/model/room.rs b/fractal-matrix-api/src/model/room.rs
index 7186d5a6..e250c4e3 100644
--- a/fractal-matrix-api/src/model/room.rs
+++ b/fractal-matrix-api/src/model/room.rs
@@ -8,6 +8,7 @@ use crate::r0::sync::sync_events::Response as SyncResponse;
use crate::util::get_user_avatar;
use crate::util::parse_m_direct;
use log::{debug, info};
+use ruma_identifiers::RoomId;
use serde::{Deserialize, Serialize};
use std::collections::{HashMap, HashSet};
use url::Url;
@@ -76,9 +77,9 @@ pub enum RoomTag {
Custom(String),
}
-#[derive(Debug, Clone, Default, Serialize, Deserialize)]
+#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Room {
- pub id: String,
+ pub id: RoomId,
pub avatar: Option<String>, // TODO: Use Option<Url>
pub name: Option<String>,
pub topic: Option<String>,
@@ -103,13 +104,27 @@ pub struct Room {
}
impl Room {
- pub fn new(id: String, membership: RoomMembership) -> Room {
+ pub fn new(id: RoomId, membership: RoomMembership) -> Room {
Room {
id,
membership,
guest_can_join: true,
world_readable: true,
- ..Default::default()
+ avatar: Default::default(),
+ name: Default::default(),
+ topic: Default::default(),
+ alias: Default::default(),
+ n_members: Default::default(),
+ members: Default::default(),
+ notifications: Default::default(),
+ highlight: Default::default(),
+ messages: Default::default(),
+ direct: Default::default(),
+ prev_batch: Default::default(),
+ typing_users: Default::default(),
+ language: Default::default(),
+ admins: Default::default(),
+ power_levels: Default::default(),
}
}
@@ -143,7 +158,7 @@ impl Room {
avatar: evc(stevents, "m.room.avatar", "url"),
alias: evc(stevents, "m.room.canonical_alias", "alias"),
topic: evc(stevents, "m.room.topic", "topic"),
- direct: direct.contains(k),
+ direct: direct.contains(&k.to_string()),
notifications: room.unread_notifications.notification_count,
highlight: room.unread_notifications.highlight_count,
prev_batch: timeline.prev_batch.clone(),
@@ -228,7 +243,7 @@ impl Room {
avatar: evc(stevents, "m.room.avatar", "url"),
alias: evc(stevents, "m.room.canonical_alias", "alias"),
topic: evc(stevents, "m.room.topic", "topic"),
- direct: direct.contains(k),
+ direct: direct.contains(&k.to_string()),
..Self::new(k.clone(), RoomMembership::Invited(inv_sender))
})
} else {
@@ -294,7 +309,7 @@ impl From<PublicRoomsChunk> for Room {
n_members: input.num_joined_members,
world_readable: input.world_readable,
guest_can_join: input.guest_can_join,
- ..Self::new(input.room_id.to_string(), RoomMembership::None)
+ ..Self::new(input.room_id, RoomMembership::None)
}
}
}
@@ -305,7 +320,7 @@ impl PartialEq for Room {
}
}
-pub type RoomList = HashMap<String, Room>;
+pub type RoomList = HashMap<RoomId, Room>;
fn evc(events: &Vec<JsonValue>, t: &str, field: &str) -> Option<String> {
events
diff --git a/fractal-matrix-api/src/r0/sync/sync_events.rs b/fractal-matrix-api/src/r0/sync/sync_events.rs
index d3c2e6ae..5aaf9bc2 100644
--- a/fractal-matrix-api/src/r0/sync/sync_events.rs
+++ b/fractal-matrix-api/src/r0/sync/sync_events.rs
@@ -3,6 +3,7 @@ use crate::r0::AccessToken;
use reqwest::Client;
use reqwest::Error;
use reqwest::Request;
+use ruma_identifiers::RoomId;
use serde::ser::SerializeMap;
use serde::{Deserialize, Serialize, Serializer};
use serde_json::Value as JsonValue;
@@ -111,11 +112,11 @@ pub struct Response {
#[derive(Clone, Debug, Default, Deserialize)]
pub struct Rooms {
#[serde(default)]
- pub leave: HashMap<String, LeftRoom>,
+ pub leave: HashMap<RoomId, LeftRoom>,
#[serde(default)]
- pub join: HashMap<String, JoinedRoom>,
+ pub join: HashMap<RoomId, JoinedRoom>,
#[serde(default)]
- pub invite: HashMap<String, InvitedRoom>,
+ pub invite: HashMap<RoomId, InvitedRoom>,
}
#[derive(Clone, Debug, Deserialize)]
diff --git a/fractal-matrix-api/src/util.rs b/fractal-matrix-api/src/util.rs
index 47db4fdb..202bda53 100644
--- a/fractal-matrix-api/src/util.rs
+++ b/fractal-matrix-api/src/util.rs
@@ -5,6 +5,7 @@ use serde_json::json;
use serde_json::Value as JsonValue;
use directories::ProjectDirs;
+use ruma_identifiers::RoomId;
use std::collections::HashMap;
use std::io::Read;
use std::path::Path;
@@ -193,12 +194,12 @@ pub fn parse_m_direct(events: &Vec<JsonValue>) -> HashMap<String, Vec<String>> {
pub fn get_prev_batch_from(
baseu: &Url,
tk: &AccessToken,
- roomid: &str,
+ room_id: &RoomId,
evid: &str,
) -> Result<String, Error> {
let params = &[("access_token", tk.to_string()), ("limit", 0.to_string())];
- let path = format!("rooms/{}/context/{}", roomid, evid);
+ let path = format!("rooms/{}/context/{}", room_id, evid);
let url = client_url(baseu, &path, params)?;
let r = json_q("get", url, &json!(null))?;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]