[fractal] Search room directory and download files through matrix-sdk



commit 0393568ca48194f58fba2fc681255b4d4e6485ef
Author: Alejandro Domínguez <adomu net-c com>
Date:   Sat Aug 15 23:46:01 2020 +0200

    Search room directory and download files through matrix-sdk

 fractal-gtk/src/actions/message.rs                 | 135 +++++++++------------
 fractal-gtk/src/appop/account.rs                   |   2 +-
 fractal-gtk/src/appop/directory.rs                 |  52 ++++----
 fractal-gtk/src/appop/media_viewer.rs              |   8 +-
 fractal-gtk/src/appop/message.rs                   |  10 ++
 fractal-gtk/src/appop/notify.rs                    |   4 +-
 fractal-gtk/src/appop/room.rs                      |  20 +--
 fractal-gtk/src/appop/room_settings.rs             |   2 +-
 fractal-gtk/src/appop/sync.rs                      |   2 +-
 fractal-gtk/src/appop/user.rs                      |   6 +-
 fractal-gtk/src/backend/directory.rs               | 121 +++++++++---------
 fractal-gtk/src/backend/media.rs                   |  21 ++--
 fractal-gtk/src/backend/mod.rs                     |  76 +++++++-----
 fractal-gtk/src/backend/room.rs                    |  29 ++++-
 fractal-gtk/src/backend/sync.rs                    |  31 +++--
 fractal-gtk/src/backend/user.rs                    |  16 ++-
 fractal-gtk/src/cache/mod.rs                       |   5 +-
 fractal-gtk/src/globals.rs                         |   2 +-
 fractal-gtk/src/model/room.rs                      |  30 ++---
 fractal-gtk/src/widgets/image.rs                   |  45 +++----
 fractal-gtk/src/widgets/inline_player.rs           |  94 ++++++--------
 fractal-gtk/src/widgets/media_viewer.rs            |  78 +++++++-----
 fractal-gtk/src/widgets/member.rs                  |   4 +-
 fractal-gtk/src/widgets/message.rs                 |  75 +++++++-----
 fractal-gtk/src/widgets/room.rs                    |  23 ++--
 fractal-gtk/src/widgets/room_history.rs            |  56 ++++++---
 fractal-gtk/src/widgets/room_settings.rs           |  14 +--
 fractal-matrix-api/src/meson.build                 |   4 -
 fractal-matrix-api/src/r0.rs                       |   1 -
 fractal-matrix-api/src/r0/context/get_context.rs   |   2 +-
 fractal-matrix-api/src/r0/directory.rs             |   1 -
 .../src/r0/directory/post_public_rooms.rs          | 102 ----------------
 fractal-matrix-api/src/r0/media.rs                 |   2 -
 fractal-matrix-api/src/r0/media/get_content.rs     |  33 -----
 .../src/r0/media/get_content_thumbnail.rs          |  37 ------
 35 files changed, 507 insertions(+), 636 deletions(-)
---
diff --git a/fractal-gtk/src/actions/message.rs b/fractal-gtk/src/actions/message.rs
index a4de118b..05d80621 100644
--- a/fractal-gtk/src/actions/message.rs
+++ b/fractal-gtk/src/actions/message.rs
@@ -1,18 +1,17 @@
-use crate::backend::{dw_media, media, room, ContentType, ThreadPool};
+use crate::backend::{dw_media, media, room, ContentType};
 use fractal_api::identifiers::RoomId;
 use fractal_api::r0::AccessToken;
+use fractal_api::Client as MatrixClient;
 use glib::clone;
 use log::error;
 use std::cell::RefCell;
 use std::fs;
 use std::process::Command;
 use std::rc::Rc;
-use std::sync::mpsc::channel;
-use std::sync::mpsc::TryRecvError;
-use std::sync::mpsc::{Receiver, Sender};
 use std::thread;
 
 use crate::actions::AppState;
+use crate::app::RUNTIME;
 use crate::backend::HandleError;
 use crate::model::message::Message;
 use crate::uibuilder::UI;
@@ -23,7 +22,6 @@ use gio::ActionGroupExt;
 use gio::ActionMapExt;
 use gio::SimpleAction;
 use gio::SimpleActionGroup;
-use glib::source::Continue;
 use gtk::prelude::*;
 
 use super::global::{get_event_id, get_message_by_id, get_room_id};
@@ -34,12 +32,12 @@ use crate::widgets::SourceDialog;
 
 /* This creates all actions the room history can perform */
 pub fn new(
-    thread_pool: ThreadPool,
-    server_url: Url,
+    session_client: MatrixClient,
     access_token: AccessToken,
     ui: UI,
     back_history: Rc<RefCell<Vec<AppState>>>,
 ) -> gio::SimpleActionGroup {
+    let server_url = session_client.homeserver().clone();
     let actions = SimpleActionGroup::new();
     /* Action for each message */
     let reply = SimpleAction::new("reply", glib::VariantTy::new("s").ok());
@@ -112,92 +110,69 @@ pub fn new(
         }
     }));
 
-    open_with.connect_activate(clone!(@strong server_url => move |_, data| {
-        if let Some(m) = get_message(data) {
-            if let Some(url) = m.url {
-                thread::spawn(clone!(@strong server_url => move || {
-                    match dw_media(server_url, &url, ContentType::Download, None) {
-                        Ok(fname) => {
-                            Command::new("xdg-open")
-                                .arg(&fname)
-                                .spawn()
-                                .expect("failed to execute process");
-                        }
-                        Err(err) => {
-                            err.handle_error()
-                        }
+    open_with.connect_activate(clone!(@strong session_client => move |_, data| {
+        if let Some(url) = get_message(data).and_then(|m| m.url) {
+            let session_client = session_client.clone();
+            RUNTIME.spawn(async move {
+                match dw_media(session_client, &url, ContentType::Download, None).await {
+                    Ok(fname) => {
+                        Command::new("xdg-open")
+                            .arg(&fname)
+                            .spawn()
+                            .expect("failed to execute process");
                     }
-                }));
-            }
+                    Err(err) => {
+                        err.handle_error()
+                    }
+                }
+            });
         }
     }));
 
     save_as.connect_activate(clone!(
-    @strong server_url,
-    @strong thread_pool,
+    @strong session_client,
     @weak parent as window
     => move |_, data| {
-        if let Some(m) = get_message(data) {
-            if let Some(url) = m.url {
-                let name = m.body;
-
-                let (tx, rx): (
-                    Sender<media::MediaResult>,
-                    Receiver<media::MediaResult>,
-                ) = channel();
-
-                media::get_media_async(thread_pool.clone(), server_url.clone(), url, tx);
-
-                glib::timeout_add_local(
-                    50,
-                    clone!(
-                        @strong name,
-                        @weak window
-                        => @default-return Continue(true), move || match rx.try_recv() {
-                            Err(TryRecvError::Empty) => Continue(true),
-                            Err(TryRecvError::Disconnected) => {
-                                let msg = i18n("Could not download the file");
-                                ErrorDialog::new(false, &msg);
+        if let Some((Some(url), name)) = get_message(data).map(|m| (m.url, m.body)) {
+            let session_client = session_client.clone();
+            let response = RUNTIME.spawn(async move {
+                media::get_media(session_client, &url).await
+            });
 
-                                Continue(true)
-                            },
-                            Ok(Ok(fname)) => {
-                                if let Some(path) = save(&window.upcast_ref(), &name, &[]) {
-                                    // TODO use glib to copy file
-                                    if fs::copy(fname, path).is_err() {
-                                        ErrorDialog::new(false, &i18n("Couldn’t save file"));
-                                    }
-                                }
-                                Continue(false)
-                            }
-                            Ok(Err(err)) => {
-                                error!("Media path could not be found due to error: {:?}", err);
-                                Continue(false)
+            glib::MainContext::default().spawn_local(async move {
+                match response.await {
+                    Err(_) => {
+                        let msg = i18n("Could not download the file");
+                        ErrorDialog::new(false, &msg);
+                    },
+                    Ok(Ok(fname)) => {
+                        if let Some(path) = save(&window.upcast_ref(), &name, &[]) {
+                            // TODO use glib to copy file
+                            if fs::copy(fname, path).is_err() {
+                                ErrorDialog::new(false, &i18n("Couldn’t save file"));
                             }
                         }
-                    ),
-                );
-            }
+                    }
+                    Ok(Err(err)) => {
+                        error!("Media path could not be found due to error: {:?}", err);
+                    }
+                }
+            });
         }
     }));
 
-    copy_image.connect_activate(clone!(@strong server_url => move |_, data| {
-        if let Some(m) = get_message(data) {
-            if let Some(url) = m.url {
-                let (tx, rx): (
-                    Sender<media::MediaResult>,
-                    Receiver<media::MediaResult>,
-                ) = channel();
-
-                media::get_media_async(thread_pool.clone(), server_url.clone(), url, tx);
+    copy_image.connect_activate(clone!(@strong session_client => move |_, data| {
+        if let Some(url) = get_message(data).and_then(|m| m.url) {
+            let session_client = session_client.clone();
+            let response = RUNTIME.spawn(async move {
+                media::get_media(session_client, &url).await
+            });
 
-                glib::timeout_add_local(50, move || match rx.try_recv() {
-                    Err(TryRecvError::Empty) => Continue(true),
-                    Err(TryRecvError::Disconnected) => {
+            glib::MainContext::default().spawn_local(async move {
+                match response.await {
+                    Err(_) => {
                         let msg = i18n("Could not download the file");
                         ErrorDialog::new(false, &msg);
-
-                        Continue(true)
                     }
                     Ok(Ok(fname)) => {
                         if let Ok(pixbuf) = gdk_pixbuf::Pixbuf::from_file(fname) {
@@ -205,14 +180,12 @@ pub fn new(
                             let clipboard = gtk::Clipboard::get(&atom);
                             clipboard.set_image(&pixbuf);
                         }
-                        Continue(false)
                     }
                     Ok(Err(err)) => {
                         error!("Image path could not be found due to error: {:?}", err);
-                        Continue(false)
                     }
-                });
-            }
+                }
+            });
         }
     }));
 
diff --git a/fractal-gtk/src/appop/account.rs b/fractal-gtk/src/appop/account.rs
index 5fd378fd..c8ba7411 100644
--- a/fractal-gtk/src/appop/account.rs
+++ b/fractal-gtk/src/appop/account.rs
@@ -543,9 +543,9 @@ impl AppOp {
             None,
         );
         download_to_cache(
+            login_data.session_client.clone(),
             self.thread_pool.clone(),
             self.user_info_cache.clone(),
-            login_data.session_client.homeserver().clone(),
             login_data.access_token,
             login_data.uid,
             data,
diff --git a/fractal-gtk/src/appop/directory.rs b/fractal-gtk/src/appop/directory.rs
index cc9e8a49..a2cf8064 100644
--- a/fractal-gtk/src/appop/directory.rs
+++ b/fractal-gtk/src/appop/directory.rs
@@ -3,13 +3,14 @@ use std::thread;
 
 use crate::backend::{directory, HandleError};
 
-use crate::app::App;
+use crate::app::{App, RUNTIME};
 use crate::appop::AppOp;
 
 use crate::widgets;
 
 use super::RoomSearchPagination;
 use crate::model::room::Room;
+use fractal_api::directory::RoomNetwork;
 use fractal_api::r0::thirdparty::get_supported_protocols::ProtocolInstance;
 
 impl AppOp {
@@ -44,14 +45,15 @@ impl AppOp {
     }
 
     pub fn search_rooms(&mut self) {
-        let login_data = unwrap_or_unit_return!(self.login_data.clone());
+        let session_client =
+            unwrap_or_unit_return!(self.login_data.as_ref().map(|ld| ld.session_client.clone()));
         let other_protocol_radio = self
             .ui
             .builder
             .get_object::<gtk::RadioButton>("other_protocol_radio")
             .expect("Can't find other_protocol_radio in ui file.");
 
-        let mut protocol = if other_protocol_radio.get_active() {
+        let protocol: Option<String> = if other_protocol_radio.get_active() {
             let protocol_combo = self
                 .ui
                 .builder
@@ -65,15 +67,12 @@ impl AppOp {
                 .expect("Can't find protocol_model in ui file.");
 
             let active = protocol_combo.get_active().map_or(-1, |uint| uint as i32);
-            match protocol_model.iter_nth_child(None, active) {
-                Some(it) => {
-                    let v = protocol_model.get_value(&it, 1);
-                    v.get().unwrap().unwrap()
-                }
-                None => String::new(),
-            }
+
+            protocol_model
+                .iter_nth_child(None, active)
+                .and_then(|it| protocol_model.get_value(&it, 1).get().ok()?)
         } else {
-            String::new()
+            None
         };
 
         let q = self
@@ -95,12 +94,9 @@ impl AppOp {
             .expect("Can't find other_homeserver_url in ui file.");
 
         let homeserver = if other_homeserver_radio.get_active() {
-            other_homeserver_url.get_text()
-        } else if protocol == "matrix.org" {
-            protocol = String::new();
-            String::from("matrix.org")
+            Some(other_homeserver_url.get_text())
         } else {
-            String::new()
+            None
         };
 
         if !self.directory_pagination.has_more() {
@@ -130,22 +126,24 @@ impl AppOp {
             q.set_sensitive(false);
         }
 
-        let search_term = q.get_text().to_string();
+        let search_term = Some(q.get_text().to_string()).filter(|s| !s.is_empty());
         if let RoomSearchPagination::NoMorePages = self.directory_pagination {
             // there are no more rooms. We don't need to request for more
             return;
         }
 
-        let rooms_since = self.directory_pagination.clone().into();
-        thread::spawn(move || {
+        let rooms_since: Option<String> = self.directory_pagination.clone().into();
+        RUNTIME.spawn(async move {
             let query = directory::room_search(
-                login_data.session_client.homeserver().clone(),
-                login_data.access_token,
-                homeserver,
-                search_term,
-                protocol,
-                rooms_since,
-            );
+                session_client,
+                homeserver.as_deref(),
+                search_term.as_deref(),
+                protocol
+                    .as_deref()
+                    .map_or(RoomNetwork::Matrix, RoomNetwork::ThirdParty),
+                rooms_since.as_deref(),
+            )
+            .await;
 
             match query {
                 Ok((rooms, rooms_since)) => {
@@ -188,7 +186,7 @@ impl AppOp {
         directory_stack.set_visible_child(&directory_clamp);
 
         let mut sorted_rooms = rooms;
-        sorted_rooms.sort_by_key(|a| -a.n_members);
+        sorted_rooms.sort_by_key(|a| -i128::from(a.n_members));
 
         for r in sorted_rooms.iter() {
             self.directory.push(r.clone());
diff --git a/fractal-gtk/src/appop/media_viewer.rs b/fractal-gtk/src/appop/media_viewer.rs
index 1cd9ad8d..98145f04 100644
--- a/fractal-gtk/src/appop/media_viewer.rs
+++ b/fractal-gtk/src/appop/media_viewer.rs
@@ -38,15 +38,15 @@ impl AppOp {
                 login_data.access_token,
                 login_data.uid,
             );
-            panel.display_media_viewer(self.thread_pool.clone(), msg);
-            let (body, header) = panel.create(self.thread_pool.clone())?;
+            panel.display_media_viewer(login_data.session_client.clone(), msg);
+            let (body, header) =
+                panel.create(login_data.session_client.clone(), self.thread_pool.clone())?;
             *self.media_viewer.borrow_mut() = Some(panel);
 
             if let Some(login_data) = self.login_data.clone() {
                 let back_history = self.room_back_history.clone();
                 let actions = actions::Message::new(
-                    self.thread_pool.clone(),
-                    login_data.session_client.homeserver().clone(),
+                    login_data.session_client,
                     login_data.access_token,
                     self.ui.clone(),
                     back_history,
diff --git a/fractal-gtk/src/appop/message.rs b/fractal-gtk/src/appop/message.rs
index e757dcf6..20868c51 100644
--- a/fractal-gtk/src/appop/message.rs
+++ b/fractal-gtk/src/appop/message.rs
@@ -48,9 +48,11 @@ impl AppOp {
     }
 
     pub fn add_room_message(&mut self, msg: &Message) -> Option<()> {
+        let session_client = self.login_data.as_ref()?.session_client.clone();
         if let Some(ui_msg) = self.create_new_room_message(msg) {
             if let Some(ref mut history) = self.history {
                 history.add_new_message(
+                    session_client,
                     self.thread_pool.clone(),
                     self.user_info_cache.clone(),
                     ui_msg,
@@ -61,9 +63,12 @@ impl AppOp {
     }
 
     pub fn remove_room_message(&mut self, msg: &Message) {
+        let session_client =
+            unwrap_or_unit_return!(self.login_data.as_ref().map(|ld| ld.session_client.clone()));
         if let Some(ui_msg) = self.create_new_room_message(msg) {
             if let Some(ref mut history) = self.history {
                 history.remove_message(
+                    session_client,
                     self.thread_pool.clone(),
                     self.user_info_cache.clone(),
                     ui_msg,
@@ -81,6 +86,7 @@ impl AppOp {
                 login_data.access_token,
             )
             .tmpwidget(
+                login_data.session_client.clone(),
                 self.thread_pool.clone(),
                 self.user_info_cache.clone(),
                 &ui_msg,
@@ -125,6 +131,7 @@ impl AppOp {
                     login_data.access_token.clone(),
                 )
                 .tmpwidget(
+                    login_data.session_client.clone(),
                     self.thread_pool.clone(),
                     self.user_info_cache.clone(),
                     &ui_msg,
@@ -441,6 +448,8 @@ impl AppOp {
         room_id: RoomId,
         prev_batch: Option<String>,
     ) {
+        let session_client =
+            unwrap_or_unit_return!(self.login_data.as_ref().map(|ld| ld.session_client.clone()));
         if let Some(r) = self.rooms.get_mut(&room_id) {
             r.prev_batch = prev_batch;
         }
@@ -462,6 +471,7 @@ impl AppOp {
 
         if let Some(ref mut history) = self.history {
             history.add_old_messages_in_batch(
+                session_client,
                 self.thread_pool.clone(),
                 self.user_info_cache.clone(),
                 list,
diff --git a/fractal-gtk/src/appop/notify.rs b/fractal-gtk/src/appop/notify.rs
index e5ce591f..47b26e1b 100644
--- a/fractal-gtk/src/appop/notify.rs
+++ b/fractal-gtk/src/appop/notify.rs
@@ -46,7 +46,7 @@ impl AppOp {
     pub fn notify(&self, app: gtk::Application, room_id: &RoomId, id: &EventId) -> Option<()> {
         let login_data = self.login_data.as_ref()?;
         let access_token = login_data.access_token.clone();
-        let server_url = login_data.session_client.homeserver().clone();
+        let session_client = login_data.session_client.clone();
         let msg = self.get_message_by_id(room_id, id)?;
         let r = self.rooms.get(room_id)?;
         let short_body = match &msg.mtype[..] {
@@ -68,8 +68,8 @@ impl AppOp {
         let (tx, rx): (Sender<user::UserInfo>, Receiver<user::UserInfo>) = channel();
         user::get_user_info_async(
             self.thread_pool.clone(),
+            session_client,
             self.user_info_cache.clone(),
-            server_url,
             access_token,
             msg.sender,
             tx,
diff --git a/fractal-gtk/src/appop/room.rs b/fractal-gtk/src/appop/room.rs
index 534a2758..74d76477 100644
--- a/fractal-gtk/src/appop/room.rs
+++ b/fractal-gtk/src/appop/room.rs
@@ -94,19 +94,19 @@ impl AppOp {
                 });
                 // Download the room avatar
                 // TODO: Use the avatar url returned by sync
-                let server = login_data.session_client.homeserver().clone();
+                let session_client = login_data.session_client.clone();
                 let access_token = login_data.access_token.clone();
                 let room_id = room.id.clone();
-                thread::spawn(
-                    move || match room::get_room_avatar(server, access_token, room_id) {
+                thread::spawn(move || {
+                    match room::get_room_avatar(session_client, access_token, room_id) {
                         Ok((room, avatar)) => {
                             APPOP!(set_room_avatar, (room, avatar));
                         }
                         Err(err) => {
                             err.handle_error();
                         }
-                    },
-                );
+                    }
+                });
                 if clear_room_list {
                     roomlist.push(room.clone());
                 } else {
@@ -246,11 +246,11 @@ impl AppOp {
         self.roomlist.select(&active_room);
 
         // getting room details
-        let server_url = login_data.session_client.homeserver().clone();
+        let session_client = login_data.session_client.clone();
         let access_token = login_data.access_token.clone();
         let a_room = active_room.clone();
         thread::spawn(
-            move || match room::get_room_avatar(server_url, access_token, a_room) {
+            move || match room::get_room_avatar(session_client, access_token, a_room) {
                 Ok((room, avatar)) => {
                     APPOP!(set_room_avatar, (room, avatar));
                 }
@@ -302,8 +302,7 @@ impl AppOp {
 
         let back_history = self.room_back_history.clone();
         let actions = actions::Message::new(
-            self.thread_pool.clone(),
-            login_data.session_client.homeserver().clone(),
+            login_data.session_client.clone(),
             login_data.access_token,
             self.ui.clone(),
             back_history,
@@ -311,6 +310,7 @@ impl AppOp {
         let history = widgets::RoomHistory::new(actions, active_room.clone(), self);
         self.history = if let Some(mut history) = history {
             history.create(
+                login_data.session_client,
                 self.thread_pool.clone(),
                 self.user_info_cache.clone(),
                 messages,
@@ -701,7 +701,7 @@ impl AppOp {
 
         thread::spawn(move || {
             match room::get_room_avatar(
-                login_data.session_client.homeserver().clone(),
+                login_data.session_client.clone(),
                 login_data.access_token,
                 room_id,
             ) {
diff --git a/fractal-gtk/src/appop/room_settings.rs b/fractal-gtk/src/appop/room_settings.rs
index d644f154..dfcae863 100644
--- a/fractal-gtk/src/appop/room_settings.rs
+++ b/fractal-gtk/src/appop/room_settings.rs
@@ -28,7 +28,7 @@ impl AppOp {
                 login_data.session_client.homeserver().clone(),
                 login_data.access_token,
             );
-            let page = panel.create()?;
+            let page = panel.create(login_data.session_client.clone())?;
 
             /* remove old panel */
             if let Some(widget) = stack.get_child_by_name("room-settings") {
diff --git a/fractal-gtk/src/appop/sync.rs b/fractal-gtk/src/appop/sync.rs
index b399bc1a..e9a63e31 100644
--- a/fractal-gtk/src/appop/sync.rs
+++ b/fractal-gtk/src/appop/sync.rs
@@ -30,7 +30,7 @@ impl AppOp {
             let since = self.since.clone().filter(|_| !initial);
             thread::spawn(move || {
                 match sync::sync(
-                    login_data.session_client.homeserver().clone(),
+                    login_data.session_client.clone(),
                     login_data.access_token,
                     login_data.uid,
                     join_to_room,
diff --git a/fractal-gtk/src/appop/user.rs b/fractal-gtk/src/appop/user.rs
index e756c1d9..6fd640f0 100644
--- a/fractal-gtk/src/appop/user.rs
+++ b/fractal-gtk/src/appop/user.rs
@@ -33,7 +33,7 @@ impl AppOp {
 
         thread::spawn(clone!(@strong login_data => move || {
             match user::get_user_avatar(
-                login_data.session_client.homeserver().clone(),
+                login_data.session_client.clone(),
                 login_data.access_token,
                 &login_data.uid,
             ) {
@@ -92,9 +92,9 @@ impl AppOp {
                 None,
             );
             download_to_cache(
+                login_data.session_client.clone(),
                 self.thread_pool.clone(),
                 self.user_info_cache.clone(),
-                login_data.session_client.homeserver().clone(),
                 login_data.access_token.clone(),
                 login_data.uid.clone(),
                 data,
@@ -118,9 +118,9 @@ impl AppOp {
                     None,
                 );
                 download_to_cache(
+                    login_data.session_client.clone(),
                     self.thread_pool.clone(),
                     self.user_info_cache.clone(),
-                    login_data.session_client.homeserver().clone(),
                     login_data.access_token.clone(),
                     login_data.uid,
                     data,
diff --git a/fractal-gtk/src/backend/directory.rs b/fractal-gtk/src/backend/directory.rs
index ffe659af..405bacbb 100644
--- a/fractal-gtk/src/backend/directory.rs
+++ b/fractal-gtk/src/backend/directory.rs
@@ -1,19 +1,20 @@
+use fractal_api::identifiers::{Error as IdentifierError, ServerName};
 use fractal_api::reqwest::Error as ReqwestError;
-use fractal_api::url::{Host, ParseError as UrlError, Url};
-use std::convert::TryInto;
+use fractal_api::url::{ParseError as UrlError, Url};
+use fractal_api::Client as MatrixClient;
+use fractal_api::Error as MatrixError;
+use std::convert::{TryFrom, TryInto};
 
 use crate::globals;
 
-use crate::backend::HTTP_CLIENT;
+use crate::backend::{MediaError, HTTP_CLIENT};
 use crate::util::cache_dir_path;
 
 use crate::model::room::Room;
-use fractal_api::r0::directory::post_public_rooms::request as post_public_rooms;
-use fractal_api::r0::directory::post_public_rooms::Body as PublicRoomsBody;
-use fractal_api::r0::directory::post_public_rooms::Filter as PublicRoomsFilter;
-use fractal_api::r0::directory::post_public_rooms::Parameters as PublicRoomsParameters;
-use fractal_api::r0::directory::post_public_rooms::Response as PublicRoomsResponse;
-use fractal_api::r0::directory::post_public_rooms::ThirdPartyNetworks;
+use fractal_api::api::r0::directory::get_public_rooms_filtered::Request as PublicRoomsFilteredRequest;
+use fractal_api::assign;
+use fractal_api::directory::Filter as PublicRoomsFilter;
+use fractal_api::directory::RoomNetwork;
 use fractal_api::r0::thirdparty::get_supported_protocols::request as get_supported_protocols;
 use fractal_api::r0::thirdparty::get_supported_protocols::Parameters as SupportedProtocolsParameters;
 use fractal_api::r0::thirdparty::get_supported_protocols::ProtocolInstance;
@@ -58,14 +59,15 @@ pub fn protocols(
 
 #[derive(Debug)]
 pub enum DirectorySearchError {
-    InvalidHomeserverUrl(UrlError),
-    Reqwest(ReqwestError),
+    Matrix(MatrixError),
+    MalformedServerName(IdentifierError),
     ParseUrl(UrlError),
+    Download(MediaError),
 }
 
-impl From<ReqwestError> for DirectorySearchError {
-    fn from(err: ReqwestError) -> Self {
-        Self::Reqwest(err)
+impl From<MatrixError> for DirectorySearchError {
+    fn from(err: MatrixError) -> Self {
+        Self::Matrix(err)
     }
 }
 
@@ -75,6 +77,12 @@ impl From<UrlError> for DirectorySearchError {
     }
 }
 
+impl From<MediaError> for DirectorySearchError {
+    fn from(err: MediaError) -> Self {
+        Self::Download(err)
+    }
+}
+
 impl HandleError for DirectorySearchError {
     fn handle_error(&self) {
         let error = i18n("Error searching for rooms");
@@ -83,69 +91,50 @@ impl HandleError for DirectorySearchError {
     }
 }
 
-pub fn room_search(
-    base: Url,
-    access_token: AccessToken,
-    homeserver: String,
-    generic_search_term: String,
-    third_party: String,
-    rooms_since: Option<String>,
+pub async fn room_search(
+    session_client: MatrixClient,
+    server: Option<&str>,
+    search_term: Option<&str>,
+    room_network: RoomNetwork<'_>,
+    rooms_since: Option<&str>,
 ) -> Result<(Vec<Room>, Option<String>), DirectorySearchError> {
-    let homeserver = Some(homeserver).filter(|hs| !hs.is_empty());
-    let generic_search_term = Some(generic_search_term).filter(|q| !q.is_empty());
-    let third_party = Some(third_party).filter(|tp| !tp.is_empty());
-
-    let server = homeserver
-        .map(|hs| {
-            Url::parse(&hs)
-                .ok()
-                .as_ref()
-                .and_then(Url::host)
-                .as_ref()
-                .map(Host::to_owned)
-                .map(Ok)
-                .unwrap_or_else(|| Host::parse(&hs))
-                // Remove the url::Host enum, we only need the domain string
-                .map(|host| host.to_string())
-                .map(Some)
-        })
-        .unwrap_or(Ok(None))
-        .map_err(DirectorySearchError::InvalidHomeserverUrl)?;
-
-    let params = PublicRoomsParameters {
-        access_token,
-        server,
-    };
+    let server = server
+        .map(<&ServerName>::try_from)
+        .transpose()
+        .map_err(DirectorySearchError::MalformedServerName)?;
 
-    let body = PublicRoomsBody {
-        limit: Some(globals::ROOM_DIRECTORY_LIMIT),
-        filter: Some(PublicRoomsFilter {
-            generic_search_term,
-        }),
+    let request = assign!(PublicRoomsFilteredRequest::new(), {
+        server,
+        limit: Some(globals::ROOM_DIRECTORY_LIMIT.into()),
         since: rooms_since,
-        third_party_networks: third_party
-            .map(ThirdPartyNetworks::Only)
-            .unwrap_or_default(),
-    };
+        filter: assign!(PublicRoomsFilter::new(), {
+            generic_search_term: search_term,
+        }),
+        room_network,
+    });
 
-    let request = post_public_rooms(base.clone(), &params, &body)?;
-    let response: PublicRoomsResponse = HTTP_CLIENT.get_client().execute(request)?.json()?;
+    let response = session_client.public_rooms_filtered(request).await?;
 
     let since = response.next_batch;
     let rooms = response
         .chunk
         .into_iter()
         .map(TryInto::try_into)
-        .inspect(|r: &Result<Room, _>| {
-            if let Ok(room) = r {
-                if let Some(avatar) = room.avatar.clone() {
-                    if let Ok(dest) = cache_dir_path(None, &room.id.to_string()) {
-                        let _ = dw_media(base.clone(), &avatar, ContentType::Download, Some(dest));
-                    }
-                }
+        .collect::<Result<Vec<Room>, UrlError>>()?;
+
+    for room in &rooms {
+        if let Some(avatar) = room.avatar.as_ref() {
+            if let Ok(dest) = cache_dir_path(None, room.id.as_str()) {
+                let _ = dw_media(
+                    session_client.clone(),
+                    avatar,
+                    ContentType::Download,
+                    Some(dest),
+                )
+                .await;
             }
-        })
-        .collect::<Result<_, UrlError>>()?;
+        }
+    }
 
     Ok((rooms, since))
 }
diff --git a/fractal-gtk/src/backend/media.rs b/fractal-gtk/src/backend/media.rs
index 717f54ae..b3f464ee 100644
--- a/fractal-gtk/src/backend/media.rs
+++ b/fractal-gtk/src/backend/media.rs
@@ -3,6 +3,7 @@ use crate::globals;
 use fractal_api::identifiers::{Error as IdError, EventId, RoomId};
 use fractal_api::reqwest::Error as ReqwestError;
 use fractal_api::url::Url;
+use fractal_api::Client as MatrixClient;
 use std::path::PathBuf;
 use std::sync::mpsc::Sender;
 
@@ -22,18 +23,18 @@ use super::{dw_media, get_prev_batch_from, ContentType, ThreadPool};
 pub type MediaResult = Result<PathBuf, MediaError>;
 pub type MediaList = (Vec<Message>, String);
 
-pub fn get_thumb_async(thread_pool: ThreadPool, baseu: Url, media: Url, tx: Sender<MediaResult>) {
-    thread_pool.run(move || {
-        let fname = dw_media(baseu, &media, ContentType::default_thumbnail(), None);
-        tx.send(fname).expect_log("Connection closed");
-    });
+pub async fn get_thumb(session_client: MatrixClient, media: &Url) -> MediaResult {
+    dw_media(
+        session_client,
+        media,
+        ContentType::default_thumbnail(),
+        None,
+    )
+    .await
 }
 
-pub fn get_media_async(thread_pool: ThreadPool, baseu: Url, media: Url, tx: Sender<MediaResult>) {
-    thread_pool.run(move || {
-        let fname = dw_media(baseu, &media, ContentType::Download, None);
-        tx.send(fname).expect_log("Connection closed");
-    });
+pub async fn get_media(session_client: MatrixClient, media: &Url) -> MediaResult {
+    dw_media(session_client, media, ContentType::Download, None).await
 }
 
 pub fn get_media_list_async(
diff --git a/fractal-gtk/src/backend/mod.rs b/fractal-gtk/src/backend/mod.rs
index d10b68e0..2eeb4bf4 100644
--- a/fractal-gtk/src/backend/mod.rs
+++ b/fractal-gtk/src/backend/mod.rs
@@ -1,11 +1,12 @@
-use fractal_api::identifiers::{EventId, RoomId};
+use fractal_api::identifiers::{EventId, RoomId, ServerName};
 use fractal_api::reqwest::Error as ReqwestError;
 use fractal_api::url::Url;
+use fractal_api::{Client as MatrixClient, Error as MatrixError};
 use lazy_static::lazy_static;
 use log::error;
 use regex::Regex;
+use std::convert::TryFrom;
 use std::fmt::Debug;
-use std::fs::write;
 use std::io::Error as IoError;
 use std::path::PathBuf;
 use std::sync::{Arc, Condvar, Mutex};
@@ -13,14 +14,13 @@ use std::thread;
 
 use crate::client::ClientBlocking;
 use crate::util::cache_dir_path;
+use fractal_api::api::r0::media::get_content::Request as GetContentRequest;
+use fractal_api::api::r0::media::get_content_thumbnail::Method;
+use fractal_api::api::r0::media::get_content_thumbnail::Request as GetContentThumbnailRequest;
+use fractal_api::assign;
 use fractal_api::r0::context::get_context::request as get_context;
 use fractal_api::r0::context::get_context::Parameters as GetContextParameters;
 use fractal_api::r0::context::get_context::Response as GetContextResponse;
-use fractal_api::r0::media::get_content::request as get_content;
-use fractal_api::r0::media::get_content::Parameters as GetContentParameters;
-use fractal_api::r0::media::get_content_thumbnail::request as get_content_thumbnail;
-use fractal_api::r0::media::get_content_thumbnail::Method;
-use fractal_api::r0::media::get_content_thumbnail::Parameters as GetContentThumbnailParameters;
 use fractal_api::r0::AccessToken;
 
 pub mod directory;
@@ -79,7 +79,7 @@ impl ThreadPool {
 
 pub enum ContentType {
     Download,
-    Thumbnail(u64, u64),
+    Thumbnail(u32, u32),
 }
 
 impl ContentType {
@@ -118,12 +118,12 @@ pub fn get_prev_batch_from(
 pub enum MediaError {
     MalformedMxcUrl,
     Io(IoError),
-    Reqwest(ReqwestError),
+    Matrix(MatrixError),
 }
 
-impl From<ReqwestError> for MediaError {
-    fn from(err: ReqwestError) -> Self {
-        Self::Reqwest(err)
+impl From<MatrixError> for MediaError {
+    fn from(err: MatrixError) -> Self {
+        Self::Matrix(err)
     }
 }
 
@@ -135,8 +135,8 @@ impl From<IoError> for MediaError {
 
 impl HandleError for MediaError {}
 
-pub fn dw_media(
-    base: Url,
+pub async fn dw_media(
+    session_client: MatrixClient,
     mxc: &Url,
     media_type: ContentType,
     dest: Option<PathBuf>,
@@ -145,7 +145,16 @@ pub fn dw_media(
         return Err(MediaError::MalformedMxcUrl);
     }
 
-    let server = mxc.host().ok_or(MediaError::MalformedMxcUrl)?.to_owned();
+    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()
@@ -153,19 +162,6 @@ pub fn dw_media(
         .filter(|s| !s.is_empty())
         .ok_or(MediaError::MalformedMxcUrl)?;
 
-    let request = if let ContentType::Thumbnail(width, height) = media_type {
-        let params = GetContentThumbnailParameters {
-            width,
-            height,
-            method: Some(Method::Crop),
-            allow_remote: true,
-        };
-        get_content_thumbnail(base, &params, &server, &media_id)
-    } else {
-        let params = GetContentParameters::default();
-        get_content(base, &params, &server, &media_id)
-    }?;
-
     let default_fname = || {
         let dir = if media_type.is_thumbnail() {
             "thumbs"
@@ -185,14 +181,28 @@ pub fn dw_media(
         .map_or(false, |dur| dur.as_secs() < 60);
 
     if fname.is_file() && (dest.is_none() || is_fname_recent) {
-        Ok(fname)
+        return Ok(fname);
+    }
+
+    let media = if let ContentType::Thumbnail(width, height) = media_type {
+        let request = assign!(GetContentThumbnailRequest::new(
+                &media_id,
+                &server_name,
+                width.into(),
+                height.into(),
+            ), {
+            method: Some(Method::Crop),
+        });
+
+        session_client.send(request).await?.file
     } else {
-        let media = HTTP_CLIENT.get_client().execute(request)?.bytes()?;
+        let request = GetContentRequest::new(&media_id, &server_name);
+        session_client.send(request).await?.file
+    };
 
-        write(&fname, media)?;
+    tokio::fs::write(&fname, media).await?;
 
-        Ok(fname)
-    }
+    Ok(fname)
 }
 
 pub trait HandleError: Debug {
diff --git a/fractal-gtk/src/backend/room.rs b/fractal-gtk/src/backend/room.rs
index 369333d6..0afc0c1d 100644
--- a/fractal-gtk/src/backend/room.rs
+++ b/fractal-gtk/src/backend/room.rs
@@ -19,7 +19,8 @@ use std::time::Duration;
 use crate::globals;
 
 use crate::actions::AppState;
-use crate::backend::HTTP_CLIENT;
+use crate::app::RUNTIME;
+use crate::backend::{MediaError, HTTP_CLIENT};
 use crate::util::cache_dir_path;
 
 use crate::model::{
@@ -122,30 +123,46 @@ pub fn get_room_detail(
 }
 
 #[derive(Debug)]
-pub struct RoomAvatarError(ReqwestError);
+pub enum RoomAvatarError {
+    Reqwest(ReqwestError),
+    Download(MediaError),
+}
 
 impl From<ReqwestError> for RoomAvatarError {
     fn from(err: ReqwestError) -> Self {
-        Self(err)
+        Self::Reqwest(err)
+    }
+}
+
+impl From<MediaError> for RoomAvatarError {
+    fn from(err: MediaError) -> Self {
+        Self::Download(err)
     }
 }
 
 impl HandleError for RoomAvatarError {}
 
 pub fn get_room_avatar(
-    base: Url,
+    session_client: MatrixClient,
     access_token: AccessToken,
     room_id: RoomId,
 ) -> Result<(RoomId, Option<Url>), RoomAvatarError> {
+    let base = session_client.homeserver().clone();
+
     let params = GetStateEventsForKeyParameters { access_token };
 
-    let request = get_state_events_for_key(base.clone(), &params, &room_id, "m.room.avatar")?;
+    let request = get_state_events_for_key(base, &params, &room_id, "m.room.avatar")?;
     let response: JsonValue = HTTP_CLIENT.get_client().execute(request)?.json()?;
 
     let avatar = response["url"].as_str().and_then(|s| Url::parse(s).ok());
     let dest = cache_dir_path(None, &room_id.to_string()).ok();
     if let Some(ref avatar) = avatar {
-        let _ = dw_media(base, avatar, ContentType::default_thumbnail(), dest);
+        RUNTIME.handle().block_on(dw_media(
+            session_client,
+            avatar,
+            ContentType::default_thumbnail(),
+            dest,
+        ))?;
     }
 
     Ok((room_id, avatar))
diff --git a/fractal-gtk/src/backend/sync.rs b/fractal-gtk/src/backend/sync.rs
index e7b0d444..091d2f39 100644
--- a/fractal-gtk/src/backend/sync.rs
+++ b/fractal-gtk/src/backend/sync.rs
@@ -20,7 +20,7 @@ use fractal_api::r0::AccessToken;
 
 use fractal_api::identifiers::{EventId, RoomId, UserId};
 use fractal_api::reqwest::blocking::{Client, Response};
-use fractal_api::url::Url;
+use fractal_api::Client as MatrixClient;
 use log::error;
 use serde::de::DeserializeOwned;
 use serde_json::value::from_value;
@@ -117,7 +117,7 @@ pub enum SyncRet {
 }
 
 pub fn sync(
-    base: Url,
+    session_client: MatrixClient,
     access_token: AccessToken,
     user_id: UserId,
     join_to_room: Option<RoomId>,
@@ -125,6 +125,8 @@ pub fn sync(
     initial: bool,
     number_tries: u64,
 ) -> Result<SyncRet, SyncError> {
+    let base = session_client.homeserver().clone();
+
     let (timeout, filter) = if !initial {
         (time::Duration::from_secs(30), Default::default())
     } else {
@@ -190,13 +192,14 @@ pub fn sync(
     match query {
         Ok(response) => {
             if since.is_none() {
-                let rooms = Room::from_sync_response(&response, user_id, access_token, base)
-                    .map(|rooms| {
-                        let def = join_to_room
-                            .and_then(|jtr| rooms.iter().find(|x| x.id == jtr).cloned());
-                        (rooms, def)
-                    })
-                    .map_err(Into::into);
+                let rooms =
+                    Room::from_sync_response(session_client, &response, user_id, access_token)
+                        .map(|rooms| {
+                            let def = join_to_room
+                                .and_then(|jtr| rooms.iter().find(|x| x.id == jtr).cloned());
+                            (rooms, def)
+                        })
+                        .map_err(Into::into);
 
                 let next_batch = response.next_batch;
 
@@ -205,9 +208,13 @@ pub fn sync(
                 let join = &response.rooms.join;
 
                 // New rooms
-                let update_rooms =
-                    Room::from_sync_response(&response, user_id.clone(), access_token, base)
-                        .map_err(Into::into);
+                let update_rooms = Room::from_sync_response(
+                    session_client,
+                    &response,
+                    user_id.clone(),
+                    access_token,
+                )
+                .map_err(Into::into);
 
                 // Message events
                 let room_messages = join
diff --git a/fractal-gtk/src/backend/user.rs b/fractal-gtk/src/backend/user.rs
index f2690f27..ce2979f9 100644
--- a/fractal-gtk/src/backend/user.rs
+++ b/fractal-gtk/src/backend/user.rs
@@ -1,11 +1,13 @@
 use fractal_api::identifiers::UserId;
 use fractal_api::reqwest::Error as ReqwestError;
 use fractal_api::url::{ParseError as UrlError, Url};
+use fractal_api::Client as MatrixClient;
 use std::fs;
 use std::io::Error as IoError;
 
 use super::MediaError;
 use crate::actions::global::activate_action;
+use crate::app::RUNTIME;
 use crate::appop::UserInfoCache;
 use crate::backend::ThreadPool;
 use crate::backend::HTTP_CLIENT;
@@ -564,8 +566,8 @@ pub fn set_user_avatar(
 
 pub fn get_user_info_async(
     thread_pool: ThreadPool,
+    session_client: MatrixClient,
     user_info_cache: UserInfoCache,
-    baseu: Url,
     access_token: AccessToken,
     uid: UserId,
     tx: Sender<UserInfo>,
@@ -578,7 +580,7 @@ pub fn get_user_info_async(
     }
 
     thread_pool.run(move || {
-        let info = get_user_avatar(baseu, access_token, &uid);
+        let info = get_user_avatar(session_client, access_token, &uid);
 
         if let Ok(ref i0) = info {
             user_info_cache.lock().unwrap().insert(uid, i0.clone());
@@ -659,10 +661,11 @@ impl From<UrlError> for GetUserAvatarError {
 impl HandleError for GetUserAvatarError {}
 
 pub fn get_user_avatar(
-    base: Url,
+    session_client: MatrixClient,
     access_token: AccessToken,
     user_id: &UserId,
 ) -> Result<(String, PathBuf), GetUserAvatarError> {
+    let base = session_client.homeserver().clone();
     let params = GetProfileParameters { access_token };
     let request = get_profile(base.clone(), &params, user_id)?;
     let response: GetProfileResponse = HTTP_CLIENT.get_client().execute(request)?.json()?;
@@ -678,7 +681,12 @@ pub fn get_user_avatar(
         .transpose()?
         .map(|url| {
             let dest = cache_dir_path(None, &user_id.to_string())?;
-            dw_media(base, &url, ContentType::default_thumbnail(), Some(dest))
+            RUNTIME.handle().block_on(dw_media(
+                session_client,
+                &url,
+                ContentType::default_thumbnail(),
+                Some(dest),
+            ))
         })
         .unwrap_or_else(|| Ok(Default::default()))
         .map_err(GetUserAvatarError::Download)?;
diff --git a/fractal-gtk/src/cache/mod.rs b/fractal-gtk/src/cache/mod.rs
index c16500ca..491c3de9 100644
--- a/fractal-gtk/src/cache/mod.rs
+++ b/fractal-gtk/src/cache/mod.rs
@@ -5,6 +5,7 @@ use crate::util::cache_dir_path;
 use crate::util::ResultExpectLog;
 use fractal_api::r0::AccessToken;
 use fractal_api::url::Url;
+use fractal_api::Client as MatrixClient;
 use glib::source::Continue;
 use gtk::LabelExt;
 use serde::{Deserialize, Serialize};
@@ -156,9 +157,9 @@ pub fn remove_from_cache(user_info_cache: UserInfoCache, user_id: &UserId) {
 
 /// this downloads a avatar and stores it in the cache folder
 pub fn download_to_cache(
+    session_client: MatrixClient,
     thread_pool: ThreadPool,
     user_info_cache: UserInfoCache,
-    server_url: Url,
     access_token: AccessToken,
     uid: UserId,
     data: Rc<RefCell<AvatarData>>,
@@ -166,8 +167,8 @@ pub fn download_to_cache(
     let (tx, rx) = channel::<(String, PathBuf)>();
     user::get_user_info_async(
         thread_pool,
+        session_client,
         user_info_cache,
-        server_url,
         access_token,
         uid,
         tx,
diff --git a/fractal-gtk/src/globals.rs b/fractal-gtk/src/globals.rs
index 6efcc99e..4a26bf50 100644
--- a/fractal-gtk/src/globals.rs
+++ b/fractal-gtk/src/globals.rs
@@ -6,7 +6,7 @@ use std::{path::PathBuf, time::Duration};
 
 pub const TIMEOUT: Duration = Duration::from_secs(80);
 pub const PAGE_LIMIT: i32 = 40;
-pub const ROOM_DIRECTORY_LIMIT: i32 = 20;
+pub const ROOM_DIRECTORY_LIMIT: u32 = 20;
 pub const DEVICE_NAME: &str = "Fractal";
 
 pub const CACHE_SIZE: usize = 40;
diff --git a/fractal-gtk/src/model/room.rs b/fractal-gtk/src/model/room.rs
index 807fb8ab..3521114c 100644
--- a/fractal-gtk/src/model/room.rs
+++ b/fractal-gtk/src/model/room.rs
@@ -5,11 +5,12 @@ use crate::model::member::Member;
 use crate::model::member::MemberList;
 use crate::model::message::Message;
 use either::Either;
-use fractal_api::identifiers::{Error as IdError, EventId, RoomId, UserId};
-use fractal_api::r0::directory::post_public_rooms::Chunk as PublicRoomsChunk;
+use fractal_api::directory::PublicRoomsChunk;
+use fractal_api::identifiers::{Error as IdError, EventId, RoomAliasId, RoomId, UserId};
 use fractal_api::r0::sync::sync_events::Response as SyncResponse;
 use fractal_api::r0::AccessToken;
 use fractal_api::url::{ParseError as UrlError, Url};
+use fractal_api::Client as MatrixClient;
 use log::{debug, info};
 use serde::{Deserialize, Serialize};
 use std::collections::{HashMap, HashSet};
@@ -88,10 +89,10 @@ pub struct Room {
     pub avatar: Option<Url>,
     pub name: Option<String>,
     pub topic: Option<String>,
-    pub alias: Option<String>,
+    pub alias: Option<RoomAliasId>,
     pub guest_can_join: bool,
     pub world_readable: bool,
-    pub n_members: i32,
+    pub n_members: u64,
     pub members: MemberList,
     pub notifications: i32,
     pub highlight: i32,
@@ -134,10 +135,10 @@ impl Room {
     }
 
     pub fn from_sync_response(
+        session_client: MatrixClient,
         response: &SyncResponse,
         user_id: UserId,
         access_token: AccessToken,
-        baseu: Url,
     ) -> Result<Vec<Self>, IdError> {
         // getting the list of direct rooms
         let direct: HashSet<RoomId> = parse_m_direct(&response.account_data.events)
@@ -165,9 +166,9 @@ impl Room {
 
             let mut r = Self {
                 name: calculate_room_name(stevents, &user_id),
-                avatar: evc(stevents, "m.room.avatar", "url")
-                    .and_then(|ref url| Url::parse(url).ok()),
-                alias: evc(stevents, "m.room.canonical_alias", "alias"),
+                avatar: evc(stevents, "m.room.avatar", "url").and_then(|url| Url::parse(&url).ok()),
+                alias: evc(stevents, "m.room.canonical_alias", "alias")
+                    .and_then(|alias| RoomAliasId::try_from(alias).ok()),
                 topic: evc(stevents, "m.room.topic", "topic"),
                 direct: direct.contains(&k),
                 notifications: room.unread_notifications.notification_count,
@@ -211,7 +212,7 @@ impl Room {
                 if leave_id != user_id {
                     let kick_reason = &last_event["content"]["reason"];
                     if let Ok((kicker_alias, kicker_avatar)) =
-                        get_user_avatar(baseu.clone(), access_token.clone(), &leave_id)
+                        get_user_avatar(session_client.clone(), access_token.clone(), &leave_id)
                     {
                         let kicker = Member {
                             alias: Some(kicker_alias),
@@ -250,7 +251,7 @@ impl Room {
                     })
                     .map_or(Ok(None), |ev| {
                         Ok(get_user_avatar(
-                            baseu.clone(),
+                            session_client.clone(),
                             access_token.clone(),
                             &UserId::try_from(ev["sender"].as_str().unwrap_or_default())?,
                         )
@@ -266,8 +267,9 @@ impl Room {
                     Ok(Some(Self {
                         name: calculate_room_name(stevents, &user_id),
                         avatar: evc(stevents, "m.room.avatar", "url")
-                            .and_then(|ref url| Url::parse(url).ok()),
-                        alias: evc(stevents, "m.room.canonical_alias", "alias"),
+                            .and_then(|url| Url::parse(&url).ok()),
+                        alias: evc(stevents, "m.room.canonical_alias", "alias")
+                            .and_then(|alias| RoomAliasId::try_from(alias).ok()),
                         topic: evc(stevents, "m.room.topic", "topic"),
                         direct: direct.contains(&k),
                         ..Self::new(k.clone(), RoomMembership::Invited(inv_sender))
@@ -333,7 +335,7 @@ impl TryFrom<PublicRoomsChunk> for Room {
 
     fn try_from(input: PublicRoomsChunk) -> Result<Self, Self::Error> {
         Ok(Self {
-            alias: input.canonical_alias.as_ref().map(ToString::to_string),
+            alias: input.canonical_alias,
             name: input.name,
             avatar: input
                 .avatar_url
@@ -341,7 +343,7 @@ impl TryFrom<PublicRoomsChunk> for Room {
                 .map(|url| Url::parse(&url))
                 .transpose()?,
             topic: input.topic,
-            n_members: input.num_joined_members,
+            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)
diff --git a/fractal-gtk/src/widgets/image.rs b/fractal-gtk/src/widgets/image.rs
index b28289c0..cd87dec7 100644
--- a/fractal-gtk/src/widgets/image.rs
+++ b/fractal-gtk/src/widgets/image.rs
@@ -1,7 +1,9 @@
-use crate::backend::{media, ThreadPool};
+use crate::app::RUNTIME;
+use crate::backend::media;
 use crate::util::get_border_radius;
 use either::Either;
 use fractal_api::url::Url;
+use fractal_api::Client as MatrixClient;
 use gdk::prelude::GdkContextExt;
 use gdk_pixbuf::Pixbuf;
 use gdk_pixbuf::PixbufAnimation;
@@ -12,9 +14,6 @@ use gtk::prelude::*;
 use gtk::DrawingArea;
 use log::error;
 use std::path::{Path, PathBuf};
-use std::sync::mpsc::channel;
-use std::sync::mpsc::TryRecvError;
-use std::sync::mpsc::{Receiver, Sender};
 use std::sync::{Arc, Mutex};
 
 #[derive(Clone, Debug)]
@@ -99,9 +98,9 @@ impl Image {
         self
     }
 
-    pub fn build(self, thread_pool: ThreadPool) -> Image {
+    pub fn build(self, session_client: MatrixClient) -> Image {
         self.draw();
-        self.load_async(thread_pool);
+        self.load_async(session_client);
 
         self
     }
@@ -267,37 +266,33 @@ impl Image {
 
     /// If `path` starts with mxc this func download the img async, in other case the image is loaded
     /// in the `image` widget scaled to size
-    pub fn load_async(&self, thread_pool: ThreadPool) {
+    pub fn load_async(&self, session_client: MatrixClient) {
         match self.path.as_ref() {
             Either::Left(url) if url.scheme() == "mxc" => {
                 let mxc = url.clone();
                 // asyn load
-                let (tx, rx): (Sender<media::MediaResult>, Receiver<media::MediaResult>) =
-                    channel();
-                let command = if self.thumb {
-                    media::get_thumb_async
+                let response = if self.thumb {
+                    RUNTIME.spawn(async move { media::get_thumb(session_client, &mxc).await })
                 } else {
-                    media::get_media_async
+                    RUNTIME.spawn(async move { media::get_media(session_client, &mxc).await })
                 };
-                command(thread_pool, self.server_url.clone(), mxc, tx);
                 let local_path = self.local_path.clone();
                 let pix = self.pixbuf.clone();
                 let scaled = self.scaled.clone();
                 let da = self.widget.clone();
 
                 da.get_style_context().add_class("image-spinner");
-                glib::timeout_add_local(50, move || match rx.try_recv() {
-                    Err(TryRecvError::Empty) => Continue(true),
-                    Err(TryRecvError::Disconnected) => Continue(false),
-                    Ok(Ok(fname)) => {
-                        *local_path.lock().unwrap() = Some(fname.clone());
-                        load_pixbuf(pix.clone(), scaled.clone(), da.clone(), &fname);
-                        da.get_style_context().remove_class("image-spinner");
-                        Continue(false)
-                    }
-                    Ok(Err(err)) => {
-                        error!("Image path could not be found due to error: {:?}", err);
-                        Continue(false)
+                glib::MainContext::default().spawn_local(async move {
+                    match response.await {
+                        Err(_) => return,
+                        Ok(Ok(fname)) => {
+                            *local_path.lock().unwrap() = Some(fname.clone());
+                            load_pixbuf(pix.clone(), scaled.clone(), da.clone(), &fname);
+                            da.get_style_context().remove_class("image-spinner");
+                        }
+                        Ok(Err(err)) => {
+                            error!("Image path could not be found due to error: {:?}", err);
+                        }
                     }
                 });
             }
diff --git a/fractal-gtk/src/widgets/inline_player.rs b/fractal-gtk/src/widgets/inline_player.rs
index b10cead8..2aca3437 100644
--- a/fractal-gtk/src/widgets/inline_player.rs
+++ b/fractal-gtk/src/widgets/inline_player.rs
@@ -17,7 +17,7 @@
 //
 // SPDX-License-Identifier: GPL-3.0-or-later
 
-use crate::backend::{media, ThreadPool};
+use crate::backend::media;
 use glib::clone;
 
 use gst::prelude::*;
@@ -40,13 +40,10 @@ use std::ops::Deref;
 use std::path::PathBuf;
 use std::rc::Rc;
 
-use std::sync::mpsc::channel;
-use std::sync::mpsc::TryRecvError;
-use std::sync::mpsc::{Receiver, Sender};
-
 use fractal_api::url::Url;
+use fractal_api::Client as MatrixClient;
 
-use crate::app::App;
+use crate::app::{App, RUNTIME};
 use crate::util::i18n::i18n;
 
 pub trait PlayerExt {
@@ -54,11 +51,10 @@ pub trait PlayerExt {
     fn pause(&self);
     fn stop(&self);
     fn initialize_stream(
-        player: &Rc<Self>,
+        player: Rc<Self>,
+        session_client: MatrixClient,
         media_url: Url,
-        server_url: Url,
-        thread_pool: ThreadPool,
-        bx: &gtk::Box,
+        bx: gtk::Box,
         start_playing: bool,
     );
     fn get_controls_container(player: &Rc<Self>) -> Option<gtk::Box>;
@@ -501,61 +497,51 @@ impl<T: MediaPlayer + 'static> PlayerExt for T {
     }
 
     fn initialize_stream(
-        player: &Rc<Self>,
+        player: Rc<Self>,
+        session_client: MatrixClient,
         media_url: Url,
-        server_url: Url,
-        thread_pool: ThreadPool,
-        bx: &gtk::Box,
+        bx: gtk::Box,
         start_playing: bool,
     ) {
+        let response =
+            RUNTIME.spawn(async move { media::get_media(session_client, &media_url).await });
         bx.set_opacity(0.3);
-        let (tx, rx): (Sender<media::MediaResult>, Receiver<media::MediaResult>) = channel();
-        media::get_media_async(thread_pool, server_url, media_url, tx);
         let local_path = player.get_local_path_access();
-        glib::timeout_add_local(
-            50,
-            clone!(@strong player, @strong bx => move || {
-                match rx.try_recv() {
-                    Err(TryRecvError::Empty) => Continue(true),
-                    Err(TryRecvError::Disconnected) => {
-                        let msg = i18n("Could not retrieve file URI");
-                        /* FIXME: don't use APPOP! */
-                        APPOP!(show_error, (msg));
-                        Continue(true)
-                    },
-                    Ok(Ok(path)) => {
-                        match Url::from_file_path(&path) {
-                            Ok(uri) => {
-                                *local_path.borrow_mut() = Some(path);
-                                if !start_playing {
-                                    if let Some(controls) = player.get_controls() {
-                                        if let Ok(duration) = get_media_duration(&uri) {
-                                            controls.timer.on_duration_changed(Duration(duration))
-                                        }
-                                    }
-                                }
-                                player.get_player().set_uri(uri.as_str());
-                                if player.get_controls().is_some() {
-                                    ControlsConnection::init(&player);
-                                }
-                                bx.set_opacity(1.0);
-                                if start_playing {
-                                    player.play();
+        glib::MainContext::default().spawn_local(async move {
+            match response.await {
+                Err(_) => {
+                    let msg = i18n("Could not retrieve file URI");
+                    /* FIXME: don't use APPOP! */
+                    APPOP!(show_error, (msg));
+                }
+                Ok(Ok(path)) => match Url::from_file_path(&path) {
+                    Ok(uri) => {
+                        *local_path.borrow_mut() = Some(path);
+                        if !start_playing {
+                            if let Some(controls) = player.get_controls() {
+                                if let Ok(duration) = get_media_duration(&uri) {
+                                    controls.timer.on_duration_changed(Duration(duration))
                                 }
                             }
-                            Err(_) => {
-                                error!("Media path is not valid: {:?}", path);
-                            }
                         }
-                        Continue(false)
+                        player.get_player().set_uri(uri.as_str());
+                        if player.get_controls().is_some() {
+                            ControlsConnection::init(&player);
+                        }
+                        bx.set_opacity(1.0);
+                        if start_playing {
+                            player.play();
+                        }
                     }
-                    Ok(Err(err)) => {
-                        error!("Media path could not be found due to error: {:?}", err);
-                        Continue(false)
+                    Err(_) => {
+                        error!("Media path is not valid: {:?}", path);
                     }
+                },
+                Ok(Err(err)) => {
+                    error!("Media path could not be found due to error: {:?}", err);
                 }
-            }),
-        );
+            }
+        });
     }
 
     fn get_controls_container(player: &Rc<Self>) -> Option<gtk::Box> {
diff --git a/fractal-gtk/src/widgets/media_viewer.rs b/fractal-gtk/src/widgets/media_viewer.rs
index 3f848dfc..292a448a 100644
--- a/fractal-gtk/src/widgets/media_viewer.rs
+++ b/fractal-gtk/src/widgets/media_viewer.rs
@@ -12,6 +12,7 @@ use crate::util::i18n::i18n;
 use either::Either;
 use fractal_api::identifiers::UserId;
 use fractal_api::url::Url;
+use fractal_api::Client as MatrixClient;
 use gdk::*;
 use glib::signal;
 use glib::source::Continue;
@@ -147,7 +148,7 @@ struct Data {
 }
 
 impl Data {
-    pub fn enter_full_screen(&mut self, thread_pool: ThreadPool) {
+    pub fn enter_full_screen(&mut self, session_client: MatrixClient) {
         self.main_window.fullscreen();
         self.is_fullscreen = true;
 
@@ -194,12 +195,12 @@ impl Data {
                 media_container.show();
             }
             _ => {
-                self.redraw_media_in_viewport(thread_pool);
+                self.redraw_media_in_viewport(session_client);
             }
         }
     }
 
-    pub fn leave_full_screen(&mut self, thread_pool: ThreadPool) {
+    pub fn leave_full_screen(&mut self, session_client: MatrixClient) {
         self.main_window.unfullscreen();
         self.is_fullscreen = false;
 
@@ -252,7 +253,7 @@ impl Data {
                 }
             }
             _ => {
-                self.redraw_media_in_viewport(thread_pool);
+                self.redraw_media_in_viewport(session_client);
             }
         }
     }
@@ -281,7 +282,7 @@ impl Data {
         }
     }
 
-    pub fn previous_media(&mut self, thread_pool: ThreadPool) -> bool {
+    pub fn previous_media(&mut self, session_client: MatrixClient) -> bool {
         if self.no_more_media {
             return true;
         }
@@ -295,12 +296,12 @@ impl Data {
                 set_header_title(&self.builder, name);
             }
 
-            self.redraw_media_in_viewport(thread_pool);
+            self.redraw_media_in_viewport(session_client);
             true
         }
     }
 
-    pub fn next_media(&mut self, thread_pool: ThreadPool) {
+    pub fn next_media(&mut self, session_client: MatrixClient) {
         if self.current_media_index >= self.media_list.len() - 1 {
             return;
         }
@@ -310,10 +311,10 @@ impl Data {
             set_header_title(&self.builder, name);
         }
 
-        self.redraw_media_in_viewport(thread_pool);
+        self.redraw_media_in_viewport(session_client);
     }
 
-    pub fn redraw_media_in_viewport(&mut self, thread_pool: ThreadPool) {
+    pub fn redraw_media_in_viewport(&mut self, session_client: MatrixClient) {
         let msg = &self.media_list[self.current_media_index];
         let url = unwrap_or_unit_return!(msg.url.clone());
         let media_container = self
@@ -330,13 +331,13 @@ impl Data {
                 let image = image::Image::new(self.server_url.clone(), Either::Left(url))
                     .shrink_to_fit(true)
                     .center(true)
-                    .build(thread_pool);
+                    .build(session_client);
                 media_container.add(&image.widget);
                 image.widget.show();
                 self.widget = Widget::Image(image);
             }
             "m.video" => {
-                let widget = self.create_video_widget(thread_pool, url);
+                let widget = self.create_video_widget(session_client, url);
                 media_container.add(&widget.outer_box);
                 self.widget = Widget::Video(widget);
                 media_container.show_all();
@@ -348,17 +349,16 @@ impl Data {
         self.set_nav_btn_visibility();
     }
 
-    fn create_video_widget(&self, thread_pool: ThreadPool, url: Url) -> VideoWidget {
+    fn create_video_widget(&self, session_client: MatrixClient, url: Url) -> VideoWidget {
         let with_controls = true;
         let player = VideoPlayerWidget::new(with_controls);
         let bx = gtk::Box::new(gtk::Orientation::Vertical, 0);
         let start_playing = true;
         PlayerExt::initialize_stream(
-            &player,
+            player.clone(),
+            session_client,
             url,
-            self.server_url.clone(),
-            thread_pool,
-            &bx,
+            bx.clone(),
             start_playing,
         );
 
@@ -642,7 +642,11 @@ impl MediaViewer {
         }
     }
 
-    pub fn create(&mut self, thread_pool: ThreadPool) -> Option<(gtk::Box, gtk::Box)> {
+    pub fn create(
+        &mut self,
+        session_client: MatrixClient,
+        thread_pool: ThreadPool,
+    ) -> Option<(gtk::Box, gtk::Box)> {
         let body = self
             .builder
             .get_object::<gtk::Box>("media_viewer_box")
@@ -651,14 +655,14 @@ impl MediaViewer {
             .builder
             .get_object::<gtk::Box>("media_viewer_headerbar_box")
             .expect("Can't find media_viewer_headerbar in ui file.");
-        self.connect_media_viewer_headerbar(thread_pool.clone());
-        self.connect_media_viewer_box(thread_pool);
+        self.connect_media_viewer_headerbar(session_client.clone());
+        self.connect_media_viewer_box(session_client, thread_pool);
         self.connect_stop_video_when_leaving();
 
         Some((body, header))
     }
 
-    pub fn display_media_viewer(&mut self, thread_pool: ThreadPool, media_msg: Message) {
+    pub fn display_media_viewer(&mut self, session_client: MatrixClient, media_msg: Message) {
         let url = unwrap_or_unit_return!(media_msg.url.clone());
 
         let previous_media_revealer = self
@@ -686,7 +690,7 @@ impl MediaViewer {
                     image::Image::new(self.data.borrow().server_url.clone(), Either::Left(url))
                         .shrink_to_fit(true)
                         .center(true)
-                        .build(thread_pool);
+                        .build(session_client);
 
                 media_container.add(&image.widget);
                 media_container.show_all();
@@ -694,7 +698,7 @@ impl MediaViewer {
                 self.data.borrow_mut().widget = Widget::Image(image);
             }
             "m.video" => {
-                let video_widget = self.data.borrow().create_video_widget(thread_pool, url);
+                let video_widget = self.data.borrow().create_video_widget(session_client, url);
                 media_container.add(&video_widget.outer_box);
                 media_container.show_all();
 
@@ -708,7 +712,7 @@ impl MediaViewer {
     }
 
     /* connect media viewer headerbar */
-    pub fn connect_media_viewer_headerbar(&self, thread_pool: ThreadPool) {
+    pub fn connect_media_viewer_headerbar(&self, session_client: MatrixClient) {
         let own = &self.data;
         let full_screen_button = self
             .builder
@@ -718,15 +722,19 @@ impl MediaViewer {
             let main_window = own.borrow().main_window.clone();
             if let Some(win) = main_window.get_window() {
                 if !win.get_state().contains(gdk::WindowState::FULLSCREEN) {
-                    own.borrow_mut().enter_full_screen(thread_pool.clone());
+                    own.borrow_mut().enter_full_screen(session_client.clone());
                 } else {
-                    own.borrow_mut().leave_full_screen(thread_pool.clone())
+                    own.borrow_mut().leave_full_screen(session_client.clone());
                 }
             }
         }));
     }
 
-    pub fn connect_media_viewer_box(&mut self, thread_pool: ThreadPool) {
+    pub fn connect_media_viewer_box(
+        &mut self,
+        session_client: MatrixClient,
+        thread_pool: ThreadPool,
+    ) {
         let full_screen_button = self
             .builder
             .get_object::<gtk::Button>("full_screen_button")
@@ -883,10 +891,11 @@ impl MediaViewer {
             .builder
             .get_object::<gtk::Button>("previous_media_button")
             .expect("Cant find previous_media_button in ui file.");
+        let s_client = session_client.clone();
         let t_pool = thread_pool.clone();
         previous_media_button.connect_clicked(clone!(@weak data => move |_| {
-            if !data.borrow_mut().previous_media(t_pool.clone()) {
-                load_more_media(t_pool.clone(), data, builder.clone());
+            if !data.borrow_mut().previous_media(s_client.clone()) {
+                load_more_media(s_client.clone(), t_pool.clone(), data, builder.clone());
             }
         }));
 
@@ -895,7 +904,7 @@ impl MediaViewer {
             .get_object::<gtk::Button>("next_media_button")
             .expect("Cant find next_media_button in ui file.");
         next_media_button.connect_clicked(clone!(@weak data => move |_| {
-            data.borrow_mut().next_media(thread_pool.clone());
+            data.borrow_mut().next_media(session_client.clone());
         }));
 
         let media_container = self
@@ -1014,7 +1023,12 @@ fn loading_state(ui: &gtk::Builder, val: bool) -> bool {
     val
 }
 
-fn load_more_media(thread_pool: ThreadPool, data: Rc<RefCell<Data>>, builder: gtk::Builder) {
+fn load_more_media(
+    session_client: MatrixClient,
+    thread_pool: ThreadPool,
+    data: Rc<RefCell<Data>>,
+    builder: gtk::Builder,
+) {
     data.borrow_mut().loading_more_media = loading_state(&builder, true);
 
     let msg = data.borrow().media_list[data.borrow().current_media_index].clone();
@@ -1067,10 +1081,10 @@ fn load_more_media(thread_pool: ThreadPool, data: Rc<RefCell<Data>>, builder: gt
                 data.borrow_mut().media_list = new_media_list;
                 data.borrow_mut().prev_batch = Some(prev_batch);
                 if img_msgs_count == 0 {
-                    load_more_media(thread_pool, data, builder.clone());
+                    load_more_media(session_client.clone(), thread_pool, data, builder.clone());
                 } else {
                     data.borrow_mut().current_media_index += img_msgs_count;
-                    data.borrow_mut().previous_media(thread_pool);
+                    data.borrow_mut().previous_media(session_client.clone());
                     data.borrow_mut().loading_more_media = loading_state(&ui, false);
                 }
 
diff --git a/fractal-gtk/src/widgets/member.rs b/fractal-gtk/src/widgets/member.rs
index 24efad61..1977ba60 100644
--- a/fractal-gtk/src/widgets/member.rs
+++ b/fractal-gtk/src/widgets/member.rs
@@ -58,9 +58,9 @@ impl<'a> MemberBox<'a> {
         );
         if let Some(login_data) = self.op.login_data.clone() {
             download_to_cache(
+                login_data.session_client.clone(),
                 self.op.thread_pool.clone(),
                 self.op.user_info_cache.clone(),
-                login_data.session_client.homeserver().clone(),
                 login_data.access_token,
                 self.member.uid.clone(),
                 data,
@@ -103,9 +103,9 @@ impl<'a> MemberBox<'a> {
         );
         if let Some(login_data) = self.op.login_data.clone() {
             download_to_cache(
+                login_data.session_client.clone(),
                 self.op.thread_pool.clone(),
                 self.op.user_info_cache.clone(),
-                login_data.session_client.homeserver().clone(),
                 login_data.access_token,
                 self.member.uid.clone(),
                 data,
diff --git a/fractal-gtk/src/widgets/message.rs b/fractal-gtk/src/widgets/message.rs
index d7b0548a..2dda58fb 100644
--- a/fractal-gtk/src/widgets/message.rs
+++ b/fractal-gtk/src/widgets/message.rs
@@ -7,6 +7,7 @@ use chrono::prelude::*;
 use either::Either;
 use fractal_api::r0::AccessToken;
 use fractal_api::url::Url;
+use fractal_api::Client as MatrixClient;
 use glib::clone;
 use gtk::{prelude::*, ButtonExt, ContainerExt, LabelExt, Overlay, WidgetExt};
 use std::cmp::max;
@@ -71,6 +72,7 @@ impl MessageBox {
     /* create the message row with or without a header */
     pub fn create(
         &mut self,
+        session_client: MatrixClient,
         thread_pool: ThreadPool,
         user_info_cache: UserInfoCache,
         msg: &Message,
@@ -84,7 +86,7 @@ impl MessageBox {
             RowType::Emote => {
                 self.row.set_margin_top(12);
                 self.header = false;
-                self.small_widget(thread_pool, msg)
+                self.small_widget(session_client, msg)
             }
             RowType::Video if is_temp => {
                 upload_attachment_msg
@@ -108,11 +110,11 @@ impl MessageBox {
             _ if has_header => {
                 self.row.set_margin_top(12);
                 self.header = true;
-                self.widget(thread_pool, user_info_cache, msg)
+                self.widget(session_client, thread_pool, user_info_cache, msg)
             }
             _ => {
                 self.header = false;
-                self.small_widget(thread_pool, msg)
+                self.small_widget(session_client, msg)
             }
         };
 
@@ -128,11 +130,19 @@ impl MessageBox {
 
     pub fn tmpwidget(
         mut self,
+        session_client: MatrixClient,
         thread_pool: ThreadPool,
         user_info_cache: UserInfoCache,
         msg: &Message,
     ) -> MessageBox {
-        self.create(thread_pool, user_info_cache, msg, true, true);
+        self.create(
+            session_client,
+            thread_pool,
+            user_info_cache,
+            msg,
+            true,
+            true,
+        );
         {
             let w = self.get_listbox_row();
             w.get_style_context().add_class("msg-tmp");
@@ -142,6 +152,7 @@ impl MessageBox {
 
     pub fn update_header(
         &mut self,
+        session_client: MatrixClient,
         thread_pool: ThreadPool,
         user_info_cache: UserInfoCache,
         msg: Message,
@@ -150,13 +161,13 @@ impl MessageBox {
         let w = if has_header && msg.mtype != RowType::Emote {
             self.row.set_margin_top(12);
             self.header = true;
-            self.widget(thread_pool, user_info_cache, &msg)
+            self.widget(session_client, thread_pool, user_info_cache, &msg)
         } else {
             if let RowType::Emote = msg.mtype {
                 self.row.set_margin_top(12);
             }
             self.header = false;
-            self.small_widget(thread_pool, &msg)
+            self.small_widget(session_client, &msg)
         };
         if let Some(eb) = self.eventbox.get_child() {
             self.eventbox.remove(&eb);
@@ -167,6 +178,7 @@ impl MessageBox {
 
     fn widget(
         &mut self,
+        session_client: MatrixClient,
         thread_pool: ThreadPool,
         user_info_cache: UserInfoCache,
         msg: &Message,
@@ -176,9 +188,9 @@ impl MessageBox {
         // | avatar | content |
         // +--------+---------+
         let msg_widget = gtk::Box::new(gtk::Orientation::Horizontal, 10);
-        let content = self.build_room_msg_content(thread_pool.clone(), msg, false);
+        let content = self.build_room_msg_content(session_client.clone(), msg, false);
         /* Todo: make build_room_msg_avatar() faster (currently ~1ms) */
-        let avatar = self.build_room_msg_avatar(thread_pool, user_info_cache, msg);
+        let avatar = self.build_room_msg_avatar(session_client, thread_pool, user_info_cache, msg);
 
         msg_widget.pack_start(&avatar, false, false, 0);
         msg_widget.pack_start(&content, true, true, 0);
@@ -186,13 +198,13 @@ impl MessageBox {
         msg_widget
     }
 
-    fn small_widget(&mut self, thread_pool: ThreadPool, msg: &Message) -> gtk::Box {
+    fn small_widget(&mut self, session_client: MatrixClient, msg: &Message) -> gtk::Box {
         // msg
         // +--------+---------+
         // |        | content |
         // +--------+---------+
         let msg_widget = gtk::Box::new(gtk::Orientation::Horizontal, 5);
-        let content = self.build_room_msg_content(thread_pool, msg, true);
+        let content = self.build_room_msg_content(session_client, msg, true);
         content.set_margin_start(50);
 
         msg_widget.pack_start(&content, true, true, 0);
@@ -202,7 +214,7 @@ impl MessageBox {
 
     fn build_room_msg_content(
         &mut self,
-        thread_pool: ThreadPool,
+        session_client: MatrixClient,
         msg: &Message,
         small: bool,
     ) -> gtk::Box {
@@ -221,13 +233,13 @@ impl MessageBox {
             content.pack_start(&info, false, false, 0);
         }
 
-        let body_bx = self.build_room_msg_body_bx(thread_pool, msg);
+        let body_bx = self.build_room_msg_body_bx(session_client, msg);
         content.pack_start(&body_bx, true, true, 0);
 
         content
     }
 
-    fn build_room_msg_body_bx(&mut self, thread_pool: ThreadPool, msg: &Message) -> gtk::Box {
+    fn build_room_msg_body_bx(&mut self, session_client: MatrixClient, msg: &Message) -> gtk::Box {
         // body_bx
         // +------+-----------+
         // | body | edit_mark |
@@ -235,11 +247,11 @@ impl MessageBox {
         let body_bx = gtk::Box::new(gtk::Orientation::Horizontal, 0);
 
         let body = match msg.mtype {
-            RowType::Sticker => self.build_room_msg_sticker(thread_pool, msg),
-            RowType::Image => self.build_room_msg_image(thread_pool, msg),
+            RowType::Sticker => self.build_room_msg_sticker(session_client, msg),
+            RowType::Image => self.build_room_msg_image(session_client, msg),
             RowType::Emote => self.build_room_msg_emote(msg),
-            RowType::Audio => self.build_room_audio_player(thread_pool, msg),
-            RowType::Video => self.build_room_video_player(thread_pool, msg),
+            RowType::Audio => self.build_room_audio_player(session_client, msg),
+            RowType::Video => self.build_room_video_player(session_client, msg),
             RowType::File => self.build_room_msg_file(msg),
             _ => self.build_room_msg_body(msg),
         };
@@ -262,6 +274,7 @@ impl MessageBox {
 
     fn build_room_msg_avatar(
         &self,
+        session_client: MatrixClient,
         thread_pool: ThreadPool,
         user_info_cache: UserInfoCache,
         msg: &Message,
@@ -285,9 +298,9 @@ impl MessageBox {
         }
 
         download_to_cache(
+            session_client,
             thread_pool,
             user_info_cache,
-            self.server_url.clone(),
             self.access_token.clone(),
             uid.clone(),
             data.clone(),
@@ -408,7 +421,7 @@ impl MessageBox {
         msg_part
     }
 
-    fn build_room_msg_image(&mut self, thread_pool: ThreadPool, msg: &Message) -> gtk::Box {
+    fn build_room_msg_image(&mut self, session_client: MatrixClient, msg: &Message) -> gtk::Box {
         let bx = gtk::Box::new(gtk::Orientation::Horizontal, 0);
 
         // If the thumbnail is not a valid URL we use the msg.url
@@ -423,7 +436,7 @@ impl MessageBox {
         if let Some(img_path) = img {
             let image = widgets::image::Image::new(self.server_url.clone(), img_path)
                 .size(Some(globals::MAX_IMAGE_SIZE))
-                .build(thread_pool);
+                .build(session_client);
 
             image.widget.get_style_context().add_class("image-widget");
 
@@ -436,12 +449,12 @@ impl MessageBox {
         bx
     }
 
-    fn build_room_msg_sticker(&self, thread_pool: ThreadPool, msg: &Message) -> gtk::Box {
+    fn build_room_msg_sticker(&self, session_client: MatrixClient, msg: &Message) -> gtk::Box {
         let bx = gtk::Box::new(gtk::Orientation::Horizontal, 0);
         if let Some(url) = msg.url.clone() {
             let image = widgets::image::Image::new(self.server_url.clone(), Either::Left(url))
                 .size(Some(globals::MAX_STICKER_SIZE))
-                .build(thread_pool);
+                .build(session_client);
             image.widget.set_tooltip_text(Some(&msg.body[..]));
 
             bx.add(&image.widget);
@@ -450,18 +463,17 @@ impl MessageBox {
         bx
     }
 
-    fn build_room_audio_player(&self, thread_pool: ThreadPool, msg: &Message) -> gtk::Box {
+    fn build_room_audio_player(&self, session_client: MatrixClient, msg: &Message) -> gtk::Box {
         let bx = gtk::Box::new(gtk::Orientation::Horizontal, 6);
 
         if let Some(url) = msg.url.clone() {
             let player = AudioPlayerWidget::new();
             let start_playing = false;
             PlayerExt::initialize_stream(
-                &player,
+                player.clone(),
+                session_client,
                 url,
-                self.server_url.clone(),
-                thread_pool,
-                &bx,
+                bx.clone(),
                 start_playing,
             );
 
@@ -496,7 +508,7 @@ impl MessageBox {
         outer_box
     }
 
-    fn build_room_video_player(&mut self, thread_pool: ThreadPool, msg: &Message) -> gtk::Box {
+    fn build_room_video_player(&mut self, session_client: MatrixClient, msg: &Message) -> gtk::Box {
         let bx = gtk::Box::new(gtk::Orientation::Vertical, 6);
 
         if let Some(url) = msg.url.clone() {
@@ -504,11 +516,10 @@ impl MessageBox {
             let player = VideoPlayerWidget::new(with_controls);
             let start_playing = false;
             PlayerExt::initialize_stream(
-                &player,
+                player.clone(),
+                session_client,
                 url,
-                self.server_url.clone(),
-                thread_pool,
-                &bx,
+                bx.clone(),
                 start_playing,
             );
 
diff --git a/fractal-gtk/src/widgets/room.rs b/fractal-gtk/src/widgets/room.rs
index c2577c62..bed88bc3 100644
--- a/fractal-gtk/src/widgets/room.rs
+++ b/fractal-gtk/src/widgets/room.rs
@@ -13,7 +13,7 @@ use crate::backend::HandleError;
 
 use crate::widgets;
 use crate::widgets::AvatarExt;
-use fractal_api::identifiers::RoomIdOrAliasId;
+use fractal_api::identifiers::{RoomAliasId, RoomIdOrAliasId};
 use gtk::WidgetExt;
 
 const AVATAR_SIZE: i32 = 60;
@@ -59,18 +59,18 @@ impl<'a> RoomBox<'a> {
 
             let details_box = gtk::Box::new(gtk::Orientation::Vertical, 6);
 
-            let name = match room.name {
-                ref n if n.is_none() || n.clone().unwrap().is_empty() => room.alias.clone(),
-                ref n => n.clone(),
-            };
+            let name = room
+                .name
+                .as_ref()
+                .filter(|n| !n.is_empty())
+                .map(String::as_str)
+                .or(room.alias.as_ref().map(RoomAliasId::as_str))
+                .unwrap_or_default();
 
             let name_label = gtk::Label::new(None);
             name_label.set_line_wrap(true);
             name_label.set_line_wrap_mode(pango::WrapMode::WordChar);
-            name_label.set_markup(&format!(
-                "<b>{}</b>",
-                markup_text(&name.unwrap_or_default())
-            ));
+            name_label.set_markup(&format!("<b>{}</b>", markup_text(name)));
             name_label.set_justify(gtk::Justification::Left);
             name_label.set_halign(gtk::Align::Start);
             name_label.set_valign(gtk::Align::Start);
@@ -94,7 +94,10 @@ impl<'a> RoomBox<'a> {
             alias_label.set_line_wrap_mode(pango::WrapMode::WordChar);
             alias_label.set_markup(&format!(
                 "<span alpha=\"60%\">{}</span>",
-                room.alias.clone().unwrap_or_default()
+                room.alias
+                    .as_ref()
+                    .map(RoomAliasId::as_str)
+                    .unwrap_or_default()
             ));
             alias_label.set_justify(gtk::Justification::Left);
             alias_label.set_halign(gtk::Align::Start);
diff --git a/fractal-gtk/src/widgets/room_history.rs b/fractal-gtk/src/widgets/room_history.rs
index 29b0f0e3..6126b01c 100644
--- a/fractal-gtk/src/widgets/room_history.rs
+++ b/fractal-gtk/src/widgets/room_history.rs
@@ -19,7 +19,7 @@ use crate::widgets;
 use crate::widgets::{PlayerExt, VideoPlayerWidget};
 use fractal_api::identifiers::RoomId;
 use fractal_api::r0::AccessToken;
-use fractal_api::url::Url;
+use fractal_api::Client as MatrixClient;
 use gio::ActionMapExt;
 use gio::SimpleActionGroup;
 use glib::clone;
@@ -272,7 +272,6 @@ pub struct RoomHistory {
     /* Contains a list of msg ids to keep track of the displayed messages */
     rows: Rc<RefCell<List>>,
     access_token: AccessToken,
-    server_url: Url,
     source_id: Rc<RefCell<Option<source::SourceId>>>,
     queue: Rc<RefCell<VecDeque<MessageContent>>>,
     edit_buffer: Rc<RefCell<VecDeque<MessageContent>>>,
@@ -301,7 +300,6 @@ impl RoomHistory {
         let mut rh = RoomHistory {
             rows: Rc::new(RefCell::new(List::new(scroll))),
             access_token: login_data.access_token,
-            server_url: login_data.session_client.homeserver().clone(),
             source_id: Rc::new(RefCell::new(None)),
             queue: Rc::new(RefCell::new(VecDeque::new())),
             edit_buffer: Rc::new(RefCell::new(VecDeque::new())),
@@ -315,6 +313,7 @@ impl RoomHistory {
 
     pub fn create(
         &mut self,
+        session_client: MatrixClient,
         thread_pool: ThreadPool,
         user_info_cache: UserInfoCache,
         mut messages: Vec<MessageContent>,
@@ -328,9 +327,14 @@ impl RoomHistory {
         }
         let bottom = messages.split_off(position);
         messages.reverse();
-        self.add_old_messages_in_batch(thread_pool.clone(), user_info_cache.clone(), messages);
+        self.add_old_messages_in_batch(
+            session_client.clone(),
+            thread_pool.clone(),
+            user_info_cache.clone(),
+            messages,
+        );
         /* Add the rest of the messages after the new message divider */
-        self.add_new_messages_in_batch(thread_pool, user_info_cache, bottom);
+        self.add_new_messages_in_batch(session_client, thread_pool, user_info_cache, bottom);
 
         let rows = &self.rows;
         let id = glib::timeout_add_local(
@@ -446,7 +450,12 @@ impl RoomHistory {
         }));
     }
 
-    fn run_queue(&mut self, thread_pool: ThreadPool, user_info_cache: UserInfoCache) -> Option<()> {
+    fn run_queue(
+        &mut self,
+        session_client: MatrixClient,
+        thread_pool: ThreadPool,
+        user_info_cache: UserInfoCache,
+    ) -> Option<()> {
         let queue = self.queue.clone();
         let edit_buffer = self.edit_buffer.clone();
         let rows = self.rows.clone();
@@ -460,7 +469,6 @@ impl RoomHistory {
         } else {
             /* Lazy load initial messages */
             let source_id = self.source_id.clone();
-            let server_url = self.server_url.clone();
             let access_token = self.access_token.clone();
             *self.source_id.borrow_mut() = Some(glib::idle_add_local(move || {
                 let mut data = queue.borrow_mut();
@@ -517,11 +525,11 @@ impl RoomHistory {
                         rows.borrow_mut().new_divider_index = Some(new_divider_index);
                     }
                     item.widget = Some(create_row(
+                        session_client.clone(),
                         thread_pool.clone(),
                         user_info_cache.clone(),
                         item.clone(),
                         has_header,
-                        server_url.clone(),
                         access_token.clone(),
                         &rows,
                     ));
@@ -555,12 +563,13 @@ impl RoomHistory {
     /* This adds new incomming messages at then end of the list */
     pub fn add_new_message(
         &mut self,
+        session_client: MatrixClient,
         thread_pool: ThreadPool,
         user_info_cache: UserInfoCache,
         mut item: MessageContent,
     ) -> Option<()> {
         if item.msg.replace.is_some() {
-            self.replace_message(thread_pool, user_info_cache, item);
+            self.replace_message(session_client, thread_pool, user_info_cache, item);
             return None;
         }
         let mut rows = self.rows.borrow_mut();
@@ -593,11 +602,11 @@ impl RoomHistory {
         }
 
         let b = create_row(
+            session_client,
             thread_pool,
             user_info_cache,
             item.clone(),
             has_header,
-            self.server_url.clone(),
             self.access_token.clone(),
             &self.rows,
         );
@@ -608,6 +617,7 @@ impl RoomHistory {
 
     pub fn replace_message(
         &mut self,
+        session_client: MatrixClient,
         thread_pool: ThreadPool,
         user_info_cache: UserInfoCache,
         mut item: MessageContent,
@@ -631,11 +641,11 @@ impl RoomHistory {
         let msg_widget = msg.widget.clone()?;
 
         item.widget = Some(create_row(
+            session_client,
             thread_pool,
             user_info_cache,
             item.clone(),
             msg_widget.header,
-            self.server_url.clone(),
             self.access_token.clone(),
             &self.rows,
         ));
@@ -645,6 +655,7 @@ impl RoomHistory {
 
     pub fn remove_message(
         &mut self,
+        session_client: MatrixClient,
         thread_pool: ThreadPool,
         user_info_cache: UserInfoCache,
         item: MessageContent,
@@ -691,7 +702,13 @@ impl RoomHistory {
                     msg_next_cloned.redactable && msg_next_cloned.sender == msg_sender
                 })
             {
-                msg_widget.update_header(thread_pool, user_info_cache, msg_next_cloned, true);
+                msg_widget.update_header(
+                    session_client,
+                    thread_pool,
+                    user_info_cache,
+                    msg_next_cloned,
+                    true,
+                );
             }
         }
         None
@@ -699,19 +716,26 @@ impl RoomHistory {
 
     pub fn add_new_messages_in_batch(
         &mut self,
+        session_client: MatrixClient,
         thread_pool: ThreadPool,
         user_info_cache: UserInfoCache,
         messages: Vec<MessageContent>,
     ) -> Option<()> {
         /* TODO: use lazy loading */
         for item in messages {
-            self.add_new_message(thread_pool.clone(), user_info_cache.clone(), item);
+            self.add_new_message(
+                session_client.clone(),
+                thread_pool.clone(),
+                user_info_cache.clone(),
+                item,
+            );
         }
         None
     }
 
     pub fn add_old_messages_in_batch(
         &mut self,
+        session_client: MatrixClient,
         thread_pool: ThreadPool,
         user_info_cache: UserInfoCache,
         messages: Vec<MessageContent>,
@@ -721,7 +745,7 @@ impl RoomHistory {
         self.queue
             .borrow_mut()
             .append(&mut VecDeque::from(messages));
-        self.run_queue(thread_pool, user_info_cache);
+        self.run_queue(session_client, thread_pool, user_info_cache);
 
         None
     }
@@ -743,18 +767,20 @@ impl RoomHistory {
 
 /* This function creates the content for a Row based on the content of msg */
 fn create_row(
+    session_client: MatrixClient,
     thread_pool: ThreadPool,
     user_info_cache: UserInfoCache,
     row: MessageContent,
     has_header: bool,
-    server_url: Url,
     access_token: AccessToken,
     rows: &Rc<RefCell<List>>,
 ) -> widgets::MessageBox {
+    let server_url = session_client.homeserver().clone();
     /* we need to create a message with the username, so that we don't have to pass
      * all information to the widget creating each row */
     let mut mb = widgets::MessageBox::new(server_url, access_token);
     mb.create(
+        session_client,
         thread_pool,
         user_info_cache,
         &row,
diff --git a/fractal-gtk/src/widgets/room_settings.rs b/fractal-gtk/src/widgets/room_settings.rs
index b3e42f89..4ff08658 100644
--- a/fractal-gtk/src/widgets/room_settings.rs
+++ b/fractal-gtk/src/widgets/room_settings.rs
@@ -1,6 +1,7 @@
 use crate::backend::{room, HandleError};
 use fractal_api::identifiers::UserId;
 use fractal_api::r0::AccessToken;
+use fractal_api::Client as MatrixClient;
 use glib::clone;
 use std::cell::RefCell;
 use std::rc::Rc;
@@ -67,7 +68,7 @@ impl RoomSettings {
 
     /* creates a empty list with members.len() rows, the content will be loaded when the row is
      * drawn */
-    pub fn create(&mut self) -> Option<gtk::Box> {
+    pub fn create(&mut self, session_client: MatrixClient) -> Option<gtk::Box> {
         let page = self
             .builder
             .get_object::<gtk::Box>("room_settings_box")
@@ -86,7 +87,7 @@ impl RoomSettings {
             stack.set_visible_child_name("info")
         }
 
-        self.init_room_settings();
+        self.init_room_settings(session_client);
         self.connect();
 
         Some(page)
@@ -198,7 +199,7 @@ impl RoomSettings {
         self.switch_handler = Some(Rc::new(switch_handler));
     }
 
-    fn init_room_settings(&mut self) {
+    fn init_room_settings(&mut self, session_client: MatrixClient) {
         let name = self.room.name.clone();
         let topic = self.room.topic.clone();
         let mut is_room = true;
@@ -228,7 +229,7 @@ impl RoomSettings {
             ))
         };
 
-        self.room_settings_show_avatar(edit);
+        self.room_settings_show_avatar(session_client, edit);
         self.room_settings_show_room_name(name, edit);
         self.room_settings_show_room_topic(topic, is_room, edit);
         self.room_settings_show_room_type(description);
@@ -421,7 +422,7 @@ impl RoomSettings {
         None
     }
 
-    fn room_settings_show_avatar(&self, edit: bool) {
+    fn room_settings_show_avatar(&self, session_client: MatrixClient, edit: bool) {
         let container = self
             .builder
             .get_object::<gtk::Box>("room_settings_avatar_box")
@@ -437,11 +438,10 @@ impl RoomSettings {
             }
         }
 
-        let server = self.server_url.clone();
         let access_token = self.access_token.clone();
         let room_id = self.room.id.clone();
         thread::spawn(
-            move || match room::get_room_avatar(server, access_token, room_id) {
+            move || match room::get_room_avatar(session_client, access_token, room_id) {
                 Ok((room, avatar)) => {
                     APPOP!(set_room_avatar, (room, avatar));
                 }
diff --git a/fractal-matrix-api/src/meson.build b/fractal-matrix-api/src/meson.build
index 9d60f08a..282d497c 100644
--- a/fractal-matrix-api/src/meson.build
+++ b/fractal-matrix-api/src/meson.build
@@ -17,10 +17,7 @@ api_sources = files(
   'r0/contact/request_verification_token_email.rs',
   'r0/contact/request_verification_token_msisdn.rs',
   'r0/context/get_context.rs',
-  'r0/directory/post_public_rooms.rs',
   'r0/media/create_content.rs',
-  'r0/media/get_content.rs',
-  'r0/media/get_content_thumbnail.rs',
   'r0/message/create_message_event.rs',
   'r0/message/get_message_events.rs',
   'r0/profile/get_display_name.rs',
@@ -43,7 +40,6 @@ api_sources = files(
   'r0/config.rs',
   'r0/contact.rs',
   'r0/context.rs',
-  'r0/directory.rs',
   'r0/filter.rs',
   'r0/media.rs',
   'r0/message.rs',
diff --git a/fractal-matrix-api/src/r0.rs b/fractal-matrix-api/src/r0.rs
index 4d46e6b8..e66e4dd0 100644
--- a/fractal-matrix-api/src/r0.rs
+++ b/fractal-matrix-api/src/r0.rs
@@ -2,7 +2,6 @@ pub mod account;
 pub mod config;
 pub mod contact;
 pub mod context;
-pub mod directory;
 pub mod filter;
 pub mod media;
 pub mod message;
diff --git a/fractal-matrix-api/src/r0/context/get_context.rs 
b/fractal-matrix-api/src/r0/context/get_context.rs
index f5b39f93..7f666700 100644
--- a/fractal-matrix-api/src/r0/context/get_context.rs
+++ b/fractal-matrix-api/src/r0/context/get_context.rs
@@ -45,7 +45,7 @@ pub fn request(
             "_matrix/client/r0/rooms/{}/context/{}",
             room_id, event_id,
         ))
-        .expect("Malformed URL in post_public_rooms");
+        .expect("Malformed URL in get_context");
 
     Client::new().get(url).query(params).build()
 }
diff --git a/fractal-matrix-api/src/r0/media.rs b/fractal-matrix-api/src/r0/media.rs
index eccd2e8e..1be1daed 100644
--- a/fractal-matrix-api/src/r0/media.rs
+++ b/fractal-matrix-api/src/r0/media.rs
@@ -1,3 +1 @@
 pub mod create_content;
-pub mod get_content;
-pub mod get_content_thumbnail;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]