[fractal/fractal-next] Drop do_async()



commit ba5a601b78567e0377bbc0713c9e47131ed64eb9
Author: Julian Sparber <julian sparber net>
Date:   Wed Oct 13 21:19:29 2021 +0200

    Drop do_async()
    
    We use now the macros `spawn!()` and `spawn_tokio!()` which helps debug
    issues with tokio task using the tokio-console.

 src/components/auth_dialog.rs                      |   7 +-
 .../account_settings/devices_page/device_list.rs   |  71 +++---
 .../account_settings/devices_page/device_row.rs    |   2 +-
 src/session/avatar.rs                              |  15 +-
 src/session/content/explore/mod.rs                 |  14 +-
 src/session/content/explore/public_room_list.rs    |  47 ++--
 src/session/content/invite.rs                      |   2 +-
 src/session/mod.rs                                 | 180 +++++++--------
 src/session/room/mod.rs                            | 257 +++++++++++----------
 src/session/room/timeline.rs                       |  21 +-
 src/session/room_creation/mod.rs                   |  35 +--
 src/session/room_list.rs                           |  22 +-
 src/utils.rs                                       |  45 ++--
 13 files changed, 368 insertions(+), 350 deletions(-)
---
diff --git a/src/components/auth_dialog.rs b/src/components/auth_dialog.rs
index dde96631..676d33b2 100644
--- a/src/components/auth_dialog.rs
+++ b/src/components/auth_dialog.rs
@@ -10,7 +10,7 @@ use std::future::Future;
 
 use crate::session::Session;
 use crate::session::UserExt;
-use crate::RUNTIME;
+use crate::spawn_tokio;
 
 use matrix_sdk::{
     ruma::api::{
@@ -232,7 +232,7 @@ impl AuthDialog {
 
         loop {
             let callback_clone = callback.clone();
-            let handle = RUNTIME.spawn(async move { callback_clone(auth_data).await });
+            let handle = spawn_tokio!(async move { callback_clone(auth_data).await });
             let response = handle.await.unwrap();
 
             let uiaa_info: UiaaInfo = match response {
@@ -275,8 +275,7 @@ impl AuthDialog {
                         priv_.stack.set_visible_child_name("fallback");
 
                         let client = self.session().client();
-                        let homeserver = RUNTIME
-                            .spawn(async move { client.homeserver().await })
+                        let homeserver = spawn_tokio!(async move { client.homeserver().await })
                             .await
                             .unwrap();
                         self.setup_fallback_page(
diff --git a/src/session/account_settings/devices_page/device_list.rs 
b/src/session/account_settings/devices_page/device_list.rs
index c3059ec4..6c0ec26d 100644
--- a/src/session/account_settings/devices_page/device_list.rs
+++ b/src/session/account_settings/devices_page/device_list.rs
@@ -5,7 +5,7 @@ use matrix_sdk::encryption::identities::UserDevices as CryptoDevices;
 use matrix_sdk::ruma::api::client::r0::device::Device as MatrixDevice;
 use matrix_sdk::Error;
 
-use crate::{session::Session, utils::do_async};
+use crate::{session::Session, spawn, spawn_tokio};
 
 use super::{Device, DeviceItem};
 
@@ -199,44 +199,43 @@ impl DeviceList {
 
         self.set_loading(true);
 
-        do_async(
-            glib::PRIORITY_DEFAULT,
-            async move {
-                let user_id = client.user_id().await.unwrap();
-                let crypto_devices = client.get_user_devices(&user_id).await;
+        let handle = spawn_tokio!(async move {
+            let user_id = client.user_id().await.unwrap();
+            let crypto_devices = client.get_user_devices(&user_id).await;
 
-                let crypto_devices = match crypto_devices {
-                    Ok(crypto_devices) => crypto_devices,
-                    Err(error) => return Err(Error::CryptoStoreError(error)),
-                };
+            let crypto_devices = match crypto_devices {
+                Ok(crypto_devices) => crypto_devices,
+                Err(error) => return Err(Error::CryptoStoreError(error)),
+            };
 
-                match client.devices().await {
-                    Ok(mut response) => {
-                        response
+            match client.devices().await {
+                Ok(mut response) => {
+                    response
+                        .devices
+                        .sort_unstable_by(|a, b| b.last_seen_ts.cmp(&a.last_seen_ts));
+
+                    let current_device = if let Some(current_device_id) = client.device_id().await {
+                        if let Some(index) = response
                             .devices
-                            .sort_unstable_by(|a, b| b.last_seen_ts.cmp(&a.last_seen_ts));
-
-                        let current_device =
-                            if let Some(current_device_id) = client.device_id().await {
-                                if let Some(index) = response.devices.iter().position(|device| {
-                                    *device.device_id == current_device_id.as_ref()
-                                }) {
-                                    Some(response.devices.remove(index))
-                                } else {
-                                    None
-                                }
-                            } else {
-                                None
-                            };
-
-                        Ok((current_device, response.devices, crypto_devices))
-                    }
-                    Err(error) => Err(Error::Http(error)),
+                            .iter()
+                            .position(|device| *device.device_id == current_device_id.as_ref())
+                        {
+                            Some(response.devices.remove(index))
+                        } else {
+                            None
+                        }
+                    } else {
+                        None
+                    };
+
+                    Ok((current_device, response.devices, crypto_devices))
                 }
-            },
-            clone!(@weak self as obj => move |response| async move {
-                obj.finish_loading(response);
-            }),
-        );
+                Err(error) => Err(Error::Http(error)),
+            }
+        });
+
+        spawn!(clone!(@weak self as obj => async move {
+            obj.finish_loading(handle.await.unwrap());
+        }));
     }
 }
diff --git a/src/session/account_settings/devices_page/device_row.rs 
b/src/session/account_settings/devices_page/device_row.rs
index a1a4a68a..1048aee4 100644
--- a/src/session/account_settings/devices_page/device_row.rs
+++ b/src/session/account_settings/devices_page/device_row.rs
@@ -1,9 +1,9 @@
 use gettextrs::gettext;
 use gtk::{glib, glib::clone, prelude::*, subclass::prelude::*, CompositeTemplate};
-use gtk_macros::spawn;
 
 use super::Device;
 use crate::components::SpinnerButton;
+use crate::spawn;
 
 const G_TIME_SPAN_DAY: i64 = 86400000000;
 
diff --git a/src/session/avatar.rs b/src/session/avatar.rs
index 4a9d566a..739ac720 100644
--- a/src/session/avatar.rs
+++ b/src/session/avatar.rs
@@ -12,7 +12,7 @@ use matrix_sdk::{
     ruma::identifiers::MxcUri,
 };
 
-use crate::utils::do_async;
+use crate::{spawn, spawn_tokio};
 
 use crate::session::Session;
 
@@ -173,16 +173,17 @@ impl Avatar {
                 media_type: MediaType::Uri(url),
                 format: MediaFormat::File,
             };
-            do_async(
+            let handle =
+                spawn_tokio!(async move { client.get_media_content(&request, true).await });
+
+            spawn!(
                 glib::PRIORITY_LOW,
-                async move { client.get_media_content(&request, true).await },
-                clone!(@weak self as obj => move |result| async move {
-                    // FIXME: We should retry if the request failed
-                    match result {
+                clone!(@weak self as obj => async move {
+                    match handle.await.unwrap() {
                         Ok(data) => obj.set_image_data(Some(data)),
                         Err(error) => error!("Couldn’t fetch avatar: {}", error),
                     };
-                }),
+                })
             );
         }
     }
diff --git a/src/session/content/explore/mod.rs b/src/session/content/explore/mod.rs
index 3040c7e2..7508a0f3 100644
--- a/src/session/content/explore/mod.rs
+++ b/src/session/content/explore/mod.rs
@@ -12,7 +12,7 @@ use log::error;
 use matrix_sdk::ruma::api::client::r0::thirdparty::get_protocols;
 
 use crate::session::Session;
-use crate::utils::do_async;
+use crate::{spawn, spawn_tokio};
 
 mod imp {
     use super::*;
@@ -236,15 +236,17 @@ impl Explore {
         priv_.network_menu.append(Some("all"), "All rooms");
         priv_.network_menu.set_active(Some(0));
 
-        do_async(
+        let handle =
+            spawn_tokio!(async move { client.send(get_protocols::Request::new(), None).await });
+
+        spawn!(
             glib::PRIORITY_DEFAULT_IDLE,
-            async move { client.send(get_protocols::Request::new(), None).await },
-            clone!(@weak self as obj => move |result| async move {
-                match result {
+            clone!(@weak self as obj => async move {
+                match handle.await.unwrap() {
                  Ok(response) => obj.set_protocols(response),
                  Err(error) => error!("Error loading supported protocols: {}", error),
                 }
-            }),
+            })
         );
     }
 }
diff --git a/src/session/content/explore/public_room_list.rs b/src/session/content/explore/public_room_list.rs
index 9b59101e..d1eb1c8d 100644
--- a/src/session/content/explore/public_room_list.rs
+++ b/src/session/content/explore/public_room_list.rs
@@ -1,6 +1,6 @@
 use crate::{
     session::{content::explore::PublicRoom, Session},
-    utils::do_async,
+    spawn, spawn_tokio,
 };
 use gtk::{gio, glib, glib::clone, prelude::*, subclass::prelude::*};
 use log::error;
@@ -292,30 +292,31 @@ impl PublicRoomList {
         let current_server = server.clone();
         let current_network = network.clone();
 
-        do_async(
+        let handle = spawn_tokio!(async move {
+            let room_network = match network.as_deref() {
+                Some("matrix") => RoomNetwork::Matrix,
+                Some("all") => RoomNetwork::All,
+                Some(custom) => RoomNetwork::ThirdParty(custom),
+                _ => RoomNetwork::default(),
+            };
+            let server = server.and_then(|server| ServerNameBox::try_from(server).ok());
+
+            let request = assign!(PublicRoomsRequest::new(), {
+              limit: Some(uint!(20)),
+              since: next_batch.as_deref(),
+              room_network,
+              server: server.as_deref(),
+              filter: assign!(Filter::new(), { generic_search_term: search_term.as_deref() }),
+            });
+            client.public_rooms_filtered(request).await
+        });
+
+        spawn!(
             glib::PRIORITY_DEFAULT_IDLE,
-            async move {
-                let room_network = match network.as_deref() {
-                    Some("matrix") => RoomNetwork::Matrix,
-                    Some("all") => RoomNetwork::All,
-                    Some(custom) => RoomNetwork::ThirdParty(custom),
-                    _ => RoomNetwork::default(),
-                };
-                let server = server.and_then(|server| ServerNameBox::try_from(server).ok());
-
-                let request = assign!(PublicRoomsRequest::new(), {
-                  limit: Some(uint!(20)),
-                  since: next_batch.as_deref(),
-                  room_network,
-                  server: server.as_deref(),
-                  filter: assign!(Filter::new(), { generic_search_term: search_term.as_deref() }),
-                });
-                client.public_rooms_filtered(request).await
-            },
-            clone!(@weak self as obj => move |result| async move {
+            clone!(@weak self as obj => async move {
                 // If the search term changed we ignore the response
                 if obj.is_valid_response(current_search_term, current_server, current_network) {
-                    match result {
+                    match handle.await.unwrap() {
                      Ok(response) => obj.handle_public_rooms_response(response),
                      Err(error) => {
                         obj.set_request_sent(false);
@@ -323,7 +324,7 @@ impl PublicRoomList {
                      },
                     }
                 }
-            }),
+            })
         );
     }
 }
diff --git a/src/session/content/invite.rs b/src/session/content/invite.rs
index 76078807..6b3ce0a8 100644
--- a/src/session/content/invite.rs
+++ b/src/session/content/invite.rs
@@ -1,10 +1,10 @@
 use crate::{
     components::{Avatar, LabelWithWidgets, Pill, SpinnerButton},
     session::room::{Room, RoomType},
+    spawn,
 };
 use adw::subclass::prelude::*;
 use gtk::{glib, glib::clone, prelude::*, subclass::prelude::*, CompositeTemplate};
-use gtk_macros::spawn;
 
 mod imp {
     use super::*;
diff --git a/src/session/mod.rs b/src/session/mod.rs
index 833a9166..25a72d24 100644
--- a/src/session/mod.rs
+++ b/src/session/mod.rs
@@ -19,10 +19,9 @@ pub use self::user::{User, UserExt};
 
 use crate::secret;
 use crate::secret::StoredSession;
-use crate::utils::do_async;
 use crate::Error;
 use crate::Window;
-use crate::RUNTIME;
+use crate::{spawn, spawn_tokio};
 
 use crate::matrix_error::UserFacingMatrixError;
 use crate::session::content::ContentType;
@@ -51,7 +50,7 @@ use matrix_sdk::{
         error::{FromHttpResponseError, ServerError},
     },
     uuid::Uuid,
-    Client, HttpError,
+    Client, Error as MatrixError, HttpError,
 };
 use rand::{distributions::Alphanumeric, thread_rng, Rng};
 use std::fs;
@@ -293,48 +292,49 @@ impl Session {
                 .encode_lower(&mut Uuid::encode_buffer()),
         );
 
-        do_async(
-            glib::PRIORITY_DEFAULT_IDLE,
-            async move {
-                let passphrase: String = {
-                    let mut rng = thread_rng();
-                    (&mut rng)
-                        .sample_iter(Alphanumeric)
-                        .take(30)
-                        .map(char::from)
-                        .collect()
-                };
-                let config = ClientConfig::new()
-                    .request_config(RequestConfig::new().retry_limit(2))
-                    .passphrase(passphrase.clone())
-                    .store_path(path.clone());
-
-                let client = Client::new_with_config(homeserver.clone(), config).unwrap();
-                let response = client
-                    .login(&username, &password, None, Some("Fractal Next"))
-                    .await;
-                match response {
-                    Ok(response) => Ok((
-                        client,
-                        StoredSession {
-                            homeserver,
-                            path,
-                            passphrase,
-                            access_token: response.access_token,
-                            user_id: response.user_id,
-                            device_id: response.device_id,
-                        },
-                    )),
-                    Err(error) => {
-                        // Remove the store created by Client::new()
-                        fs::remove_dir_all(path).unwrap();
-                        Err(error)
-                    }
+        let handle = spawn_tokio!(async move {
+            let passphrase: String = {
+                let mut rng = thread_rng();
+                (&mut rng)
+                    .sample_iter(Alphanumeric)
+                    .take(30)
+                    .map(char::from)
+                    .collect()
+            };
+            let config = ClientConfig::new()
+                .request_config(RequestConfig::new().retry_limit(2))
+                .passphrase(passphrase.clone())
+                .store_path(path.clone());
+
+            let client = Client::new_with_config(homeserver.clone(), config).unwrap();
+            let response = client
+                .login(&username, &password, None, Some("Fractal Next"))
+                .await;
+            match response {
+                Ok(response) => Ok((
+                    client,
+                    StoredSession {
+                        homeserver,
+                        path,
+                        passphrase,
+                        access_token: response.access_token,
+                        user_id: response.user_id,
+                        device_id: response.device_id,
+                    },
+                )),
+                Err(error) => {
+                    // Remove the store created by Client::new()
+                    fs::remove_dir_all(path).unwrap();
+                    Err(error)
                 }
-            },
-            clone!(@weak self as obj => move |result| async move {
-                obj.handle_login_result(result, true);
-            }),
+            }
+        });
+
+        spawn!(
+            glib::PRIORITY_DEFAULT_IDLE,
+            clone!(@weak self as obj => async move {
+                obj.handle_login_result(handle.await.unwrap(), true);
+            })
         );
     }
 
@@ -345,27 +345,27 @@ impl Session {
     }
 
     pub fn login_with_previous_session(&self, session: StoredSession) {
-        do_async(
+        let handle = spawn_tokio!(async move {
+            let config = ClientConfig::new()
+                .request_config(RequestConfig::new().retry_limit(2))
+                .passphrase(session.passphrase.clone())
+                .store_path(session.path.clone());
+
+            let client = Client::new_with_config(session.homeserver.clone(), config).unwrap();
+            client
+                .restore_login(matrix_sdk::Session {
+                    user_id: session.user_id.clone(),
+                    device_id: session.device_id.clone(),
+                    access_token: session.access_token.clone(),
+                })
+                .await
+                .map(|_| (client, session))
+        });
+        spawn!(
             glib::PRIORITY_DEFAULT_IDLE,
-            async move {
-                let config = ClientConfig::new()
-                    .request_config(RequestConfig::new().retry_limit(2))
-                    .passphrase(session.passphrase.clone())
-                    .store_path(session.path.clone());
-
-                let client = Client::new_with_config(session.homeserver.clone(), config).unwrap();
-                client
-                    .restore_login(matrix_sdk::Session {
-                        user_id: session.user_id.clone(),
-                        device_id: session.device_id.clone(),
-                        access_token: session.access_token.clone(),
-                    })
-                    .await
-                    .map(|_| (client, session))
-            },
-            clone!(@weak self as obj => move |result| async move {
-                obj.handle_login_result(result, false);
-            }),
+            clone!(@weak self as obj => async move {
+                obj.handle_login_result(handle.await.unwrap(), false);
+            })
         );
     }
 
@@ -382,23 +382,22 @@ impl Session {
                 priv_.user.set(user.clone()).unwrap();
                 self.notify("user");
 
-                do_async(
-                    glib::PRIORITY_LOW,
-                    async move {
-                        let display_name = client.display_name().await?;
-                        let avatar_url = client.avatar_url().await?;
-                        Ok((display_name, avatar_url))
-                    },
-                    move |result: matrix_sdk::Result<_>| async move {
-                        match result {
-                            Ok((display_name, avatar_url)) => {
-                                user.set_display_name(display_name);
-                                user.set_avatar_url(avatar_url);
-                            }
-                            Err(error) => error!("Couldn’t fetch account metadata: {}", error),
-                        };
-                    },
-                );
+                let handle = spawn_tokio!(async move {
+                    let display_name = client.display_name().await?;
+                    let avatar_url = client.avatar_url().await?;
+                    let result: Result<_, MatrixError> = Ok((display_name, avatar_url));
+                    result
+                });
+
+                spawn!(glib::PRIORITY_LOW, async move {
+                    match handle.await.unwrap() {
+                        Ok((display_name, avatar_url)) => {
+                            user.set_display_name(display_name);
+                            user.set_avatar_url(avatar_url);
+                        }
+                        Err(error) => error!("Couldn’t fetch account metadata: {}", error),
+                    }
+                });
 
                 if store_session {
                     // TODO: report secret service errors
@@ -434,7 +433,7 @@ impl Session {
         let priv_ = imp::Session::from_instance(self);
         let sender = self.create_new_sync_response_sender();
         let client = self.client();
-        let handle = RUNTIME.spawn(async move {
+        let handle = spawn_tokio!(async move {
             // TODO: only create the filter once and reuse it in the future
             let room_event_filter = assign!(RoomEventFilter::default(), {
                 lazy_load_options: LazyLoadOptions::Enabled {include_redundant_members: false},
@@ -596,14 +595,15 @@ impl Session {
     pub fn logout(&self) {
         let client = self.client();
 
-        do_async(
+        let handle = spawn_tokio!(async move {
+            let request = logout::Request::new();
+            client.send(request, None).await
+        });
+
+        spawn!(
             glib::PRIORITY_DEFAULT_IDLE,
-            async move {
-                let request = logout::Request::new();
-                client.send(request, None).await
-            },
-            clone!(@weak self as obj => move |result| async move {
-                match result {
+            clone!(@weak self as obj => async move {
+                match handle.await.unwrap() {
                     Ok(_) => obj.cleanup_session(),
                     Err(error) => {
                         error!("Couldn’t logout the session {}", error);
@@ -620,7 +620,7 @@ impl Session {
                         }
                     }
                 }
-            }),
+            })
         );
     }
 
diff --git a/src/session/room/mod.rs b/src/session/room/mod.rs
index 6d2f47cd..fb0d3b8b 100644
--- a/src/session/room/mod.rs
+++ b/src/session/room/mod.rs
@@ -31,7 +31,6 @@ use matrix_sdk::{
                     TextMessageEventContent,
                 },
                 name::NameEventContent,
-                power_levels::PowerLevelsEventContent,
                 topic::TopicEventContent,
             },
             tag::TagName,
@@ -55,9 +54,8 @@ use crate::components::{LabelWithWidgets, Pill};
 use crate::prelude::*;
 use crate::session::avatar::update_room_avatar_from_file;
 use crate::session::{Avatar, Session};
-use crate::utils::do_async;
 use crate::Error;
-use crate::RUNTIME;
+use crate::{spawn, spawn_tokio};
 
 mod imp {
     use super::*;
@@ -355,65 +353,66 @@ impl Room {
             return;
         }
 
-        do_async(
-            glib::PRIORITY_DEFAULT_IDLE,
-            async move {
-                match matrix_room {
-                    MatrixRoom::Invited(room) => {
-                        match category {
-                            RoomType::Invited => Ok(()),
-                            RoomType::Favorite => {
-                                room.accept_invitation().await
-                                // TODO: set favorite tag
-                            }
-                            RoomType::Normal => room.accept_invitation().await,
-                            RoomType::LowPriority => {
-                                room.accept_invitation().await
-                                // TODO: set low priority tag
-                            }
-                            RoomType::Left => room.reject_invitation().await,
+        let handle = spawn_tokio!(async move {
+            match matrix_room {
+                MatrixRoom::Invited(room) => {
+                    match category {
+                        RoomType::Invited => Ok(()),
+                        RoomType::Favorite => {
+                            room.accept_invitation().await
+                            // TODO: set favorite tag
+                        }
+                        RoomType::Normal => room.accept_invitation().await,
+                        RoomType::LowPriority => {
+                            room.accept_invitation().await
+                            // TODO: set low priority tag
                         }
+                        RoomType::Left => room.reject_invitation().await,
                     }
-                    MatrixRoom::Joined(room) => {
-                        match category {
-                            RoomType::Invited => Ok(()),
-                            RoomType::Favorite => {
-                                // TODO: set favorite tag
-                                Ok(())
-                            }
-                            RoomType::Normal => {
-                                // TODO: remove tags
-                                Ok(())
-                            }
-                            RoomType::LowPriority => {
-                                // TODO: set low priority tag
-                                Ok(())
-                            }
-                            RoomType::Left => room.leave().await,
+                }
+                MatrixRoom::Joined(room) => {
+                    match category {
+                        RoomType::Invited => Ok(()),
+                        RoomType::Favorite => {
+                            // TODO: set favorite tag
+                            Ok(())
+                        }
+                        RoomType::Normal => {
+                            // TODO: remove tags
+                            Ok(())
                         }
+                        RoomType::LowPriority => {
+                            // TODO: set low priority tag
+                            Ok(())
+                        }
+                        RoomType::Left => room.leave().await,
                     }
-                    MatrixRoom::Left(room) => {
-                        match category {
-                            RoomType::Invited => Ok(()),
-                            RoomType::Favorite => {
-                                room.join().await
-                                // TODO: set favorite tag
-                            }
-                            RoomType::Normal => {
-                                room.join().await
-                                // TODO: remove tags
-                            }
-                            RoomType::LowPriority => {
-                                room.join().await
-                                // TODO: set low priority tag
-                            }
-                            RoomType::Left => Ok(()),
+                }
+                MatrixRoom::Left(room) => {
+                    match category {
+                        RoomType::Invited => Ok(()),
+                        RoomType::Favorite => {
+                            room.join().await
+                            // TODO: set favorite tag
                         }
+                        RoomType::Normal => {
+                            room.join().await
+                            // TODO: remove tags
+                        }
+                        RoomType::LowPriority => {
+                            room.join().await
+                            // TODO: set low priority tag
+                        }
+                        RoomType::Left => Ok(()),
                     }
                 }
-            },
-            clone!(@weak self as obj => move |result| async move {
-                match result {
+            }
+        });
+
+        spawn!(
+            glib::PRIORITY_DEFAULT_IDLE,
+            clone!(@weak self as obj => async move {
+                match handle.await.unwrap() {
                         Ok(_) => {},
                         Err(error) => {
                                 error!("Couldn’t set the room category: {}", error);
@@ -440,8 +439,7 @@ impl Room {
                                 obj.load_category();
                         },
                 };
-
-            }),
+            })
         );
 
         self.set_category_internal(category);
@@ -452,13 +450,14 @@ impl Room {
 
         match matrix_room {
             MatrixRoom::Joined(_) => {
-                do_async(
+                let handle = spawn_tokio!(async move { matrix_room.tags().await });
+
+                spawn!(
                     glib::PRIORITY_DEFAULT_IDLE,
-                    async move { matrix_room.tags().await },
-                    clone!(@weak self as obj => move |tags_result| async move {
+                    clone!(@weak self as obj => async move {
                         let mut category = RoomType::Normal;
 
-                        if let Ok(Some(tags)) = tags_result {
+                        if let Ok(Some(tags)) = handle.await.unwrap() {
                             if tags.get(&TagName::Favorite).is_some() {
                                 category = RoomType::Favorite;
                             } else if tags.get(&TagName::LowPriority).is_some() {
@@ -467,7 +466,7 @@ impl Room {
                         }
 
                         obj.set_category_internal(category);
-                    }),
+                    })
                 );
             }
             MatrixRoom::Invited(_) => self.set_category_internal(RoomType::Invited),
@@ -522,16 +521,17 @@ impl Room {
 
     fn load_display_name(&self) {
         let matrix_room = self.matrix_room();
-        do_async(
+        let handle = spawn_tokio!(async move { matrix_room.display_name().await });
+
+        spawn!(
             glib::PRIORITY_DEFAULT_IDLE,
-            async move { matrix_room.display_name().await },
-            clone!(@weak self as obj => move |display_name| async move {
+            clone!(@weak self as obj => async move {
                 // FIXME: We should retry to if the request failed
-                match display_name {
+                match handle.await.unwrap() {
                         Ok(display_name) => obj.set_display_name(Some(display_name)),
                         Err(error) => error!("Couldn’t fetch display name: {}", error),
                 };
-            }),
+            })
         );
     }
 
@@ -557,18 +557,19 @@ impl Room {
         };
         let name_content = NameEventContent::new(Some(room_name));
 
-        do_async(
+        let handle = spawn_tokio!(async move {
+            let content = AnyStateEventContent::RoomName(name_content);
+            joined_room.send_state_event(content, "").await
+        });
+
+        spawn!(
             glib::PRIORITY_DEFAULT_IDLE,
-            async move {
-                let content = AnyStateEventContent::RoomName(name_content);
-                joined_room.send_state_event(content, "").await
-            },
-            clone!(@weak self as obj => move |room_name| async move {
-                match room_name {
+            clone!(@weak self as obj => async move {
+                match handle.await.unwrap() {
                     Ok(_room_name) => info!("Successfully updated room name"),
                     Err(error) => error!("Couldn’t update room name: {}", error),
                 };
-            }),
+            })
         );
     }
 
@@ -597,18 +598,19 @@ impl Room {
             }
         };
 
-        do_async(
+        let handle = spawn_tokio!(async move {
+            let content = AnyStateEventContent::RoomTopic(TopicEventContent::new(topic));
+            joined_room.send_state_event(content, "").await
+        });
+
+        spawn!(
             glib::PRIORITY_DEFAULT_IDLE,
-            async move {
-                let content = AnyStateEventContent::RoomTopic(TopicEventContent::new(topic));
-                joined_room.send_state_event(content, "").await
-            },
-            clone!(@weak self as obj => move |topic| async move {
-                match topic {
+            clone!(@weak self as obj => async move {
+                match handle.await.unwrap() {
                     Ok(_topic) => info!("Successfully updated room topic"),
                     Err(error) => error!("Couldn’t update topic: {}", error),
                 };
-            }),
+            })
         );
     }
 
@@ -749,54 +751,55 @@ impl Room {
 
         priv_.members_loaded.set(true);
         let matrix_room = self.matrix_room();
-        do_async(
+        let handle = spawn_tokio!(async move { matrix_room.active_members().await });
+        spawn!(
             glib::PRIORITY_LOW,
-            async move { matrix_room.active_members().await },
-            clone!(@weak self as obj => move |members| async move {
+            clone!(@weak self as obj => async move {
                 // FIXME: We should retry to load the room members if the request failed
                 let priv_ = imp::Room::from_instance(&obj);
-                match members {
+                match handle.await.unwrap() {
                         Ok(members) => obj.add_members(members),
                         Err(error) => {
                             priv_.members_loaded.set(false);
                             error!("Couldn’t load room members: {}", error)
                         },
                 };
-            }),
+            })
         );
     }
 
     fn load_power_levels(&self) {
         let matrix_room = self.matrix_room();
-        do_async(
-            glib::PRIORITY_DEFAULT_IDLE,
-            async move {
-                let state_event = match matrix_room
-                    .get_state_event(EventType::RoomPowerLevels, "")
-                    .await
-                {
-                    Ok(state_event) => state_event,
-                    Err(e) => {
-                        error!("Initial load of room power levels failed: {}", e);
-                        return None;
+        let handle = spawn_tokio!(async move {
+            let state_event = match matrix_room
+                .get_state_event(EventType::RoomPowerLevels, "")
+                .await
+            {
+                Ok(state_event) => state_event,
+                Err(e) => {
+                    error!("Initial load of room power levels failed: {}", e);
+                    return None;
+                }
+            };
+
+            state_event
+                .and_then(|e| e.deserialize().ok())
+                .and_then(|e| {
+                    if let AnySyncStateEvent::RoomPowerLevels(e) = e {
+                        Some(e)
+                    } else {
+                        None
                     }
-                };
+                })
+        });
 
-                state_event
-                    .and_then(|e| e.deserialize().ok())
-                    .and_then(|e| {
-                        if let AnySyncStateEvent::RoomPowerLevels(e) = e {
-                            Some(e)
-                        } else {
-                            None
-                        }
-                    })
-            },
-            clone!(@weak self as obj => move |event: Option<SyncStateEvent<PowerLevelsEventContent>>| async 
move {
-                if let Some(event) = event {
+        spawn!(
+            glib::PRIORITY_DEFAULT_IDLE,
+            clone!(@weak self as obj => async move {
+                if let Some(event) = handle.await.unwrap() {
                     obj.power_levels().update_from_event(event);
                 }
-            }),
+            })
         );
     }
 
@@ -842,16 +845,17 @@ impl Room {
             let event = Event::new(raw_event.into(), self);
             priv_.timeline.get().unwrap().append_pending(event);
 
-            do_async(
+            let handle = spawn_tokio!(async move { matrix_room.send(content, Some(txn_id)).await });
+
+            spawn!(
                 glib::PRIORITY_DEFAULT_IDLE,
-                async move { matrix_room.send(content, Some(txn_id)).await },
-                clone!(@weak self as obj => move |result| async move {
+                clone!(@weak self as obj => async move {
                     // FIXME: We should retry the request if it fails
-                    match result {
+                    match handle.await.unwrap() {
                             Ok(result) => obj.timeline().set_event_id_for_pending(pending_id, 
result.event_id),
                             Err(error) => error!("Couldn’t send message: {}", error),
                     };
-                }),
+                })
             );
         }
     }
@@ -871,15 +875,18 @@ impl Room {
         let matrix_room = self.matrix_room();
         let client = self.session().client();
 
-        do_async(
+        let handle = spawn_tokio!(async move {
+            update_room_avatar_from_file(&client, &matrix_room, filename.as_ref()).await
+        });
+
+        spawn!(
             glib::PRIORITY_DEFAULT_IDLE,
-            async move { update_room_avatar_from_file(&client, &matrix_room, filename.as_ref()).await },
-            clone!(@weak self as this => move |avatar_uri| async move {
-                match avatar_uri {
+            clone!(@weak self as this => async move {
+                match handle.await.unwrap() {
                     Ok(_avatar_uri) => info!("Sucessfully updated room avatar"),
                     Err(error) => error!("Couldn’t update room avatar: {}", error),
                 };
-            }),
+            })
         );
     }
 
@@ -887,7 +894,7 @@ impl Room {
         let matrix_room = self.matrix_room();
 
         if let MatrixRoom::Invited(matrix_room) = matrix_room {
-            let handle = RUNTIME.spawn(async move { matrix_room.accept_invitation().await });
+            let handle = spawn_tokio!(async move { matrix_room.accept_invitation().await });
             match handle.await.unwrap() {
                 Ok(result) => Ok(result),
                 Err(error) => {
@@ -917,7 +924,7 @@ impl Room {
         let matrix_room = self.matrix_room();
 
         if let MatrixRoom::Invited(matrix_room) = matrix_room {
-            let handle = RUNTIME.spawn(async move { matrix_room.reject_invitation().await });
+            let handle = spawn_tokio!(async move { matrix_room.reject_invitation().await });
             match handle.await.unwrap() {
                 Ok(result) => Ok(result),
                 Err(error) => {
diff --git a/src/session/room/timeline.rs b/src/session/room/timeline.rs
index 026fc2a1..f3cd94f4 100644
--- a/src/session/room/timeline.rs
+++ b/src/session/room/timeline.rs
@@ -7,7 +7,7 @@ use matrix_sdk::ruma::{
 };
 
 use crate::session::room::{Event, Item, ItemType, Room};
-use crate::utils::do_async;
+use crate::{spawn, spawn_tokio};
 
 mod imp {
     use super::*;
@@ -530,19 +530,20 @@ impl Timeline {
         let last_event = self.oldest_event();
         let contains_last_event = last_event.is_some();
 
-        do_async(
+        let handle = spawn_tokio!(async move {
+            matrix_room
+                .messages(last_event.as_ref(), None, 20, Direction::Backward)
+                .await
+        });
+
+        spawn!(
             glib::PRIORITY_LOW,
-            async move {
-                matrix_room
-                    .messages(last_event.as_ref(), None, 20, Direction::Backward)
-                    .await
-            },
-            clone!(@weak self as obj => move |events| async move {
+            clone!(@weak self as obj => async move {
                 obj.remove_loading_spinner();
 
                 // FIXME: If the request fails it's automatically restarted because the added events (none), 
didn't fill the screen.
                 // We should block the loading for some time before retrying
-                match events {
+                match handle.await.unwrap() {
                        Ok(Some(events)) => {
                             let events: Vec<Event> = if contains_last_event {
                                             events
@@ -563,7 +564,7 @@ impl Timeline {
                        Err(error) => error!("Couldn't load previous events for room {}: {}", error, 
obj.room().room_id()),
                }
                obj.set_loading(false);
-            }),
+            })
         );
     }
 }
diff --git a/src/session/room_creation/mod.rs b/src/session/room_creation/mod.rs
index 239e2e99..0783cc4c 100644
--- a/src/session/room_creation/mod.rs
+++ b/src/session/room_creation/mod.rs
@@ -7,7 +7,7 @@ use std::convert::{TryFrom, TryInto};
 use crate::components::SpinnerButton;
 use crate::session::user::UserExt;
 use crate::session::Session;
-use crate::utils::do_async;
+use crate::{spawn, spawn_tokio};
 use matrix_sdk::{
     ruma::{
         api::{
@@ -222,22 +222,23 @@ impl RoomCreation {
             None
         };
 
-        do_async(
+        let handle = spawn_tokio!(async move {
+            // We don't allow invalid room names to be entered by the user
+            let name = room_name.as_str().try_into().unwrap();
+
+            let request = assign!(create_room::Request::new(),
+            {
+                name: Some(name),
+                visibility,
+                room_alias_name: room_address.as_deref()
+            });
+            client.create_room(request).await
+        });
+
+        spawn!(
             glib::PRIORITY_DEFAULT_IDLE,
-            async move {
-                // We don't allow invalid room names to be entered by the user
-                let name = room_name.as_str().try_into().unwrap();
-
-                let request = assign!(create_room::Request::new(),
-                {
-                    name: Some(name),
-                    visibility,
-                    room_alias_name: room_address.as_deref()
-                });
-                client.create_room(request).await
-            },
-            clone!(@weak self as obj => move |result| async move {
-                match result {
+            clone!(@weak self as obj => async move {
+                match handle.await.unwrap() {
                         Ok(response) => {
                             if let Some(session) = obj.session() {
                                 let room = session.room_list().get_wait(response.room_id).await;
@@ -250,7 +251,7 @@ impl RoomCreation {
                             obj.handle_error(error);
                         },
                 };
-            }),
+            })
         );
 
         None
diff --git a/src/session/room_list.rs b/src/session/room_list.rs
index c75af6f8..573de2df 100644
--- a/src/session/room_list.rs
+++ b/src/session/room_list.rs
@@ -7,8 +7,7 @@ use matrix_sdk::{
 
 use crate::{
     session::{room::Room, Session},
-    utils::do_async,
-    Error,
+    spawn, spawn_tokio, Error,
 };
 use gettextrs::gettext;
 use log::error;
@@ -319,15 +318,16 @@ impl RoomList {
 
         self.pending_rooms_insert(identifier.clone());
 
-        do_async(
+        let handle = spawn_tokio!(async move {
+            client
+                .join_room_by_id_or_alias(&identifier_clone, &[])
+                .await
+        });
+
+        spawn!(
             glib::PRIORITY_DEFAULT_IDLE,
-            async move {
-                client
-                    .join_room_by_id_or_alias(&identifier_clone, &[])
-                    .await
-            },
-            clone!(@weak self as obj => move |response| async move {
-                match response {
+            clone!(@weak self as obj => async move {
+                match handle.await.unwrap() {
                     Ok(response) => obj.pending_rooms_replace_or_remove(&identifier, response.room_id),
                     Err(error) => {
                         obj.pending_rooms_remove(&identifier);
@@ -347,7 +347,7 @@ impl RoomList {
                         }
                     }
                 }
-            }),
+            })
         );
     }
 
diff --git a/src/utils.rs b/src/utils.rs
index a1d1769f..19a6db3e 100644
--- a/src/utils.rs
+++ b/src/utils.rs
@@ -32,28 +32,35 @@ macro_rules! event_from_sync_event {
     };
 }
 
-use crate::RUNTIME;
-use gtk::gio::prelude::*;
-use gtk::glib::{self, Object};
-use std::future::Future;
-/// Execute a future on a tokio runtime and spawn a future on the local thread to handle the result
-pub fn do_async<
-    R: Send + 'static,
-    F1: Future<Output = R> + Send + 'static,
-    F2: Future<Output = ()> + 'static,
-    FN: FnOnce(R) -> F2 + 'static,
->(
-    priority: glib::source::Priority,
-    tokio_fut: F1,
-    glib_closure: FN,
-) {
-    let handle = RUNTIME.spawn(async move { tokio_fut.await });
+/// Spawn a future on the default `MainContext`
+///
+/// This was taken from `gtk-macors`
+/// but allows setting optionally the priority
+///
+/// FIXME: this should maybe be upstreamed
+#[macro_export]
+macro_rules! spawn {
+    ($future:expr) => {
+        let ctx = glib::MainContext::default();
+        ctx.spawn_local($future);
+    };
+    ($priority:expr, $future:expr) => {
+        let ctx = glib::MainContext::default();
+        ctx.spawn_local_with_priority($priority, $future);
+    };
+}
 
-    glib::MainContext::default().spawn_local_with_priority(priority, async move {
-        glib_closure(handle.await.unwrap()).await
-    });
+/// Spawn a future on the tokio runtime
+#[macro_export]
+macro_rules! spawn_tokio {
+    ($future:expr) => {
+        crate::RUNTIME.spawn($future)
+    };
 }
 
+use gtk::gio::prelude::*;
+use gtk::glib::Object;
+
 /// Returns an expression looking up the given property on `object`.
 pub fn prop_expr<T: IsA<Object>>(object: &T, prop: &str) -> gtk::Expression {
     let obj_expr = gtk::ConstantExpression::new(object).upcast();


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