From fd759155b32eb6cadb2221ecd5a9f8bac3f87551 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Commaille?= Date: Wed, 26 Jun 2024 12:31:03 +0200 Subject: [PATCH] chore: Use new glib::clone! macro syntax --- Cargo.lock | 1 + Cargo.toml | 1 + .../account_switcher_button.rs | 10 +- .../account_switcher_popover.rs | 9 +- src/application.rs | 111 +++-- src/components/avatar/editable.rs | 10 +- src/components/avatar/image.rs | 16 +- src/components/avatar/overlapping.rs | 10 +- src/components/context_menu_bin.rs | 33 +- src/components/crypto/identity_setup_view.rs | 81 ++- src/components/dialogs/auth.rs | 19 +- src/components/dialogs/join_room.rs | 17 +- src/components/dialogs/user_profile.rs | 12 +- src/components/drag_overlay.rs | 10 +- src/components/media/content_viewer.rs | 10 +- src/components/media/image_paintable.rs | 12 +- src/components/media/video_player.rs | 19 +- src/components/offline_banner.rs | 18 +- src/components/pill/mod.rs | 20 +- src/components/pill/search_entry.rs | 25 +- .../power_level_selection/popover.rs | 30 +- src/components/reaction_chooser.rs | 9 +- src/components/rows/button_row.rs | 12 +- src/components/rows/check_loading_row.rs | 15 +- src/components/rows/combo_loading_row.rs | 95 ++-- src/components/rows/loading_row.rs | 9 +- src/components/rows/substring_entry_row.rs | 10 +- src/components/rows/switch_loading_row.rs | 15 +- src/components/scale_revealer.rs | 38 +- src/components/user_page.rs | 55 ++- .../camera/camera_paintable/linux.rs | 29 +- src/contrib/qr_code_scanner/mod.rs | 22 +- .../accept_request_page.rs | 13 +- .../cancelled_page.rs | 22 +- .../choose_method_page.rs | 23 +- .../completed_page.rs | 13 +- .../confirm_qr_code_page.rs | 13 +- src/identity_verification_view/mod.rs | 25 +- .../no_supported_methods_page.rs | 22 +- .../qr_code_scanned_page.rs | 13 +- src/identity_verification_view/sas_page.rs | 22 +- .../scan_qr_code_page.rs | 54 +- .../wait_for_other_page.rs | 13 +- src/login/homeserver_page.rs | 12 +- src/login/idp_button.rs | 7 +- src/login/method_page.rs | 19 +- src/login/mod.rs | 39 +- src/login/session_setup_view.rs | 71 ++- src/session/model/ignored_users.rs | 10 +- .../notifications/notifications_settings.rs | 40 +- src/session/model/remote_room.rs | 10 +- src/session/model/room/join_rule.rs | 21 +- src/session/model/room/member.rs | 34 +- src/session/model/room/member_list.rs | 20 +- src/session/model/room/mod.rs | 225 ++++++--- src/session/model/room/permissions.rs | 10 +- src/session/model/room/timeline/mod.rs | 20 +- src/session/model/room_list/mod.rs | 10 +- src/session/model/session.rs | 50 +- .../model/sidebar_data/category/mod.rs | 12 +- src/session/model/sidebar_data/item_list.rs | 10 +- src/session/model/sidebar_data/list_model.rs | 45 +- src/session/model/sidebar_data/selection.rs | 9 +- src/session/model/user.rs | 30 +- src/session/model/user_sessions_list/mod.rs | 22 +- .../verification/identity_verification.rs | 38 +- .../model/verification/verification_list.rs | 10 +- .../general_page/change_password_subpage.rs | 21 +- .../deactivate_account_subpage.rs | 32 +- .../view/account_settings/general_page/mod.rs | 35 +- src/session/view/account_settings/mod.rs | 50 +- .../account_settings/notifications_page.rs | 93 ++-- .../ignored_users_subpage/mod.rs | 44 +- .../account_settings/security_page/mod.rs | 41 +- .../user_sessions_page/mod.rs | 42 +- .../user_sessions_page/user_session_row.rs | 9 +- src/session/view/content/explore/mod.rs | 53 +- .../view/content/explore/public_room.rs | 25 +- .../view/content/explore/public_room_list.rs | 24 +- .../view/content/explore/public_room_row.rs | 39 +- .../view/content/explore/server_list.rs | 10 +- .../view/content/explore/servers_popover.rs | 34 +- src/session/view/content/invite.rs | 18 +- src/session/view/content/mod.rs | 32 +- .../addresses_subpage/completion_popover.rs | 107 ++-- .../room_details/addresses_subpage/mod.rs | 133 +++-- .../content/room_details/general_page/mod.rs | 272 ++++++---- .../room_details/history_viewer/audio.rs | 36 +- .../room_details/history_viewer/audio_row.rs | 28 +- .../room_details/history_viewer/file.rs | 36 +- .../room_details/history_viewer/media.rs | 36 +- .../room_details/history_viewer/media_item.rs | 40 +- .../room_details/invite_subpage/list.rs | 30 +- .../room_details/invite_subpage/mod.rs | 30 +- .../members_list_view/extra_lists.rs | 33 +- .../membership_subpage_row.rs | 10 +- .../members_page/members_list_view/mod.rs | 18 +- .../content/room_details/members_page/mod.rs | 15 +- .../permissions/add_members_subpage.rs | 108 ++-- .../permissions/member_power_level.rs | 9 +- .../room_details/permissions/member_row.rs | 18 +- .../permissions/members_subpage.rs | 34 +- .../permissions/permissions_subpage.rs | 19 +- .../permissions/privileged_members.rs | 28 +- .../view/content/room_history/item_row.rs | 466 ++++++++++++------ .../room_history/member_timestamp/row.rs | 9 +- .../content/room_history/message_row/audio.rs | 68 +-- .../room_history/message_row/content.rs | 12 +- .../content/room_history/message_row/media.rs | 115 +++-- .../message_row/message_state_stack.rs | 20 +- .../content/room_history/message_row/mod.rs | 38 +- .../room_history/message_row/reaction/mod.rs | 22 +- .../message_row/reaction/reaction_popover.rs | 16 +- .../room_history/message_row/reaction_list.rs | 5 +- .../room_history/message_row/text/mod.rs | 24 +- .../completion/completion_popover.rs | 109 ++-- .../message_toolbar/completion/member_list.rs | 22 +- .../room_history/message_toolbar/mod.rs | 113 +++-- src/session/view/content/room_history/mod.rs | 236 +++++---- .../room_history/read_receipts_list/mod.rs | 40 +- .../read_receipts_popover.rs | 16 +- .../content/room_history/sender_avatar/mod.rs | 65 ++- .../room_history/state_row/tombstone.rs | 18 +- .../view/content/room_history/typing_row.rs | 17 +- .../room_history/verification_info_bar.rs | 19 +- .../view/create_dm_dialog/dm_user_list.rs | 20 +- src/session/view/create_dm_dialog/mod.rs | 10 +- src/session/view/media_viewer.rs | 188 ++++--- src/session/view/session_view.rs | 42 +- src/session/view/sidebar/mod.rs | 66 ++- src/session/view/sidebar/room_row.rs | 59 ++- src/session/view/sidebar/row.rs | 213 +++++--- src/session_list/mod.rs | 34 +- src/system_settings/linux.rs | 10 +- src/utils/expression_list_model.rs | 22 +- src/utils/sourceview.rs | 10 +- src/window.rs | 63 ++- 137 files changed, 3607 insertions(+), 2012 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 74f1d68e..83de4b26 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1410,6 +1410,7 @@ dependencies = [ "futures-util", "geo-uri", "gettext-rs", + "glib", "gst-plugin-gtk4", "gstreamer", "gstreamer-base", diff --git a/Cargo.toml b/Cargo.toml index 15f3c31a..9baf08d2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -51,6 +51,7 @@ url = "2" # gtk-rs project and dependents. These usually need to be updated together. adw = { package = "libadwaita", version = "0.6", features = ["v1_5"] } +glib = { version = "0.19", features = ["unstable-clone-syntax"] } # Remove when GTK depends on version with new clone syntax gst = { version = "0.22", package = "gstreamer" } gst_base = { version = "0.22", package = "gstreamer-base" } gst_gtk = { version = "0.12", package = "gst-plugin-gtk4" } diff --git a/src/account_switcher/account_switcher_button.rs b/src/account_switcher/account_switcher_button.rs index 557c5393..08bb8937 100644 --- a/src/account_switcher/account_switcher_button.rs +++ b/src/account_switcher/account_switcher_button.rs @@ -116,9 +116,13 @@ impl AccountSwitcherButton { parent.set_popover(None); } - let closed_handler = popover.connect_closed(clone!(@weak self as obj => move |_| { - obj.set_active(false); - })); + let closed_handler = popover.connect_closed(clone!( + #[weak(rename_to = obj)] + self, + move |_| { + obj.set_active(false); + } + )); popover.set_parent(self); imp.popover.set(popover, vec![closed_handler]); diff --git a/src/account_switcher/account_switcher_popover.rs b/src/account_switcher/account_switcher_popover.rs index cf7ec787..f8ea2424 100644 --- a/src/account_switcher/account_switcher_popover.rs +++ b/src/account_switcher/account_switcher_popover.rs @@ -68,10 +68,13 @@ mod imp { }); if let Some(selection) = &selection { - let selected_handler = - selection.connect_selected_item_notify(clone!(@weak obj => move |selection| { + let selected_handler = selection.connect_selected_item_notify(clone!( + #[weak] + obj, + move |selection| { obj.update_selected_item(selection.selected()); - })); + } + )); obj.update_selected_item(selection.selected()); self.session_selection diff --git a/src/application.rs b/src/application.rs index e1339184..7c4bfe44 100644 --- a/src/application.rs +++ b/src/application.rs @@ -56,18 +56,23 @@ mod imp { app.set_up_gactions(); app.set_up_accels(); - self.session_list - .connect_error_notify(clone!(@weak app => move |session_list| { + self.session_list.connect_error_notify(clone!( + #[weak] + app, + move |session_list| { if let Some(message) = session_list.error() { let window = app.present_main_window(); window.show_secret_error(&message); } - })); - spawn!( - clone!(@weak self.session_list as session_list => async move { + } + )); + spawn!(clone!( + #[weak(rename_to = session_list)] + self.session_list, + async move { session_list.restore_sessions().await; - }) - ); + } + )); } } @@ -228,15 +233,25 @@ impl Application { dialog.add_credit_section(Some(&gettext("Name by")), &["Regina Bíró"]); // If the user wants our support room, try to open it ourselves. - dialog.connect_activate_link(clone!(@weak self as obj, @weak dialog => @default-return false, move |_, uri| { - if uri == "https://matrix.to/#/#fractal:gnome.org" && obj.session_list().has_session_ready() { - obj.process_uri(uri); - dialog.close(); - return true; - } + dialog.connect_activate_link(clone!( + #[weak(rename_to = obj)] + self, + #[weak] + dialog, + #[upgrade_or] + false, + move |_, uri| { + if uri == "https://matrix.to/#/#fractal:gnome.org" + && obj.session_list().has_session_ready() + { + obj.process_uri(uri); + dialog.close(); + return true; + } - false - })); + false + } + )); dialog.present(&self.present_main_window()); } @@ -277,26 +292,34 @@ impl Application { self.process_session_intent(session_intent); } _ => { - spawn!(clone!(@weak self as obj => async move { - obj.choose_session_for_uri(matrix_uri).await; - })); + spawn!(clone!( + #[weak(rename_to = obj)] + self, + async move { + obj.choose_session_for_uri(matrix_uri).await; + } + )); } }, } } else { // Wait for the list to be ready. let cell = Rc::new(RefCell::new(Some(intent))); - let handler = session_list.connect_state_notify( - clone!(@weak self as app, @strong cell => move |session_list| { + let handler = session_list.connect_state_notify(clone!( + #[weak(rename_to = obj)] + self, + #[strong] + cell, + move |session_list| { if session_list.state() == LoadingState::Ready { - app.imp().intent_handler.disconnect_signals(); + obj.imp().intent_handler.disconnect_signals(); if let Some(intent) = cell.take() { - app.process_intent(intent); + obj.process_intent(intent); } } - }), - ); + } + )); self.imp() .intent_handler .set(session_list.upcast_ref(), vec![handler]); @@ -335,17 +358,22 @@ impl Application { } else { // Wait for the session to be ready. let cell = Rc::new(RefCell::new(Some(intent))); - let handler = session.connect_state_notify( - clone!(@weak self as app, @strong cell => move |session| { + let handler = session.connect_state_notify(clone!( + #[weak(rename_to = obj)] + self, + #[strong] + cell, + move |session| { if session.state() == SessionState::Ready { - app.imp().intent_handler.disconnect_signals(); + obj.imp().intent_handler.disconnect_signals(); if let Some(intent) = cell.take() { - app.present_main_window().process_session_intent_ready(intent); + obj.present_main_window() + .process_session_intent_ready(intent); } } - }), - ); + } + )); self.imp() .intent_handler .set(session.upcast_ref(), vec![handler]); @@ -354,31 +382,38 @@ impl Application { // Wait for the session to be a `Session`. let session_list = self.session_list(); let cell = Rc::new(RefCell::new(Some(intent))); - let handler = session_list.connect_items_changed( - clone!(@weak self as app, @strong cell => move |session_list, pos, _, added| { + let handler = session_list.connect_items_changed(clone!( + #[weak(rename_to = obj)] + self, + #[strong] + cell, + move |session_list, pos, _, added| { if added == 0 { return; } - let Some(session_id) = cell.borrow().as_ref().map(|i| i.session_id().to_owned()) else { + let Some(session_id) = + cell.borrow().as_ref().map(|i| i.session_id().to_owned()) + else { return; }; for i in pos..pos + added { - let Some(session_info) = session_list.item(i).and_downcast::() else { + let Some(session_info) = session_list.item(i).and_downcast::() + else { break; }; if session_info.session_id() == session_id { - app.imp().intent_handler.disconnect_signals(); + obj.imp().intent_handler.disconnect_signals(); if let Some(intent) = cell.take() { - app.process_session_intent(intent); + obj.process_session_intent(intent); } break; } } - }), - ); + } + )); self.imp() .intent_handler .set(session_list.upcast_ref(), vec![handler]); diff --git a/src/components/avatar/editable.rs b/src/components/avatar/editable.rs index 34d90c2b..1fec8eb1 100644 --- a/src/components/avatar/editable.rs +++ b/src/components/avatar/editable.rs @@ -213,9 +213,13 @@ mod imp { obj.set_edit_state(ActionState::Success); glib::timeout_add_local_once( Duration::from_secs(2), - clone!(@weak obj => move || { - obj.set_state(EditableAvatarState::Default); - }), + clone!( + #[weak] + obj, + move || { + obj.set_state(EditableAvatarState::Default); + } + ), ); } EditableAvatarState::RemovalInProgress => { diff --git a/src/components/avatar/image.rs b/src/components/avatar/image.rs index c19d7053..8ae9c4d7 100644 --- a/src/components/avatar/image.rs +++ b/src/components/avatar/image.rs @@ -150,12 +150,16 @@ impl AvatarImage { spawn!( glib::Priority::LOW, - clone!(@weak self as obj => async move { - match handle.await.unwrap() { - Ok(data) => obj.set_image_data(Some(data)), - Err(error) => error!("Could not fetch avatar: {error}"), - }; - }) + clone!( + #[weak(rename_to = obj)] + self, + async move { + match handle.await.unwrap() { + Ok(data) => obj.set_image_data(Some(data)), + Err(error) => error!("Could not fetch avatar: {error}"), + }; + } + ) ); } } diff --git a/src/components/avatar/overlapping.rs b/src/components/avatar/overlapping.rs index 5acf4808..2d5cdf25 100644 --- a/src/components/avatar/overlapping.rs +++ b/src/components/avatar/overlapping.rs @@ -214,11 +214,13 @@ impl OverlappingAvatars { return; }; - let signal_handler_id = model.connect_items_changed( - clone!(@weak self as obj => move |model, position, removed, added| { + let signal_handler_id = model.connect_items_changed(clone!( + #[weak(rename_to = obj)] + self, + move |model, position, removed, added| { obj.handle_items_changed(model, position, removed, added) - }), - ); + } + )); imp.bound_model .set(model.clone().upcast(), vec![signal_handler_id]); diff --git a/src/components/context_menu_bin.rs b/src/components/context_menu_bin.rs index 62d94acd..be49f6de 100644 --- a/src/components/context_menu_bin.rs +++ b/src/components/context_menu_bin.rs @@ -90,17 +90,22 @@ mod imp { fn constructed(&self) { let obj = self.obj(); - self.long_press_gesture - .connect_pressed(clone!(@weak obj => move |gesture, x, y| { + self.long_press_gesture.connect_pressed(clone!( + #[weak] + obj, + move |gesture, x, y| { if obj.has_context_menu() { gesture.set_state(gtk::EventSequenceState::Claimed); gesture.reset(); obj.open_menu_at(x as i32, y as i32); } - })); + } + )); - self.click_gesture.connect_released( - clone!(@weak obj => move |gesture, n_press, x, y| { + self.click_gesture.connect_released(clone!( + #[weak] + obj, + move |gesture, n_press, x, y| { if n_press > 1 { return; } @@ -109,8 +114,8 @@ mod imp { gesture.set_state(gtk::EventSequenceState::Claimed); obj.open_menu_at(x as i32, y as i32); } - }), - ); + } + )); self.parent_constructed(); } @@ -167,12 +172,18 @@ mod imp { popover.unparent(); popover.set_parent(&*obj); - let parent_handler = - popover.connect_parent_notify(clone!(@weak obj => move |popover| { - if !popover.parent().is_some_and(|w| &w == obj.upcast_ref::()) { + let parent_handler = popover.connect_parent_notify(clone!( + #[weak] + obj, + move |popover| { + if !popover + .parent() + .is_some_and(|w| &w == obj.upcast_ref::()) + { obj.imp().popover.disconnect_signals(); } - })); + } + )); self.popover.set(popover, vec![parent_handler]); } diff --git a/src/components/crypto/identity_setup_view.rs b/src/components/crypto/identity_setup_view.rs index 2ce4ec06..1e30fe17 100644 --- a/src/components/crypto/identity_setup_view.rs +++ b/src/components/crypto/identity_setup_view.rs @@ -115,9 +115,13 @@ mod imp { fn dispose(&self) { if let Some(verification) = self.verification.obj() { - spawn!(clone!(@strong verification => async move { - let _ = verification.cancel().await; - })); + spawn!(clone!( + #[strong] + verification, + async move { + let _ = verification.cancel().await; + } + )); } if let Some(session) = self.session.upgrade() { @@ -162,9 +166,13 @@ mod imp { let recovery_view = CryptoRecoverySetupView::new(&session); let obj = self.obj(); - recovery_view.connect_completed(clone!(@weak obj => move |_| { - obj.emit_completed(CryptoIdentitySetupNextStep::None); - })); + recovery_view.connect_completed(clone!( + #[weak] + obj, + move |_| { + obj.emit_completed(CryptoIdentitySetupNextStep::None); + } + )); recovery_view }) @@ -176,8 +184,10 @@ mod imp { // Use received verification requests too. let verification_list = session.verification_list(); - let verification_list_handler = verification_list.connect_items_changed( - clone!(@weak self as imp => move |verification_list, _, _, _| { + let verification_list_handler = verification_list.connect_items_changed(clone!( + #[weak(rename_to = imp)] + self, + move |verification_list, _, _, _| { if imp.verification.obj().is_some() { // We don't want to override the current verification. return; @@ -186,8 +196,8 @@ mod imp { if let Some(verification) = verification_list.ongoing_session_verification() { imp.set_verification(Some(verification)); } - }), - ); + } + )); self.verification_list_handler .replace(Some(verification_list_handler)); @@ -264,34 +274,47 @@ mod imp { if let Some(verification) = prev_verification { if !verification.is_finished() { - spawn!(clone!(@strong verification => async move { - let _ = verification.cancel().await; - })); + spawn!(clone!( + #[strong] + verification, + async move { + let _ = verification.cancel().await; + } + )); } self.verification.disconnect_signals(); } if let Some(verification) = &verification { - let replaced_handler = verification.connect_replaced( - clone!(@weak self as imp => move |_, new_verification| { + let replaced_handler = verification.connect_replaced(clone!( + #[weak(rename_to = imp)] + self, + move |_, new_verification| { imp.set_verification(Some(new_verification.clone())); - }), - ); - let done_handler = verification.connect_done( - clone!(@weak obj => @default-return glib::Propagation::Stop, move |verification| { + } + )); + let done_handler = verification.connect_done(clone!( + #[weak] + obj, + #[upgrade_or] + glib::Propagation::Stop, + move |verification| { obj.emit_completed(CryptoIdentitySetupNextStep::EnableRecovery); obj.imp().set_verification(None); verification.remove_from_list(); glib::Propagation::Stop - }), - ); - let remove_handler = - verification.connect_dismiss(clone!(@weak self as imp => move |_| { + } + )); + let remove_handler = verification.connect_dismiss(clone!( + #[weak(rename_to = imp)] + self, + move |_| { imp.navigation.pop(); imp.set_verification(None); - })); + } + )); self.verification.set( verification, @@ -328,9 +351,13 @@ mod imp { .tag(CryptoIdentitySetupPage::Recovery.as_ref()) .child(recovery_view) .build(); - page.connect_shown(clone!(@weak recovery_view => move |_| { - recovery_view.grab_focus(); - })); + page.connect_shown(clone!( + #[weak] + recovery_view, + move |_| { + recovery_view.grab_focus(); + } + )); page } diff --git a/src/components/dialogs/auth.rs b/src/components/dialogs/auth.rs index eec8eddf..5020c12d 100644 --- a/src/components/dialogs/auth.rs +++ b/src/components/dialogs/auth.rs @@ -94,10 +94,13 @@ mod imp { self.parent_constructed(); let obj = self.obj(); - self.password - .connect_changed(clone!(@weak obj => move |password| { + self.password.connect_changed(clone!( + #[weak] + obj, + move |password| { obj.set_response_enabled("confirm", !password.text().is_empty()); - })); + } + )); } } @@ -328,9 +331,10 @@ impl AuthDialog { "{homeserver}_matrix/client/r0/auth/{auth_type}/fallback/web?session={uiaa_session}" ); - let handler = imp - .open_browser_btn - .connect_clicked(clone!(@weak self as obj => move |_| { + let handler = imp.open_browser_btn.connect_clicked(clone!( + #[weak(rename_to = obj)] + self, + move |_| { let uri = uri.clone(); spawn!(async move { let Some(parent) = obj.parent() else { @@ -346,7 +350,8 @@ impl AuthDialog { obj.set_response_enabled("confirm", true); }); - })); + } + )); imp.open_browser_btn_handler.replace(Some(handler)); } diff --git a/src/components/dialogs/join_room.rs b/src/components/dialogs/join_room.rs index f8e15a8c..541cb066 100644 --- a/src/components/dialogs/join_room.rs +++ b/src/components/dialogs/join_room.rs @@ -110,11 +110,18 @@ mod imp { ) { obj.fill_details(); } else { - room.connect_loading_state_notify(clone!(@weak obj => move |room| { - if matches!(room.loading_state(), LoadingState::Ready | LoadingState::Error) { - obj.fill_details(); - } - })); + room.connect_loading_state_notify(clone!( + #[weak] + obj, + move |room| { + if matches!( + room.loading_state(), + LoadingState::Ready | LoadingState::Error + ) { + obj.fill_details(); + } + } + )); } } diff --git a/src/components/dialogs/user_profile.rs b/src/components/dialogs/user_profile.rs index 4edbd92f..961e9542 100644 --- a/src/components/dialogs/user_profile.rs +++ b/src/components/dialogs/user_profile.rs @@ -68,10 +68,14 @@ impl UserProfileDialog { let user = RemoteUser::new(session, user_id); imp.user_page.set_user(Some(user.clone())); - spawn!(clone!(@weak imp => async move { - user.load_profile().await; - imp.stack.set_visible_child_name("details"); - })); + spawn!(clone!( + #[weak] + imp, + async move { + user.load_profile().await; + imp.stack.set_visible_child_name("details"); + } + )); } /// Set the member to present. diff --git a/src/components/drag_overlay.rs b/src/components/drag_overlay.rs index ad425826..22708fa1 100644 --- a/src/components/drag_overlay.rs +++ b/src/components/drag_overlay.rs @@ -102,8 +102,10 @@ mod imp { } self.drop_target.disconnect_signals(); - let handler_id = drop_target.connect_current_drop_notify( - clone!(@weak self.revealer as revealer => move |target| { + let handler_id = drop_target.connect_current_drop_notify(clone!( + #[weak(rename_to = revealer)] + self.revealer, + move |target| { let reveal = target.current_drop().is_some(); if reveal { @@ -111,8 +113,8 @@ mod imp { } revealer.set_reveal_child(reveal); - }), - ); + } + )); obj.add_controller(drop_target.clone()); self.drop_target.set(drop_target, vec![handler_id]); diff --git a/src/components/media/content_viewer.rs b/src/components/media/content_viewer.rs index 08325532..da766e16 100644 --- a/src/components/media/content_viewer.rs +++ b/src/components/media/content_viewer.rs @@ -168,9 +168,13 @@ impl MediaContentViewer { pub fn view_file(&self, file: gio::File) { self.show_loading(); - spawn!(clone!(@weak self as obj => async move { - obj.view_file_inner(file).await; - })); + spawn!(clone!( + #[weak(rename_to = obj)] + self, + async move { + obj.view_file_inner(file).await; + } + )); } async fn view_file_inner(&self, file: gio::File) { diff --git a/src/components/media/image_paintable.rs b/src/components/media/image_paintable.rs index 28cddc13..18584ca2 100644 --- a/src/components/media/image_paintable.rs +++ b/src/components/media/image_paintable.rs @@ -359,10 +359,14 @@ impl ImagePaintable { self.invalidate_contents(); // Update the frame when the duration is elapsed. - let update_frame_callback = glib::clone!(@weak self as obj => move || { - obj.imp().timeout_source_id.take(); - obj.update_frame(); - }); + let update_frame_callback = glib::clone!( + #[weak(rename_to = obj)] + self, + move || { + obj.imp().timeout_source_id.take(); + obj.update_frame(); + } + ); let source_id = glib::timeout_add_local_once(next_frame.duration, update_frame_callback); imp.timeout_source_id.replace(Some(source_id)); diff --git a/src/components/media/video_player.rs b/src/components/media/video_player.rs index 6222efda..baec96b8 100644 --- a/src/components/media/video_player.rs +++ b/src/components/media/video_player.rs @@ -57,12 +57,19 @@ mod imp { self.parent_constructed(); let obj = self.obj(); - let bus_guard = self.player + let bus_guard = self + .player .message_bus() - .add_watch_local( - clone!(@weak obj => @default-return glib::ControlFlow::Break, move |_, message| { + .add_watch_local(clone!( + #[weak] + obj, + #[upgrade_or] + glib::ControlFlow::Break, + move |_, message| { match PlayMessage::parse(message) { - Ok(PlayMessage::DurationChanged { duration }) => obj.duration_changed(duration), + Ok(PlayMessage::DurationChanged { duration }) => { + obj.duration_changed(duration) + } Ok(PlayMessage::Warning { error, .. }) => { warn!("Warning playing video: {error}"); } @@ -73,8 +80,8 @@ mod imp { } glib::ControlFlow::Continue - }), - ) + } + )) .unwrap(); self.bus_guard.set(bus_guard).unwrap(); } diff --git a/src/components/offline_banner.rs b/src/components/offline_banner.rs index 49e537b5..b508087a 100644 --- a/src/components/offline_banner.rs +++ b/src/components/offline_banner.rs @@ -59,10 +59,13 @@ mod imp { self.session.disconnect_signals(); if let Some(session) = session { - let offline_handler = - session.connect_offline_notify(clone!(@weak self as imp => move |_| { + let offline_handler = session.connect_offline_notify(clone!( + #[weak(rename_to = imp)] + self, + move |_| { imp.update(); - })); + } + )); self.session.set(session, vec![offline_handler]); } @@ -83,10 +86,13 @@ mod imp { } let monitor = gio::NetworkMonitor::default(); - let monitor_handler = - monitor.connect_network_changed(clone!(@weak self as imp => move |_, _| { + let monitor_handler = monitor.connect_network_changed(clone!( + #[weak(rename_to = imp)] + self, + move |_, _| { imp.update(); - })); + } + )); self.monitor_handler.replace(Some(monitor_handler)); } diff --git a/src/components/pill/mod.rs b/src/components/pill/mod.rs index e462ae79..6820fc1b 100644 --- a/src/components/pill/mod.rs +++ b/src/components/pill/mod.rs @@ -97,11 +97,13 @@ mod imp { self.source.disconnect_signals(); if let Some(source) = source { - let display_name_handler = source.connect_disambiguated_name_notify( - clone!(@weak self as imp => move |source| { + let display_name_handler = source.connect_disambiguated_name_notify(clone!( + #[weak(rename_to = imp)] + self, + move |source| { imp.set_display_name(&source.disambiguated_name()); - }), - ); + } + )); self.set_display_name(&source.disambiguated_name()); self.source.set(source, vec![display_name_handler]); @@ -126,9 +128,13 @@ mod imp { if activatable { let gesture_click = gtk::GestureClick::new(); - gesture_click.connect_released(clone!(@weak obj => move |_, _, _, _| { - obj.activate(); - })); + gesture_click.connect_released(clone!( + #[weak] + obj, + move |_, _, _, _| { + obj.activate(); + } + )); obj.add_controller(gesture_click.clone()); self.gesture_click.replace(Some(gesture_click)); diff --git a/src/components/pill/search_entry.rs b/src/components/pill/search_entry.rs index c0c3f5cc..c3549ead 100644 --- a/src/components/pill/search_entry.rs +++ b/src/components/pill/search_entry.rs @@ -68,8 +68,10 @@ mod imp { self.parent_constructed(); let obj = self.obj(); - self.text_buffer - .connect_delete_range(clone!(@weak obj => move |_, start, end| { + self.text_buffer.connect_delete_range(clone!( + #[weak] + obj, + move |_, start, end| { if start == end { // Nothing to do. return; @@ -83,7 +85,12 @@ mod imp { .and_downcast_ref::() .and_then(|p| p.source()) { - let removed = obj.imp().pills.borrow_mut().remove(&source.identifier()).is_some(); + let removed = obj + .imp() + .pills + .borrow_mut() + .remove(&source.identifier()) + .is_some(); if removed { obj.emit_by_name::<()>("pill-removed", &[&source]); @@ -96,7 +103,8 @@ mod imp { break; } } - })); + } + )); self.text_buffer .connect_insert_text(|text_buffer, location, text| { @@ -121,10 +129,13 @@ mod imp { } }); - self.text_buffer - .connect_text_notify(clone!(@weak obj => move |_| { + self.text_buffer.connect_text_notify(clone!( + #[weak] + obj, + move |_| { obj.notify_text(); - })); + } + )); } } diff --git a/src/components/power_level_selection/popover.rs b/src/components/power_level_selection/popover.rs index b46515f4..4b23b5eb 100644 --- a/src/components/power_level_selection/popover.rs +++ b/src/components/power_level_selection/popover.rs @@ -84,24 +84,30 @@ mod imp { self.permissions.disconnect_signals(); if let Some(permissions) = permissions { - let own_pl_handler = permissions.connect_own_power_level_notify( - clone!(@weak self as imp => move |_| { + let own_pl_handler = permissions.connect_own_power_level_notify(clone!( + #[weak(rename_to = imp)] + self, + move |_| { imp.update(); - }), - ); - let default_pl_handler = permissions.connect_default_power_level_notify( - clone!(@weak self as imp => move |_| { + } + )); + let default_pl_handler = permissions.connect_default_power_level_notify(clone!( + #[weak(rename_to = imp)] + self, + move |_| { imp.update_default(); imp.update_muted(); imp.update_selection(); - }), - ); - let muted_pl_handler = permissions.connect_mute_power_level_notify( - clone!(@weak self as imp => move |_| { + } + )); + let muted_pl_handler = permissions.connect_mute_power_level_notify(clone!( + #[weak(rename_to = imp)] + self, + move |_| { imp.update_muted(); imp.update_selection(); - }), - ); + } + )); self.permissions.set( permissions, diff --git a/src/components/reaction_chooser.rs b/src/components/reaction_chooser.rs index 971d0955..354e6f0e 100644 --- a/src/components/reaction_chooser.rs +++ b/src/components/reaction_chooser.rs @@ -151,10 +151,13 @@ impl ReactionChooser { } if let Some(reactions) = reactions.as_ref() { - let signal_handler = - reactions.connect_items_changed(clone!(@weak self as obj => move |_, _, _, _| { + let signal_handler = reactions.connect_items_changed(clone!( + #[weak(rename_to = obj)] + self, + move |_, _, _, _| { obj.update_reactions(); - })); + } + )); imp.reactions_handler.replace(Some(signal_handler)); } imp.reactions.replace(reactions); diff --git a/src/components/rows/button_row.rs b/src/components/rows/button_row.rs index d1f31439..58fc0b2e 100644 --- a/src/components/rows/button_row.rs +++ b/src/components/rows/button_row.rs @@ -58,11 +58,15 @@ mod imp { self.obj().connect_parent_notify(|obj| { if let Some(listbox) = obj.parent().and_downcast_ref::() { - listbox.connect_row_activated(clone!(@weak obj => move |_, row| { - if row == obj.upcast_ref::() { - obj.emit_by_name::<()>("activated", &[]); + listbox.connect_row_activated(clone!( + #[weak] + obj, + move |_, row| { + if row == obj.upcast_ref::() { + obj.emit_by_name::<()>("activated", &[]); + } } - })); + )); } }); } diff --git a/src/components/rows/check_loading_row.rs b/src/components/rows/check_loading_row.rs index 01c7b064..abda1f73 100644 --- a/src/components/rows/check_loading_row.rs +++ b/src/components/rows/check_loading_row.rs @@ -51,12 +51,15 @@ mod imp { self.parent_constructed(); let obj = self.obj(); - self.check - .connect_active_notify(clone!(@weak obj => move |check| { - obj.update_state(&[gtk::accessible::State::Checked(bool_to_accessible_tristate( - check.is_active(), - ))]); - })); + self.check.connect_active_notify(clone!( + #[weak] + obj, + move |check| { + obj.update_state(&[gtk::accessible::State::Checked( + bool_to_accessible_tristate(check.is_active()), + )]); + } + )); obj.update_state(&[gtk::accessible::State::Checked( bool_to_accessible_tristate(self.check.is_active()), )]); diff --git a/src/components/rows/combo_loading_row.rs b/src/components/rows/combo_loading_row.rs index a6423df5..719d52b9 100644 --- a/src/components/rows/combo_loading_row.rs +++ b/src/components/rows/combo_loading_row.rs @@ -89,57 +89,68 @@ mod imp { self.list.bind_model( model.as_ref(), - clone!(@weak obj => @default-return { gtk::ListBoxRow::new().upcast() }, move |item| { - let Some(item) = item.downcast_ref::() else { - return gtk::ListBoxRow::new().upcast(); - }; - - let string = item.string(); - let child = gtk::Box::new(gtk::Orientation::Horizontal, 6); - - let label = gtk::Label::builder() - .xalign(0.0) - .ellipsize(pango::EllipsizeMode::End) - .max_width_chars(40) - .valign(gtk::Align::Center) - .label(string) - .build(); - child.append(&label); + clone!( + #[weak] + obj, + #[upgrade_or_else] + || { gtk::ListBoxRow::new().upcast() }, + move |item| { + let Some(item) = item.downcast_ref::() else { + return gtk::ListBoxRow::new().upcast(); + }; - let icon = gtk::Image::builder() - .accessible_role(gtk::AccessibleRole::Presentation) - .icon_name("object-select-symbolic") - .build(); + let string = item.string(); + let child = gtk::Box::new(gtk::Orientation::Horizontal, 6); + + let label = gtk::Label::builder() + .xalign(0.0) + .ellipsize(pango::EllipsizeMode::End) + .max_width_chars(40) + .valign(gtk::Align::Center) + .label(string) + .build(); + child.append(&label); + + let icon = gtk::Image::builder() + .accessible_role(gtk::AccessibleRole::Presentation) + .icon_name("object-select-symbolic") + .build(); + + let selected_handler = obj.connect_selected_string_notify(clone!( + #[weak] + label, + #[weak] + icon, + move |obj| { + let is_selected = + obj.selected_string().is_some_and(|s| s == label.label()); + let opacity = if is_selected { 1.0 } else { 0.0 }; + icon.set_opacity(opacity); + } + )); + obj.imp() + .selected_handlers + .borrow_mut() + .push(selected_handler); - let selected_handler = obj.connect_selected_string_notify(clone!(@weak label, @weak icon => move |obj| { let is_selected = obj.selected_string().is_some_and(|s| s == label.label()); - let opacity = if is_selected { - 1.0 - } else { - 0.0 - }; + let opacity = if is_selected { 1.0 } else { 0.0 }; icon.set_opacity(opacity); - })); - obj.imp().selected_handlers.borrow_mut().push(selected_handler); - - let is_selected = obj.selected_string().is_some_and(|s| s == label.label()); - let opacity = if is_selected { - 1.0 - } else { - 0.0 - }; - icon.set_opacity(opacity); - child.append(&icon); + child.append(&icon); - gtk::ListBoxRow::builder().child(&child).build().upcast() - }), + gtk::ListBoxRow::builder().child(&child).build().upcast() + } + ), ); if let Some(model) = model { - let items_changed_handler = - model.connect_items_changed(clone!(@weak self as imp => move |_, _, _, _| { + let items_changed_handler = model.connect_items_changed(clone!( + #[weak(rename_to = imp)] + self, + move |_, _, _, _| { imp.update_selected(); - })); + } + )); self.string_model.set(model, vec![items_changed_handler]); } diff --git a/src/components/rows/loading_row.rs b/src/components/rows/loading_row.rs index c0ecbfcf..fe4a408e 100644 --- a/src/components/rows/loading_row.rs +++ b/src/components/rows/loading_row.rs @@ -59,10 +59,13 @@ mod imp { self.parent_constructed(); let obj = self.obj(); - self.retry_button - .connect_clicked(clone!(@weak obj => move |_| { + self.retry_button.connect_clicked(clone!( + #[weak] + obj, + move |_| { obj.emit_by_name::<()>("retry", &[]); - })); + } + )); } } diff --git a/src/components/rows/substring_entry_row.rs b/src/components/rows/substring_entry_row.rs index 6f6a10cb..844ac7ed 100644 --- a/src/components/rows/substring_entry_row.rs +++ b/src/components/rows/substring_entry_row.rs @@ -134,11 +134,13 @@ mod imp { obj.init_delegate(); - self.text - .buffer() - .connect_length_notify(clone!(@weak obj => move |_| { + self.text.buffer().connect_length_notify(clone!( + #[weak] + obj, + move |_| { obj.notify_text_length(); - })); + } + )); } fn dispose(&self) { diff --git a/src/components/rows/switch_loading_row.rs b/src/components/rows/switch_loading_row.rs index 9b16acdf..71eb4271 100644 --- a/src/components/rows/switch_loading_row.rs +++ b/src/components/rows/switch_loading_row.rs @@ -52,13 +52,16 @@ mod imp { self.parent_constructed(); let obj = self.obj(); - self.switch - .connect_active_notify(clone!(@weak obj => move |switch| { - obj.update_state(&[gtk::accessible::State::Checked(bool_to_accessible_tristate( - switch.is_active(), - ))]); + self.switch.connect_active_notify(clone!( + #[weak] + obj, + move |switch| { + obj.update_state(&[gtk::accessible::State::Checked( + bool_to_accessible_tristate(switch.is_active()), + )]); obj.notify_is_active(); - })); + } + )); obj.update_state(&[gtk::accessible::State::Checked( bool_to_accessible_tristate(self.switch.is_active()), )]); diff --git a/src/components/scale_revealer.rs b/src/components/scale_revealer.rs index 66b66fd2..b004ed6c 100644 --- a/src/components/scale_revealer.rs +++ b/src/components/scale_revealer.rs @@ -44,26 +44,34 @@ mod imp { self.parent_constructed(); let obj = self.obj(); - let target = adw::CallbackAnimationTarget::new(clone!(@weak obj => move |_| { - obj.queue_draw(); - })); + let target = adw::CallbackAnimationTarget::new(clone!( + #[weak] + obj, + move |_| { + obj.queue_draw(); + } + )); let animation = adw::TimedAnimation::new(&*obj, 0.0, 1.0, ANIMATION_DURATION, target); animation.set_easing(adw::Easing::EaseOutQuart); - animation.connect_done(clone!(@weak obj => move |_| { - let imp = obj.imp(); - - if !imp.reveal_child.get() { - if let Some(source_widget) = imp.source_widget.upgrade() { - // Show the original source widget now that the - // transition is over. - source_widget.set_opacity(1.0); + animation.connect_done(clone!( + #[weak] + obj, + move |_| { + let imp = obj.imp(); + + if !imp.reveal_child.get() { + if let Some(source_widget) = imp.source_widget.upgrade() { + // Show the original source widget now that the + // transition is over. + source_widget.set_opacity(1.0); + } + obj.set_visible(false); } - obj.set_visible(false); - } - obj.emit_by_name::<()>("transition-done", &[]); - })); + obj.emit_by_name::<()>("transition-done", &[]); + } + )); self.animation.set(animation).unwrap(); obj.set_visible(false); diff --git a/src/components/user_page.rs b/src/components/user_page.rs index c823187f..aa3a0769 100644 --- a/src/components/user_page.rs +++ b/src/components/user_page.rs @@ -176,46 +176,65 @@ mod imp { .build(); let bindings = vec![title_binding, avatar_binding]; - let verified_handler = user.connect_verified_notify(clone!(@weak obj => move |_| { - obj.update_verified(); - })); - let ignored_handler = - user.connect_is_ignored_notify(clone!(@weak obj => move |_| { + let verified_handler = user.connect_verified_notify(clone!( + #[weak] + obj, + move |_| { + obj.update_verified(); + } + )); + let ignored_handler = user.connect_is_ignored_notify(clone!( + #[weak] + obj, + move |_| { obj.update_direct_chat(); obj.update_ignored(); - })); + } + )); let mut handlers = vec![verified_handler, ignored_handler]; if let Some(member) = user.downcast_ref::() { let room = member.room(); let permissions = room.permissions(); - let permissions_handler = - permissions.connect_changed(clone!(@weak obj => move |_| { + let permissions_handler = permissions.connect_changed(clone!( + #[weak] + obj, + move |_| { obj.update_room(); - })); + } + )); self.permissions_handler.replace(Some(permissions_handler)); self.power_level_row.set_permissions(Some(permissions)); - let room_display_name_handler = - room.connect_display_name_notify(clone!(@weak obj => move |_| { + let room_display_name_handler = room.connect_display_name_notify(clone!( + #[weak] + obj, + move |_| { obj.update_room(); - })); + } + )); self.room_display_name_handler .replace(Some(room_display_name_handler)); - let membership_handler = - member.connect_membership_notify(clone!(@weak obj => move |member| { + let membership_handler = member.connect_membership_notify(clone!( + #[weak] + obj, + move |member| { if member.membership() == Membership::Leave { obj.emit_by_name::<()>("close", &[]); } else { obj.update_room(); } - })); - let power_level_handler = - member.connect_power_level_notify(clone!(@weak obj => move |_| { + } + )); + let power_level_handler = member.connect_power_level_notify(clone!( + #[weak] + obj, + move |_| { obj.update_room(); - })); + } + )); handlers.extend([membership_handler, power_level_handler]); } diff --git a/src/contrib/qr_code_scanner/camera/camera_paintable/linux.rs b/src/contrib/qr_code_scanner/camera/camera_paintable/linux.rs index 75f74d23..ea9a9cf3 100644 --- a/src/contrib/qr_code_scanner/camera/camera_paintable/linux.rs +++ b/src/contrib/qr_code_scanner/camera/camera_paintable/linux.rs @@ -183,8 +183,8 @@ impl LinuxCameraPaintable { gst::Element::link_many([&queue2, &videoconvert2, &sink]).unwrap(); let bus = pipeline.bus().unwrap(); - let bus_guard = bus.add_watch_local( - clone!(@weak self as paintable => @default-return glib::ControlFlow::Break, move |_, msg| { + let bus_guard = bus + .add_watch_local(move |_, msg| { if let gst::MessageView::Error(err) = msg.view() { error!( "Error from {:?}: {} ({:?})", @@ -194,9 +194,8 @@ impl LinuxCameraPaintable { ); } glib::ControlFlow::Continue - }), - ) - .expect("Could not add bus watch"); + }) + .expect("Could not add bus watch"); let paintable = sink.property::("paintable"); @@ -224,13 +223,21 @@ impl LinuxCameraPaintable { fn set_sink_paintable(&self, paintable: gdk::Paintable) { let imp = self.imp(); - paintable.connect_invalidate_contents(clone!(@weak self as obj => move |_| { - obj.invalidate_contents(); - })); + paintable.connect_invalidate_contents(clone!( + #[weak(rename_to = obj)] + self, + move |_| { + obj.invalidate_contents(); + } + )); - paintable.connect_invalidate_size(clone!(@weak self as obj => move |_| { - obj.invalidate_size(); - })); + paintable.connect_invalidate_size(clone!( + #[weak(rename_to = obj)] + self, + move |_| { + obj.invalidate_size(); + } + )); imp.sink_paintable.replace(Some(paintable)); diff --git a/src/contrib/qr_code_scanner/mod.rs b/src/contrib/qr_code_scanner/mod.rs index 0b02f3d7..650e8b74 100644 --- a/src/contrib/qr_code_scanner/mod.rs +++ b/src/contrib/qr_code_scanner/mod.rs @@ -90,12 +90,22 @@ impl QrCodeScanner { imp.picture.set_paintable(Some(&paintable)); - let callback = glib::clone!(@weak self as obj => @default-return None, move |args: &[glib::Value]| { - let code = args.get(1).unwrap().get::().unwrap(); - obj.emit_by_name::<()>("code-detected", &[&code]); - - None - }); + let callback = glib::clone!( + #[weak(rename_to = obj)] + self, + #[upgrade_or] + None, + move |args: &[glib::Value]| { + let code = args + .get(1) + .unwrap() + .get::() + .unwrap(); + obj.emit_by_name::<()>("code-detected", &[&code]); + + None + } + ); let handler = paintable.connect_local("code-detected", false, callback); imp.handler.replace(Some(handler)); diff --git a/src/identity_verification_view/accept_request_page.rs b/src/identity_verification_view/accept_request_page.rs index 611b28e3..9a0e3592 100644 --- a/src/identity_verification_view/accept_request_page.rs +++ b/src/identity_verification_view/accept_request_page.rs @@ -87,12 +87,13 @@ mod imp { } if let Some(verification) = &verification { - let display_name_handler = - verification - .user() - .connect_display_name_notify(clone!(@weak obj => move |_| { - obj.update_labels(); - })); + let display_name_handler = verification.user().connect_display_name_notify(clone!( + #[weak] + obj, + move |_| { + obj.update_labels(); + } + )); self.display_name_handler .replace(Some(display_name_handler)); } diff --git a/src/identity_verification_view/cancelled_page.rs b/src/identity_verification_view/cancelled_page.rs index c5ee0e29..41c36a63 100644 --- a/src/identity_verification_view/cancelled_page.rs +++ b/src/identity_verification_view/cancelled_page.rs @@ -84,19 +84,23 @@ mod imp { self.verification.disconnect_signals(); if let Some(verification) = verification { - let display_name_handler = - verification - .user() - .connect_display_name_notify(clone!(@weak obj => move |_| { - obj.update_message(); - })); + let display_name_handler = verification.user().connect_display_name_notify(clone!( + #[weak] + obj, + move |_| { + obj.update_message(); + } + )); self.display_name_handler .replace(Some(display_name_handler)); - let cancel_info_changed_handler = - verification.connect_cancel_info_changed(clone!(@weak obj => move |_| { + let cancel_info_changed_handler = verification.connect_cancel_info_changed(clone!( + #[weak] + obj, + move |_| { obj.update_message(); - })); + } + )); self.verification .set(&verification, vec![cancel_info_changed_handler]); diff --git a/src/identity_verification_view/choose_method_page.rs b/src/identity_verification_view/choose_method_page.rs index 0c433743..fdbaeac0 100644 --- a/src/identity_verification_view/choose_method_page.rs +++ b/src/identity_verification_view/choose_method_page.rs @@ -104,19 +104,24 @@ mod imp { self.verification.disconnect_signals(); if let Some(verification) = &verification { - let display_name_handler = - verification - .user() - .connect_display_name_notify(clone!(@weak obj => move |_| { - obj.update_page(); - })); + let display_name_handler = verification.user().connect_display_name_notify(clone!( + #[weak] + obj, + move |_| { + obj.update_page(); + } + )); self.display_name_handler .replace(Some(display_name_handler)); let supported_methods_handler = - verification.connect_supported_methods_notify(clone!(@weak obj => move |_| { - obj.update_page(); - })); + verification.connect_supported_methods_notify(clone!( + #[weak] + obj, + move |_| { + obj.update_page(); + } + )); self.verification .set(verification, vec![supported_methods_handler]); diff --git a/src/identity_verification_view/completed_page.rs b/src/identity_verification_view/completed_page.rs index d9e3b217..940ee577 100644 --- a/src/identity_verification_view/completed_page.rs +++ b/src/identity_verification_view/completed_page.rs @@ -79,12 +79,13 @@ mod imp { } if let Some(verification) = &verification { - let display_name_handler = - verification - .user() - .connect_display_name_notify(clone!(@weak obj => move |_| { - obj.update_labels(); - })); + let display_name_handler = verification.user().connect_display_name_notify(clone!( + #[weak] + obj, + move |_| { + obj.update_labels(); + } + )); self.display_name_handler .replace(Some(display_name_handler)); } diff --git a/src/identity_verification_view/confirm_qr_code_page.rs b/src/identity_verification_view/confirm_qr_code_page.rs index 97f698f8..acb236db 100644 --- a/src/identity_verification_view/confirm_qr_code_page.rs +++ b/src/identity_verification_view/confirm_qr_code_page.rs @@ -85,12 +85,13 @@ mod imp { } if let Some(verification) = &verification { - let display_name_handler = - verification - .user() - .connect_display_name_notify(clone!(@weak obj => move |_| { - obj.update_labels(); - })); + let display_name_handler = verification.user().connect_display_name_notify(clone!( + #[weak] + obj, + move |_| { + obj.update_labels(); + } + )); self.display_name_handler .replace(Some(display_name_handler)); } diff --git a/src/identity_verification_view/mod.rs b/src/identity_verification_view/mod.rs index eacf765c..86b55126 100644 --- a/src/identity_verification_view/mod.rs +++ b/src/identity_verification_view/mod.rs @@ -84,14 +84,14 @@ mod imp { fn constructed(&self) { self.parent_constructed(); - self.main_stack.connect_transition_running_notify( - clone!(@weak self as imp => move |stack| - if !stack.is_transition_running() { - // Focus the default widget when the transition has ended. - imp.grab_focus(); - } - ), - ); + self.main_stack.connect_transition_running_notify(clone!( + #[weak(rename_to = imp)] + self, + move |stack| if !stack.is_transition_running() { + // Focus the default widget when the transition has ended. + imp.grab_focus(); + } + )); } } @@ -130,10 +130,13 @@ mod imp { self.verification.disconnect_signals(); if let Some(verification) = verification { - let state_handler = - verification.connect_state_notify(clone!(@weak obj => move |_| { + let state_handler = verification.connect_state_notify(clone!( + #[weak] + obj, + move |_| { obj.update_view(); - })); + } + )); verification.set_was_viewed(true); self.verification.set(verification, vec![state_handler]); diff --git a/src/identity_verification_view/no_supported_methods_page.rs b/src/identity_verification_view/no_supported_methods_page.rs index 9660b496..354d26ab 100644 --- a/src/identity_verification_view/no_supported_methods_page.rs +++ b/src/identity_verification_view/no_supported_methods_page.rs @@ -85,19 +85,23 @@ mod imp { self.verification.disconnect_signals(); if let Some(verification) = &verification { - let display_name_handler = - verification - .user() - .connect_display_name_notify(clone!(@weak obj => move |_| { - obj.update_page(); - })); + let display_name_handler = verification.user().connect_display_name_notify(clone!( + #[weak] + obj, + move |_| { + obj.update_page(); + } + )); self.display_name_handler .replace(Some(display_name_handler)); - let was_accepted_handler = - verification.connect_was_accepted_notify(clone!(@weak obj => move |_| { + let was_accepted_handler = verification.connect_was_accepted_notify(clone!( + #[weak] + obj, + move |_| { obj.update_page(); - })); + } + )); self.verification .set(verification, vec![was_accepted_handler]); diff --git a/src/identity_verification_view/qr_code_scanned_page.rs b/src/identity_verification_view/qr_code_scanned_page.rs index 1226d33f..da8b00b2 100644 --- a/src/identity_verification_view/qr_code_scanned_page.rs +++ b/src/identity_verification_view/qr_code_scanned_page.rs @@ -76,12 +76,13 @@ mod imp { } if let Some(verification) = &verification { - let display_name_handler = - verification - .user() - .connect_display_name_notify(clone!(@weak obj => move |_| { - obj.update_labels(); - })); + let display_name_handler = verification.user().connect_display_name_notify(clone!( + #[weak] + obj, + move |_| { + obj.update_labels(); + } + )); self.display_name_handler .replace(Some(display_name_handler)); } diff --git a/src/identity_verification_view/sas_page.rs b/src/identity_verification_view/sas_page.rs index 47a67a3c..3bd4d34f 100644 --- a/src/identity_verification_view/sas_page.rs +++ b/src/identity_verification_view/sas_page.rs @@ -94,20 +94,24 @@ mod imp { self.verification.disconnect_signals(); if let Some(verification) = &verification { - let display_name_handler = - verification - .user() - .connect_display_name_notify(clone!(@weak obj => move |_| { - obj.update_labels(); - })); + let display_name_handler = verification.user().connect_display_name_notify(clone!( + #[weak] + obj, + move |_| { + obj.update_labels(); + } + )); self.display_name_handler .replace(Some(display_name_handler)); - let sas_data_changed_handler = - verification.connect_sas_data_changed(clone!(@weak obj => move |_| { + let sas_data_changed_handler = verification.connect_sas_data_changed(clone!( + #[weak] + obj, + move |_| { obj.update_labels(); obj.fill_rows(); - })); + } + )); self.verification .set(verification, vec![sas_data_changed_handler]); diff --git a/src/identity_verification_view/scan_qr_code_page.rs b/src/identity_verification_view/scan_qr_code_page.rs index d90a6278..80c0f57d 100644 --- a/src/identity_verification_view/scan_qr_code_page.rs +++ b/src/identity_verification_view/scan_qr_code_page.rs @@ -64,10 +64,13 @@ mod imp { self.parent_constructed(); let obj = self.obj(); - self.qr_code_scanner - .connect_code_detected(clone!(@weak obj => move |_, data| { + self.qr_code_scanner.connect_code_detected(clone!( + #[weak] + obj, + move |_, data| { obj.code_detected(data); - })); + } + )); } fn dispose(&self) { @@ -83,9 +86,13 @@ mod imp { fn map(&self) { self.parent_map(); - spawn!(clone!(@weak self as imp => async move { - imp.qr_code_scanner.start().await; - })); + spawn!(clone!( + #[weak(rename_to = imp)] + self, + async move { + imp.qr_code_scanner.start().await; + } + )); } fn unmap(&self) { @@ -114,19 +121,24 @@ mod imp { self.verification.disconnect_signals(); if let Some(verification) = &verification { - let display_name_handler = - verification - .user() - .connect_display_name_notify(clone!(@weak obj => move |_| { - obj.update_labels(); - })); + let display_name_handler = verification.user().connect_display_name_notify(clone!( + #[weak] + obj, + move |_| { + obj.update_labels(); + } + )); self.display_name_handler .replace(Some(display_name_handler)); let supported_methods_handler = - verification.connect_supported_methods_notify(clone!(@weak obj => move |_| { - obj.update_page(); - })); + verification.connect_supported_methods_notify(clone!( + #[weak] + obj, + move |_| { + obj.update_page(); + } + )); self.verification .set(verification, vec![supported_methods_handler]); @@ -207,11 +219,15 @@ impl ScanQrCodePage { return; }; - spawn!(clone!(@weak self as obj => async move { - if verification.qr_code_scanned(data).await.is_err() { - toast!(obj, gettext("Could not validate scanned QR Code")); + spawn!(clone!( + #[weak(rename_to = obj)] + self, + async move { + if verification.qr_code_scanned(data).await.is_err() { + toast!(obj, gettext("Could not validate scanned QR Code")); + } } - })); + )); } /// Switch to the screen to scan a QR Code. diff --git a/src/identity_verification_view/wait_for_other_page.rs b/src/identity_verification_view/wait_for_other_page.rs index fcbf6e3d..8e1b008d 100644 --- a/src/identity_verification_view/wait_for_other_page.rs +++ b/src/identity_verification_view/wait_for_other_page.rs @@ -80,12 +80,13 @@ mod imp { } if let Some(verification) = &verification { - let display_name_handler = - verification - .user() - .connect_display_name_notify(clone!(@weak obj => move |_| { - obj.update_labels(); - })); + let display_name_handler = verification.user().connect_display_name_notify(clone!( + #[weak] + obj, + move |_| { + obj.update_labels(); + } + )); self.display_name_handler .replace(Some(display_name_handler)); } diff --git a/src/login/homeserver_page.rs b/src/login/homeserver_page.rs index 06157171..f34d804c 100644 --- a/src/login/homeserver_page.rs +++ b/src/login/homeserver_page.rs @@ -78,10 +78,14 @@ mod imp { self.login.disconnect_signals(); if let Some(login) = login { - let handler = login.connect_autodiscovery_notify(clone!(@weak obj => move |_| { - obj.update_next_state(); - obj.update_text(); - })); + let handler = login.connect_autodiscovery_notify(clone!( + #[weak] + obj, + move |_| { + obj.update_next_state(); + obj.update_text(); + } + )); self.login.set(login, vec![handler]); } diff --git a/src/login/idp_button.rs b/src/login/idp_button.rs index e72ff327..46133d60 100644 --- a/src/login/idp_button.rs +++ b/src/login/idp_button.rs @@ -109,8 +109,11 @@ mod imp { self.parent_constructed(); let obj = self.obj(); - adw::StyleManager::default() - .connect_dark_notify(clone!(@weak obj => move |_| obj.update_icon())); + adw::StyleManager::default().connect_dark_notify(clone!( + #[weak] + obj, + move |_| obj.update_icon() + )); obj.update_icon(); obj.set_tooltip_text(Some(&gettext_f( diff --git a/src/login/method_page.rs b/src/login/method_page.rs index 3dac30b8..52f6d84d 100644 --- a/src/login/method_page.rs +++ b/src/login/method_page.rs @@ -74,13 +74,20 @@ mod imp { self.login.disconnect_signals(); if let Some(login) = login { - let domain_handler = login.connect_domain_notify(clone!(@weak obj => move |_| { - obj.update_domain_name(); - })); - let login_types_handler = - login.connect_login_types_notify(clone!(@weak obj => move |_| { + let domain_handler = login.connect_domain_notify(clone!( + #[weak] + obj, + move |_| { + obj.update_domain_name(); + } + )); + let login_types_handler = login.connect_login_types_notify(clone!( + #[weak] + obj, + move |_| { obj.update_sso(); - })); + } + )); self.login .set(login, vec![domain_handler, login_types_handler]); diff --git a/src/login/mod.rs b/src/login/mod.rs index 0a1144b4..06176806 100644 --- a/src/login/mod.rs +++ b/src/login/mod.rs @@ -137,15 +137,22 @@ mod imp { self.parent_constructed(); let monitor = gio::NetworkMonitor::default(); - monitor.connect_network_changed(clone!(@weak obj => move |_, available| { - obj.action_set_enabled("login.sso", available); - })); + monitor.connect_network_changed(clone!( + #[weak] + obj, + move |_, available| { + obj.action_set_enabled("login.sso", available); + } + )); obj.action_set_enabled("login.sso", monitor.is_network_available()); - self.navigation - .connect_visible_page_notify(clone!(@weak obj => move |_| { + self.navigation.connect_visible_page_notify(clone!( + #[weak] + obj, + move |_| { obj.visible_page_changed(); - })); + } + )); } fn dispose(&self) { @@ -368,9 +375,13 @@ impl Login { .navigation .push_by_tag(LoginPage::Method.as_ref()); } else { - spawn!(clone!(@weak self as obj => async move { - obj.login_with_sso(None).await; - })); + spawn!(clone!( + #[weak(rename_to = obj)] + self, + async move { + obj.login_with_sso(None).await; + } + )); } } @@ -443,9 +454,13 @@ impl Login { let imp = self.imp(); let setup_view = SessionSetupView::new(&session); - setup_view.connect_completed(clone!(@weak imp => move |_| { - imp.navigation.push_by_tag(LoginPage::Completed.as_ref()); - })); + setup_view.connect_completed(clone!( + #[weak] + imp, + move |_| { + imp.navigation.push_by_tag(LoginPage::Completed.as_ref()); + } + )); imp.navigation.push(&setup_view); self.drop_client(); diff --git a/src/login/session_setup_view.rs b/src/login/session_setup_view.rs index b380132b..e1de36f6 100644 --- a/src/login/session_setup_view.rs +++ b/src/login/session_setup_view.rs @@ -122,13 +122,19 @@ mod imp { .expect("Session should still have a strong reference"); let crypto_identity_view = CryptoIdentitySetupView::new(&session); - crypto_identity_view.connect_completed(clone!(@weak self as imp => move |_, next| { - match next { - CryptoIdentitySetupNextStep::None => imp.obj().emit_completed(), - CryptoIdentitySetupNextStep::EnableRecovery => imp.check_recovery(true), - CryptoIdentitySetupNextStep::CompleteRecovery => imp.check_recovery(false), + crypto_identity_view.connect_completed(clone!( + #[weak(rename_to = imp)] + self, + move |_, next| { + match next { + CryptoIdentitySetupNextStep::None => imp.obj().emit_completed(), + CryptoIdentitySetupNextStep::EnableRecovery => imp.check_recovery(true), + CryptoIdentitySetupNextStep::CompleteRecovery => { + imp.check_recovery(false) + } + } } - })); + )); crypto_identity_view }) @@ -144,9 +150,13 @@ mod imp { let recovery_view = CryptoRecoverySetupView::new(&session); let obj = self.obj(); - recovery_view.connect_completed(clone!(@weak obj => move |_| { - obj.emit_completed(); - })); + recovery_view.connect_completed(clone!( + #[weak] + obj, + move |_| { + obj.emit_completed(); + } + )); recovery_view }) @@ -156,11 +166,15 @@ mod imp { fn set_session(&self, session: &Session) { self.session.set(Some(session)); - let ready_handler = session.connect_ready(clone!(@weak self as imp => move |_| { - spawn!(async move { - imp.load().await; - }); - })); + let ready_handler = session.connect_ready(clone!( + #[weak(rename_to = imp)] + self, + move |_| { + spawn!(async move { + imp.load().await; + }); + } + )); self.session_handler.replace(Some(ready_handler)); } @@ -195,11 +209,13 @@ mod imp { // Wait if we don't know the crypto identity state. let crypto_identity_state = session.crypto_identity_state(); if crypto_identity_state == CryptoIdentityState::Unknown { - let handler = session.connect_crypto_identity_state_notify( - clone!(@weak self as imp => move |_| { + let handler = session.connect_crypto_identity_state_notify(clone!( + #[weak(rename_to = imp)] + self, + move |_| { imp.check_session_setup(); - }), - ); + } + )); self.session_handler.replace(Some(handler)); return; } @@ -207,11 +223,13 @@ mod imp { // Wait if we don't know the verification state. let verification_state = session.verification_state(); if verification_state == SessionVerificationState::Unknown { - let handler = session.connect_verification_state_notify( - clone!(@weak self as imp => move |_| { + let handler = session.connect_verification_state_notify(clone!( + #[weak(rename_to = imp)] + self, + move |_| { imp.check_session_setup(); - }), - ); + } + )); self.session_handler.replace(Some(handler)); return; } @@ -219,10 +237,13 @@ mod imp { // Wait if we don't know the recovery state. let recovery_state = session.recovery_state(); if recovery_state == RecoveryState::Unknown { - let handler = - session.connect_recovery_state_notify(clone!(@weak self as imp => move |_| { + let handler = session.connect_recovery_state_notify(clone!( + #[weak(rename_to = imp)] + self, + move |_| { imp.check_session_setup(); - })); + } + )); self.session_handler.replace(Some(handler)); return; } diff --git a/src/session/model/ignored_users.rs b/src/session/model/ignored_users.rs index 1071f24d..3fec3719 100644 --- a/src/session/model/ignored_users.rs +++ b/src/session/model/ignored_users.rs @@ -104,9 +104,13 @@ mod imp { let abort_handle = spawn_tokio!(fut).abort_handle(); self.abort_handle.replace(Some(abort_handle)); - spawn!(clone!(@weak self as imp => async move { - imp.load_list().await; - })); + spawn!(clone!( + #[weak(rename_to = imp)] + self, + async move { + imp.load_list().await; + } + )); } /// Load the list from the store and update it. diff --git a/src/session/model/notifications/notifications_settings.rs b/src/session/model/notifications/notifications_settings.rs index b26718a3..1f3903ae 100644 --- a/src/session/model/notifications/notifications_settings.rs +++ b/src/session/model/notifications/notifications_settings.rs @@ -139,9 +139,13 @@ mod imp { self.session.set(session); obj.notify_session(); - spawn!(clone!(@weak obj => async move { - obj.init_api().await; - })); + spawn!(clone!( + #[weak] + obj, + async move { + obj.init_api().await; + } + )); } /// Set whether notifications are enabled for this session. @@ -190,11 +194,15 @@ impl NotificationsSettings { if session.state() != SessionState::Ready { self.imp().api.take(); - session.connect_ready(clone!(@weak self as obj => move |_| { - spawn!(async move { - obj.init_api().await; - }); - })); + session.connect_ready(clone!( + #[weak(rename_to = obj)] + self, + move |_| { + spawn!(async move { + obj.init_api().await; + }); + } + )); return; } @@ -227,10 +235,22 @@ impl NotificationsSettings { } }); - spawn!(clone!(@weak self as obj => async move { obj.update().await; })); + spawn!(clone!( + #[weak(rename_to = obj)] + self, + async move { + obj.update().await; + } + )); while let Some(()) = receiver.next().await { - spawn!(clone!(@weak self as obj => async move { obj.update().await; })); + spawn!(clone!( + #[weak(rename_to = obj)] + self, + async move { + obj.update().await; + } + )); } } diff --git a/src/session/model/remote_room.rs b/src/session/model/remote_room.rs index cbcb5a03..a8bd046a 100644 --- a/src/session/model/remote_room.rs +++ b/src/session/model/remote_room.rs @@ -188,9 +188,13 @@ impl RemoteRoom { imp.uri.set(uri).unwrap(); imp.update_display_name(); - spawn!(clone!(@weak obj => async move { - obj.load().await; - })); + spawn!(clone!( + #[weak] + obj, + async move { + obj.load().await; + } + )); obj } diff --git a/src/session/model/room/join_rule.rs b/src/session/model/room/join_rule.rs index 65eaea33..ffacd174 100644 --- a/src/session/model/room/join_rule.rs +++ b/src/session/model/room/join_rule.rs @@ -129,11 +129,13 @@ mod imp { return; }; - let own_membership_handler = - room.own_member() - .connect_membership_notify(clone!(@weak self as imp => move |_| { - imp.update_we_can_join(); - })); + let own_membership_handler = room.own_member().connect_membership_notify(clone!( + #[weak(rename_to = imp)] + self, + move |_| { + imp.update_we_can_join(); + } + )); self.own_membership_handler .replace(Some(own_membership_handler)); @@ -254,10 +256,13 @@ mod imp { RemoteRoom::new(&session, room_id.into()).upcast() }; - let display_name_handler = - room.connect_display_name_notify(clone!(@weak self as imp => move |_| { + let display_name_handler = room.connect_display_name_notify(clone!( + #[weak(rename_to = imp)] + self, + move |_| { imp.update_display_name(); - })); + } + )); self.membership_room.set(room, vec![display_name_handler]) } diff --git a/src/session/model/room/member.rs b/src/session/model/room/member.rs index 6cfefe4b..709a3c3e 100644 --- a/src/session/model/room/member.rs +++ b/src/session/model/room/member.rs @@ -103,16 +103,22 @@ mod imp { fn set_room(&self, room: Room) { let obj = self.obj(); - let default_pl_handler = room.permissions().connect_default_power_level_notify( - clone!(@weak obj => move |_| { - obj.update_role(); - }), - ); - let mute_pl_handler = - room.permissions() - .connect_mute_power_level_notify(clone!(@weak obj => move |_| { + let default_pl_handler = room + .permissions() + .connect_default_power_level_notify(clone!( + #[weak] + obj, + move |_| { obj.update_role(); - })); + } + )); + let mute_pl_handler = room.permissions().connect_mute_power_level_notify(clone!( + #[weak] + obj, + move |_| { + obj.update_role(); + } + )); self.power_level_handlers .replace(vec![default_pl_handler, mute_pl_handler]); @@ -201,9 +207,13 @@ impl Member { /// Update this member with the SDK's data. pub fn update(&self) { - spawn!(clone!(@weak self as obj => async move { - obj.update_inner().await; - })); + spawn!(clone!( + #[weak(rename_to = obj)] + self, + async move { + obj.update_inner().await; + } + )); } async fn update_inner(&self) { diff --git a/src/session/model/room/member_list.rs b/src/session/model/room/member_list.rs index 05e895a1..2de0cf1a 100644 --- a/src/session/model/room/member_list.rs +++ b/src/session/model/room/member_list.rs @@ -79,9 +79,13 @@ mod imp { spawn!( glib::Priority::LOW, - clone!(@weak obj => async move { - obj.load().await; - }) + clone!( + #[weak] + obj, + async move { + obj.load().await; + } + ) ); } } @@ -115,9 +119,13 @@ impl MemberList { pub fn reload(&self) { self.set_state(LoadingState::Initial); - spawn!(clone!(@weak self as obj => async move { - obj.load().await; - })); + spawn!(clone!( + #[weak(rename_to = obj)] + self, + async move { + obj.load().await; + } + )); } /// Load this list. diff --git a/src/session/model/room/mod.rs b/src/session/model/room/mod.rs index ad5bc2da..05b58d4b 100644 --- a/src/session/model/room/mod.rs +++ b/src/session/model/room/mod.rs @@ -344,15 +344,21 @@ mod imp { }); if let Some(verification) = &verification { - let state_handler = - verification.connect_is_finished_notify(clone!(@weak self as imp => move |_| { + let state_handler = verification.connect_is_finished_notify(clone!( + #[weak(rename_to = imp)] + self, + move |_| { imp.set_verification(None); - })); + } + )); - let dismiss_handler = - verification.connect_dismiss(clone!(@weak self as imp => move |_| { + let dismiss_handler = verification.connect_dismiss(clone!( + #[weak(rename_to = imp)] + self, + move |_| { imp.set_verification(None); - })); + } + )); self.verification .set(verification, vec![state_handler, dismiss_handler]); @@ -429,51 +435,79 @@ impl Room { spawn!( glib::Priority::DEFAULT_IDLE, - clone!(@weak self as obj => async move { - obj.load_display_name().await; - }) + clone!( + #[weak(rename_to = obj)] + self, + async move { + obj.load_display_name().await; + } + ) ); spawn!( glib::Priority::DEFAULT_IDLE, - clone!(@weak self as obj => async move { - obj.load_own_member().await; - }) + clone!( + #[weak(rename_to = obj)] + self, + async move { + obj.load_own_member().await; + } + ) ); spawn!( glib::Priority::DEFAULT_IDLE, - clone!(@weak self as obj => async move { - obj.load_is_direct().await; - }) + clone!( + #[weak(rename_to = obj)] + self, + async move { + obj.load_is_direct().await; + } + ) ); spawn!( glib::Priority::DEFAULT_IDLE, - clone!(@weak self as obj => async move { - obj.watch_room_info().await; - }) + clone!( + #[weak(rename_to = obj)] + self, + async move { + obj.watch_room_info().await; + } + ) ); spawn!( glib::Priority::DEFAULT_IDLE, - clone!(@weak self as obj => async move { - obj.load_inviter().await; - }) + clone!( + #[weak(rename_to = obj)] + self, + async move { + obj.load_inviter().await; + } + ) ); spawn!( glib::Priority::DEFAULT_IDLE, - clone!(@weak self as obj => async move { - obj.imp().permissions.init(&obj).await; - }) + clone!( + #[weak(rename_to = obj)] + self, + async move { + obj.imp().permissions.init(&obj).await; + } + ) ); spawn!( glib::Priority::DEFAULT_IDLE, - clone!(@weak self as obj => async move { - obj.imp().join_rule.init(&obj).await; - }) + clone!( + #[weak(rename_to = obj)] + self, + async move { + obj.imp().join_rule.init(&obj).await; + } + ) ); } @@ -481,21 +515,27 @@ impl Room { let timeline = Timeline::new(self); self.imp().timeline.set(timeline.clone()).unwrap(); - timeline - .sdk_items() - .connect_items_changed(clone!(@weak self as obj => move |_, _, _, _| { + timeline.sdk_items().connect_items_changed(clone!( + #[weak(rename_to = obj)] + self, + move |_, _, _, _| { spawn!(async move { obj.update_is_read().await; }); - })); + } + )); if !matches!(self.category(), RoomType::Left | RoomType::Outdated) { // Load the room history when idle. spawn!( glib::source::Priority::LOW, - clone!(@weak self as obj => async move { - obj.timeline().load().await; - }) + clone!( + #[weak(rename_to = obj)] + self, + async move { + obj.timeline().load().await; + } + ) ); } } @@ -524,9 +564,13 @@ impl Room { self.imp().is_direct.set(is_direct); self.notify_is_direct(); - spawn!(clone!(@weak self as obj => async move { - obj.load_direct_member().await; - })); + spawn!(clone!( + #[weak(rename_to = obj)] + self, + async move { + obj.load_direct_member().await; + } + )); } /// Load whether the room is direct or not. @@ -913,19 +957,23 @@ impl Room { spawn!( glib::Priority::DEFAULT_IDLE, - clone!(@weak self as obj => async move { - let mut category = RoomType::Normal; - - if let Ok(Some(tags)) = tags.await.unwrap() { - if tags.contains_key(&TagName::Favorite) { - category = RoomType::Favorite; - } else if tags.contains_key(&TagName::LowPriority) { - category = RoomType::LowPriority; + clone!( + #[weak(rename_to = obj)] + self, + async move { + let mut category = RoomType::Normal; + + if let Ok(Some(tags)) = tags.await.unwrap() { + if tags.contains_key(&TagName::Favorite) { + category = RoomType::Favorite; + } else if tags.contains_key(&TagName::LowPriority) { + category = RoomType::LowPriority; + } } - } - obj.set_category_internal(category); - }) + obj.set_category_internal(category); + } + ) ); } } @@ -1034,9 +1082,13 @@ impl Room { for (_event_id, receipts) in content.iter() { if let Some(users) = receipts.get(&ReceiptType::Read) { if users.contains_key(own_user_id) { - spawn!(clone!(@weak self as obj => async move { - obj.update_is_read().await; - })); + spawn!(clone!( + #[weak(rename_to = obj)] + self, + async move { + obj.update_is_read().await; + } + )); } } } @@ -1239,11 +1291,15 @@ impl Room { let inviter = Member::new(self, inviter_id); inviter.update_from_room_member(&inviter_member); - inviter.upcast_ref::().connect_is_ignored_notify( - clone!(@weak self as obj => move |_| { - obj.load_category(); - }), - ); + inviter + .upcast_ref::() + .connect_is_ignored_notify(clone!( + #[weak(rename_to = obj)] + self, + move |_| { + obj.load_category(); + } + )); self.imp().inviter.replace(Some(inviter)); @@ -1283,19 +1339,27 @@ impl Room { } // It might change the direct member. - spawn!(clone!(@weak self as obj => async move { - obj.load_direct_member().await; - obj.load_display_name().await; - })); + spawn!(clone!( + #[weak(rename_to = obj)] + self, + async move { + obj.load_direct_member().await; + obj.load_display_name().await; + } + )); } AnySyncStateEvent::RoomAvatar(SyncStateEvent::Original(_)) => { self.update_avatar(); } AnySyncStateEvent::RoomName(_) => { self.notify_name(); - spawn!(clone!(@weak self as obj => async move { - obj.load_display_name().await; - })); + spawn!(clone!( + #[weak(rename_to = obj)] + self, + async move { + obj.load_display_name().await; + } + )); } AnySyncStateEvent::RoomTopic(_) => { self.notify_topic(); @@ -1394,15 +1458,12 @@ impl Room { let matrix_room = matrix_room.clone(); let handle = spawn_tokio!(async move { matrix_room.typing_notice(is_typing).await }); - spawn!( - glib::Priority::DEFAULT_IDLE, - clone!(@weak self as obj => async move { - match handle.await.unwrap() { - Ok(_) => {}, - Err(error) => error!("Could not send typing notification: {error}"), - }; - }) - ); + spawn!(glib::Priority::DEFAULT_IDLE, async move { + match handle.await.unwrap() { + Ok(_) => {} + Err(error) => error!("Could not send typing notification: {error}"), + }; + }); } pub async fn accept_invite(&self) -> MatrixResult<()> { @@ -1466,9 +1527,13 @@ impl Room { } self.load_category(); - spawn!(clone!(@weak self as obj => async move { - obj.load_inviter().await; - })); + spawn!(clone!( + #[weak(rename_to = obj)] + self, + async move { + obj.load_inviter().await; + } + )); } pub fn handle_left_update(&self, update: LeftRoomUpdate) { @@ -1816,9 +1881,13 @@ impl Room { spawn!( glib::Priority::DEFAULT_IDLE, - clone!(@weak self as obj => async move { - obj.load_is_encrypted().await; - }) + clone!( + #[weak(rename_to = obj)] + self, + async move { + obj.load_is_encrypted().await; + } + ) ); } diff --git a/src/session/model/room/permissions.rs b/src/session/model/room/permissions.rs index d8ab13ea..29a4aef2 100644 --- a/src/session/model/room/permissions.rs +++ b/src/session/model/room/permissions.rs @@ -178,9 +178,13 @@ mod imp { impl Permissions { /// Initialize the room. pub(super) fn init_own_member(&self, own_member: Member) { - own_member.connect_membership_notify(clone!(@weak self as imp => move |_| { - imp.update_is_joined(); - })); + own_member.connect_membership_notify(clone!( + #[weak(rename_to = imp)] + self, + move |_| { + imp.update_is_joined(); + } + )); self.update_is_joined(); } diff --git a/src/session/model/room/timeline/mod.rs b/src/session/model/room/timeline/mod.rs index ec19cb73..d33a8d30 100644 --- a/src/session/model/room/timeline/mod.rs +++ b/src/session/model/room/timeline/mod.rs @@ -156,18 +156,24 @@ mod imp { self.room.set(room.as_ref()); if let Some(room) = room { - room.typing_list().connect_items_changed( - clone!(@weak obj => move |list, _, _, _| { + room.typing_list().connect_items_changed(clone!( + #[weak] + obj, + move |list, _, _, _| { if !list.is_empty() { obj.add_typing_row(); } - }), - ); + } + )); } - spawn!(clone!(@weak obj => async move { - obj.setup_timeline().await; - })); + spawn!(clone!( + #[weak] + obj, + async move { + obj.setup_timeline().await; + } + )); } /// Whether the timeline is empty. diff --git a/src/session/model/room_list/mod.rs b/src/session/model/room_list/mod.rs index 2adbce4e..0a2afa74 100644 --- a/src/session/model/room_list/mod.rs +++ b/src/session/model/room_list/mod.rs @@ -251,9 +251,13 @@ impl RoomList { let position = list.len().saturating_sub(added); for (_room_id, room) in list.iter().skip(position) { - room.connect_room_forgotten(clone!(@weak self as obj => move |room| { - obj.remove(room.room_id()); - })); + room.connect_room_forgotten(clone!( + #[weak(rename_to = obj)] + self, + move |room| { + obj.remove(room.room_id()); + } + )); } let mut to_remove = Vec::new(); diff --git a/src/session/model/session.rs b/src/session/model/session.rs index aba22ae3..82743c94 100644 --- a/src/session/model/session.rs +++ b/src/session/model/session.rs @@ -206,11 +206,15 @@ mod imp { self.user_sessions.init(&obj, obj.user_id().clone()); let monitor = gio::NetworkMonitor::default(); - let handler_id = monitor.connect_network_changed(clone!(@weak obj => move |_, _| { - spawn!(async move { - obj.update_offline().await; - }); - })); + let handler_id = monitor.connect_network_changed(clone!( + #[weak] + obj, + move |_, _| { + spawn!(async move { + obj.update_offline().await; + }); + } + )); self.offline_handler_id.replace(Some(handler_id)); } @@ -365,12 +369,16 @@ impl Session { pub async fn prepare(&self) { spawn!( glib::Priority::LOW, - clone!(@weak self as obj => async move { - // First, load the profile from the cache, it will be quicker. - obj.init_user_profile().await; - // Then, check if the profile changed. - obj.update_user_profile().await; - }) + clone!( + #[weak(rename_to = obj)] + self, + async move { + // First, load the profile from the cache, it will be quicker. + obj.init_user_profile().await; + // Then, check if the profile changed. + obj.update_user_profile().await; + } + ) ); self.update_offline().await; @@ -380,9 +388,13 @@ impl Session { self.init_verification_state(); self.init_recovery_state(); - spawn!(clone!(@weak self as obj => async move { - obj.init_crypto_identity_state().await; - })); + spawn!(clone!( + #[weak(rename_to = obj)] + self, + async move { + obj.init_crypto_identity_state().await; + } + )); self.set_state(SessionState::InitialSync); self.sync(); @@ -891,9 +903,13 @@ impl Session { spawn!( glib::Priority::LOW, - clone!(@strong self as obj => async move { - obj.clean_up().await; - }) + clone!( + #[strong(rename_to = obj)] + self, + async move { + obj.clean_up().await; + } + ) ); } diff --git a/src/session/model/sidebar_data/category/mod.rs b/src/session/model/sidebar_data/category/mod.rs index 444acbd2..12908d21 100644 --- a/src/session/model/sidebar_data/category/mod.rs +++ b/src/session/model/sidebar_data/category/mod.rs @@ -108,10 +108,14 @@ mod imp { model }; - model.connect_items_changed(clone!(@weak obj => move |model, pos, removed, added| { - obj.items_changed(pos, removed, added); - obj.imp().set_empty(model.n_items() == 0); - })); + model.connect_items_changed(clone!( + #[weak] + obj, + move |model, pos, removed, added| { + obj.items_changed(pos, removed, added); + obj.imp().set_empty(model.n_items() == 0); + } + )); self.set_empty(model.n_items() == 0); self.model.set(model).unwrap(); diff --git a/src/session/model/sidebar_data/item_list.rs b/src/session/model/sidebar_data/item_list.rs index 67037cb4..ba5f5a58 100644 --- a/src/session/model/sidebar_data/item_list.rs +++ b/src/session/model/sidebar_data/item_list.rs @@ -102,9 +102,13 @@ mod imp { for (pos, item) in list.iter().enumerate() { if let Some(category) = item.item.downcast_ref::() { - category.connect_empty_notify(clone!(@weak self as imp => move |_| { - imp.update_item_at(pos); - })); + category.connect_empty_notify(clone!( + #[weak(rename_to = imp)] + self, + move |_| { + imp.update_item_at(pos); + } + )); } self.update_item_at(pos); } diff --git a/src/session/model/sidebar_data/list_model.rs b/src/session/model/sidebar_data/list_model.rs index 1f9d1e7e..2740b201 100644 --- a/src/session/model/sidebar_data/list_model.rs +++ b/src/session/model/sidebar_data/list_model.rs @@ -60,29 +60,38 @@ mod imp { .build(); // When a verification is replaced, select the replacement automatically. - self.unfiltered_selection_model.connect_selected_item_notify( - clone!(@weak self as imp => move |selection_model| { - imp.selected_item.disconnect_signals(); - - if let Some(item) = &selection_model.selected_item() { - if let Some(verification) = item.downcast_ref::() { - let verification_handler = verification.connect_replaced( - clone!(@weak selection_model => move |_, new_verification| { - selection_model.set_selected_item(Some(new_verification.clone())); - }), - ); - imp.selected_item.set(item, vec![verification_handler]); + self.unfiltered_selection_model + .connect_selected_item_notify(clone!( + #[weak(rename_to = imp)] + self, + move |selection_model| { + imp.selected_item.disconnect_signals(); + + if let Some(item) = &selection_model.selected_item() { + if let Some(verification) = item.downcast_ref::() + { + let verification_handler = verification.connect_replaced(clone!( + #[weak] + selection_model, + move |_, new_verification| { + selection_model + .set_selected_item(Some(new_verification.clone())); + } + )); + imp.selected_item.set(item, vec![verification_handler]); + } } } - }), - ); + )); // Switch between the filtered and unfiltered list models. - self.string_filter.connect_search_notify( - clone!(@weak self as imp => move |string_filter| { + self.string_filter.connect_search_notify(clone!( + #[weak(rename_to = imp)] + self, + move |string_filter| { imp.set_is_filtered(string_filter.search().filter(|s| !s.is_empty()).is_some()); - }), - ); + } + )); } } diff --git a/src/session/model/sidebar_data/selection.rs b/src/session/model/sidebar_data/selection.rs index 7fcbb1b0..438586b5 100644 --- a/src/session/model/sidebar_data/selection.rs +++ b/src/session/model/sidebar_data/selection.rs @@ -93,10 +93,13 @@ mod imp { self.model.disconnect_signals(); if let Some(model) = model { - let items_changed_handler = - model.connect_items_changed(clone!(@weak obj => move |m, p, r, a| { + let items_changed_handler = model.connect_items_changed(clone!( + #[weak] + obj, + move |m, p, r, a| { obj.items_changed_cb(m, p, r, a); - })); + } + )); obj.items_changed_cb(&model, 0, n_items_before, model.n_items()); diff --git a/src/session/model/user.rs b/src/session/model/user.rs index d1b39faa..3e05c87b 100644 --- a/src/session/model/user.rs +++ b/src/session/model/user.rs @@ -109,8 +109,10 @@ mod imp { self.is_own_user.set(*session.user_id() == user_id); let ignored_users = session.ignored_users(); - let ignored_handler = ignored_users.connect_items_changed( - clone!(@weak self as imp => move |ignored_users, _, _, _| { + let ignored_handler = ignored_users.connect_items_changed(clone!( + #[weak(rename_to = imp)] + self, + move |ignored_users, _, _, _| { let user_id = imp.user_id.get().unwrap(); let is_ignored = ignored_users.contains(user_id); @@ -118,8 +120,8 @@ mod imp { imp.is_ignored.set(is_ignored); imp.obj().notify_is_ignored(); } - }), - ); + } + )); self.is_ignored.set(ignored_users.contains(&user_id)); self.ignored_handler.replace(Some(ignored_handler)); @@ -170,16 +172,20 @@ impl User { /// Load whether this user is verified. fn init_is_verified(&self) { - spawn!(clone!(@weak self as obj => async move { - let verified = obj.crypto_identity().await.is_some_and(|i| i.is_verified()); + spawn!(clone!( + #[weak(rename_to = obj)] + self, + async move { + let verified = obj.crypto_identity().await.is_some_and(|i| i.is_verified()); + + if verified == obj.verified() { + return; + } - if verified == obj.verified() { - return; + obj.imp().verified.set(verified); + obj.notify_verified(); } - - obj.imp().verified.set(verified); - obj.notify_verified(); - })); + )); } /// The existing direct chat with this user, if any. diff --git a/src/session/model/user_sessions_list/mod.rs b/src/session/model/user_sessions_list/mod.rs index 6b008bd8..dd6b8571 100644 --- a/src/session/model/user_sessions_list/mod.rs +++ b/src/session/model/user_sessions_list/mod.rs @@ -127,12 +127,22 @@ impl UserSessionsList { imp.session.set(Some(session)); imp.user_id.set(user_id).unwrap(); - spawn!(clone!(@weak self as obj => async move { - obj.load().await; - })); - spawn!(clone!(@weak self as obj, @weak session => async move { - obj.init_sessions_watch(session.client()).await; - })); + spawn!(clone!( + #[weak(rename_to = obj)] + self, + async move { + obj.load().await; + } + )); + spawn!(clone!( + #[weak(rename_to = obj)] + self, + #[weak] + session, + async move { + obj.init_sessions_watch(session.client()).await; + } + )); } /// Start listening to changes in the user sessions. diff --git a/src/session/model/verification/identity_verification.rs b/src/session/model/verification/identity_verification.rs index c37fd511..1fff6ee0 100644 --- a/src/session/model/verification/identity_verification.rs +++ b/src/session/model/verification/identity_verification.rs @@ -259,12 +259,16 @@ mod imp { if matches!(request.state(), VerificationRequestState::Requested { .. }) { let source_id = glib::timeout_add_local_once( REQUEST_RECEIVED_TIMEOUT, - clone!(@weak self as imp => move || { - imp.received_timeout_source.take(); - - imp.set_state(VerificationState::Dismissed); - imp.obj().dismiss(); - }), + clone!( + #[weak(rename_to = imp)] + self, + move || { + imp.received_timeout_source.take(); + + imp.set_state(VerificationState::Dismissed); + imp.obj().dismiss(); + } + ), ); self.received_timeout_source.replace(Some(source_id)); } @@ -280,10 +284,13 @@ mod imp { // to keep track of their name since it's used as the display name. if user.is::() { let obj = self.obj(); - let display_name_handler = - user.connect_display_name_notify(clone!(@weak obj => move |_| { + let display_name_handler = user.connect_display_name_notify(clone!( + #[weak] + obj, + move |_| { obj.notify_display_name(); - })); + } + )); handlers.push(display_name_handler); } @@ -297,18 +304,21 @@ mod imp { return; }; - let handler = room.own_member().connect_membership_notify( - clone!(@weak self as imp => move |own_member| { + let handler = room.own_member().connect_membership_notify(clone!( + #[weak(rename_to = imp)] + self, + move |own_member| { if matches!(own_member.membership(), Membership::Leave | Membership::Ban) { - // If the user is not in the room anymore, nothing can be done with this verification. + // If the user is not in the room anymore, nothing can be done with this + // verification. imp.set_state(VerificationState::RoomLeft); if let Some(handler) = imp.membership_handler.take() { own_member.disconnect(handler); } } - }), - ); + } + )); self.membership_handler.replace(Some(handler)); self.room.set(Some(room)); diff --git a/src/session/model/verification/verification_list.rs b/src/session/model/verification/verification_list.rs index e5ca99fa..1d04e933 100644 --- a/src/session/model/verification/verification_list.rs +++ b/src/session/model/verification/verification_list.rs @@ -268,9 +268,13 @@ impl VerificationList { return; } - verification.connect_remove_from_list(clone!(@weak self as obj => move |verification| { - obj.remove(&verification.key()); - })); + verification.connect_remove_from_list(clone!( + #[weak(rename_to = obj)] + self, + move |verification| { + obj.remove(&verification.key()); + } + )); let (pos, _) = imp.list.borrow_mut().insert_full(key, verification); diff --git a/src/session/view/account_settings/general_page/change_password_subpage.rs b/src/session/view/account_settings/general_page/change_password_subpage.rs index 31716176..778890fa 100644 --- a/src/session/view/account_settings/general_page/change_password_subpage.rs +++ b/src/session/view/account_settings/general_page/change_password_subpage.rs @@ -82,15 +82,22 @@ mod imp { self.password_progress .add_offset_value(gtk::LEVEL_BAR_OFFSET_FULL, 5.0); - self.password.connect_changed(clone!(@weak obj => move|_| { - obj.validate_password(); - obj.validate_password_confirmation(); - })); + self.password.connect_changed(clone!( + #[weak] + obj, + move |_| { + obj.validate_password(); + obj.validate_password_confirmation(); + } + )); - self.confirm_password - .connect_changed(clone!(@weak obj => move|_| { + self.confirm_password.connect_changed(clone!( + #[weak] + obj, + move |_| { obj.validate_password_confirmation(); - })); + } + )); } } diff --git a/src/session/view/account_settings/general_page/deactivate_account_subpage.rs b/src/session/view/account_settings/general_page/deactivate_account_subpage.rs index 7ffa0e53..0190e520 100644 --- a/src/session/view/account_settings/general_page/deactivate_account_subpage.rs +++ b/src/session/view/account_settings/general_page/deactivate_account_subpage.rs @@ -55,22 +55,32 @@ mod imp { self.parent_constructed(); let obj = self.obj(); - self.confirmation - .connect_entry_activated(clone!(@weak obj => move |_| { + self.confirmation.connect_entry_activated(clone!( + #[weak] + obj, + move |_| { spawn!(async move { obj.deactivate_account().await; }); - })); - self.confirmation - .connect_changed(clone!(@weak obj => move|_| { + } + )); + self.confirmation.connect_changed(clone!( + #[weak] + obj, + move |_| { obj.update_button(); - })); + } + )); - self.button.connect_clicked(clone!(@weak obj => move |_| { - spawn!(async move { - obj.deactivate_account().await; - }); - })); + self.button.connect_clicked(clone!( + #[weak] + obj, + move |_| { + spawn!(async move { + obj.deactivate_account().await; + }); + } + )); } } diff --git a/src/session/view/account_settings/general_page/mod.rs b/src/session/view/account_settings/general_page/mod.rs index 367d922c..d47424ab 100644 --- a/src/session/view/account_settings/general_page/mod.rs +++ b/src/session/view/account_settings/general_page/mod.rs @@ -116,25 +116,38 @@ mod imp { self.session_id.set_subtitle(session.device_id().as_str()); let user = session.user(); - let avatar_uri_handler = user.avatar_data().image().unwrap().connect_uri_notify( - clone!(@weak obj => move |avatar_image| { - obj.user_avatar_changed(avatar_image.uri()); - }), - ); + let avatar_uri_handler = + user.avatar_data() + .image() + .unwrap() + .connect_uri_notify(clone!( + #[weak] + obj, + move |avatar_image| { + obj.user_avatar_changed(avatar_image.uri()); + } + )); self.avatar_uri_handler.replace(Some(avatar_uri_handler)); - let display_name_handler = - user.connect_display_name_notify(clone!(@weak obj => move |user| { + let display_name_handler = user.connect_display_name_notify(clone!( + #[weak] + obj, + move |user| { obj.user_display_name_changed(user.display_name()); - })); + } + )); self.display_name_handler .replace(Some(display_name_handler)); spawn!( glib::Priority::LOW, - clone!(@weak self as imp => async move { - imp.load_can_change_password().await; - }) + clone!( + #[weak(rename_to = imp)] + self, + async move { + imp.load_can_change_password().await; + } + ) ); } diff --git a/src/session/view/account_settings/mod.rs b/src/session/view/account_settings/mod.rs index 32b008bd..c1cb81e5 100644 --- a/src/session/view/account_settings/mod.rs +++ b/src/session/view/account_settings/mod.rs @@ -120,9 +120,13 @@ mod imp { self.session.disconnect_signals(); if let Some(session) = session { - let logged_out_handler = session.connect_logged_out(clone!(@weak obj => move |_| { - obj.close(); - })); + let logged_out_handler = session.connect_logged_out(clone!( + #[weak] + obj, + move |_| { + obj.close(); + } + )); self.session.set(&session, vec![logged_out_handler]); } @@ -163,33 +167,49 @@ impl AccountSettings { } AccountSettingsSubpage::CryptoIdentitySetup => { let view = CryptoIdentitySetupView::new(&session); - view.connect_completed(clone!(@weak self as obj => move |_, _| { - obj.pop_subpage(); - })); + view.connect_completed(clone!( + #[weak(rename_to = obj)] + self, + move |_, _| { + obj.pop_subpage(); + } + )); let page = adw::NavigationPage::builder() .tag(AccountSettingsSubpage::CryptoIdentitySetup.as_ref()) .child(&view) .build(); - page.connect_shown(clone!(@weak view => move |_| { - view.grab_focus(); - })); + page.connect_shown(clone!( + #[weak] + view, + move |_| { + view.grab_focus(); + } + )); page } AccountSettingsSubpage::RecoverySetup => { let view = CryptoRecoverySetupView::new(&session); - view.connect_completed(clone!(@weak self as obj => move |_| { - obj.pop_subpage(); - })); + view.connect_completed(clone!( + #[weak(rename_to = obj)] + self, + move |_| { + obj.pop_subpage(); + } + )); let page = adw::NavigationPage::builder() .tag(AccountSettingsSubpage::RecoverySetup.as_ref()) .child(&view) .build(); - page.connect_shown(clone!(@weak view => move |_| { - view.grab_focus(); - })); + page.connect_shown(clone!( + #[weak] + view, + move |_| { + view.grab_focus(); + } + )); page } diff --git a/src/session/view/account_settings/notifications_page.rs b/src/session/view/account_settings/notifications_page.rs index 3d767a5b..b61ebf42 100644 --- a/src/session/view/account_settings/notifications_page.rs +++ b/src/session/view/account_settings/notifications_page.rs @@ -87,10 +87,13 @@ mod imp { self.parent_constructed(); let obj = self.obj(); - self.keywords_add_row - .connect_changed(clone!(@weak obj => move |_| { + self.keywords_add_row.connect_changed(clone!( + #[weak] + obj, + move |_| { obj.update_keywords(); - })); + } + )); } } @@ -111,18 +114,27 @@ mod imp { self.notifications_settings.disconnect_signals(); if let Some(settings) = notifications_settings { - let account_enabled_handler = - settings.connect_account_enabled_notify(clone!(@weak obj => move |_| { + let account_enabled_handler = settings.connect_account_enabled_notify(clone!( + #[weak] + obj, + move |_| { obj.update_account(); - })); - let session_enabled_handler = - settings.connect_session_enabled_notify(clone!(@weak obj => move |_| { + } + )); + let session_enabled_handler = settings.connect_session_enabled_notify(clone!( + #[weak] + obj, + move |_| { obj.update_session(); - })); - let global_setting_handler = - settings.connect_global_setting_notify(clone!(@weak obj => move |_| { + } + )); + let global_setting_handler = settings.connect_global_setting_notify(clone!( + #[weak] + obj, + move |_| { obj.update_global(); - })); + } + )); self.notifications_settings.set( settings, @@ -143,12 +155,24 @@ mod imp { let flattened_list = gtk::FlattenListModel::new(Some(all_items)); self.keywords.bind_model( Some(&flattened_list), - clone!(@weak obj => @default-return { adw::ActionRow::new().upcast() }, move |item| obj.create_keyword_row(item)), + clone!( + #[weak] + obj, + #[upgrade_or_else] + || { adw::ActionRow::new().upcast() }, + move |item| obj.create_keyword_row(item) + ), ); } else { self.keywords.bind_model( None::<&gio::ListModel>, - clone!(@weak obj => @default-return { adw::ActionRow::new().upcast() }, move |item| obj.create_keyword_row(item)), + clone!( + #[weak] + obj, + #[upgrade_or_else] + || { adw::ActionRow::new().upcast() }, + move |item| obj.create_keyword_row(item) + ), ); } @@ -176,9 +200,13 @@ mod imp { }; let obj = self.obj(); - spawn!(clone!(@weak obj => async move { - obj.global_setting_changed(default).await; - })); + spawn!(clone!( + #[weak] + obj, + async move { + obj.global_setting_changed(default).await; + } + )); } } } @@ -359,9 +387,13 @@ impl NotificationsPage { &[("keyword", &keyword)], ))); - row.connect_remove(clone!(@weak self as obj => move |row| { - obj.remove_keyword(row); - })); + row.connect_remove(clone!( + #[weak(rename_to = obj)] + self, + move |row| { + obj.remove_keyword(row); + } + )); row.upcast() } else { @@ -378,16 +410,19 @@ impl NotificationsPage { row.set_is_loading(true); - spawn!(clone!(@weak self as obj, @weak row => async move { - if settings.remove_keyword(row.title().into()).await.is_err() { - toast!( - obj, - gettext("Could not remove notification keyword") - ); - } + spawn!(clone!( + #[weak(rename_to = obj)] + self, + #[weak] + row, + async move { + if settings.remove_keyword(row.title().into()).await.is_err() { + toast!(obj, gettext("Could not remove notification keyword")); + } - row.set_is_loading(false); - })); + row.set_is_loading(false); + } + )); } /// Whether we can add the keyword that is currently in the entry. diff --git a/src/session/view/account_settings/security_page/ignored_users_subpage/mod.rs b/src/session/view/account_settings/security_page/ignored_users_subpage/mod.rs index 4b9360e6..40fa26ef 100644 --- a/src/session/view/account_settings/security_page/ignored_users_subpage/mod.rs +++ b/src/session/view/account_settings/security_page/ignored_users_subpage/mod.rs @@ -73,21 +73,25 @@ mod imp { self.filtered_model.set_filter(Some(&search_filter)); let factory = gtk::SignalListItemFactory::new(); - factory.connect_setup(clone!(@weak self as imp => move |_, item| { - let Some(session) = imp.session.upgrade() else { - return; - }; - let Some(item) = item.downcast_ref::() else { - error!("List item factory did not receive a list item: {item:?}"); - return; - }; - - let row = IgnoredUserRow::new(&session.ignored_users()); - item.set_child(Some(&row)); - item.bind_property("item", &row, "item").build(); - item.set_activatable(false); - item.set_selectable(false); - })); + factory.connect_setup(clone!( + #[weak(rename_to = imp)] + self, + move |_, item| { + let Some(session) = imp.session.upgrade() else { + return; + }; + let Some(item) = item.downcast_ref::() else { + error!("List item factory did not receive a list item: {item:?}"); + return; + }; + + let row = IgnoredUserRow::new(&session.ignored_users()); + item.set_child(Some(&row)); + item.bind_property("item", &row, "item").build(); + item.set_activatable(false); + item.set_selectable(false); + } + )); self.list_view.set_factory(Some(&factory)); self.list_view.set_model(Some(>k::NoSelection::new(Some( @@ -124,11 +128,13 @@ mod imp { let ignored_users = session.as_ref().map(|s| s.ignored_users()); if let Some(ignored_users) = &ignored_users { - let items_changed_handler = ignored_users.connect_items_changed( - clone!(@weak self as imp => move |_, _, _, _| { + let items_changed_handler = ignored_users.connect_items_changed(clone!( + #[weak(rename_to = imp)] + self, + move |_, _, _, _| { imp.update_visible_page(); - }), - ); + } + )); self.items_changed_handler .replace(Some(items_changed_handler)); } diff --git a/src/session/view/account_settings/security_page/mod.rs b/src/session/view/account_settings/security_page/mod.rs index cf14b2d3..0dd0f605 100644 --- a/src/session/view/account_settings/security_page/mod.rs +++ b/src/session/view/account_settings/security_page/mod.rs @@ -114,11 +114,14 @@ mod imp { if let Some(session) = &session { let ignored_users = session.ignored_users(); - let ignored_users_count_handler = ignored_users.connect_items_changed( - clone!(@weak self as imp => move |ignored_users, _, _, _| { - imp.ignored_users_row.set_count(ignored_users.n_items().to_string()); - }), - ); + let ignored_users_count_handler = ignored_users.connect_items_changed(clone!( + #[weak(rename_to = imp)] + self, + move |ignored_users, _, _, _| { + imp.ignored_users_row + .set_count(ignored_users.n_items().to_string()); + } + )); self.ignored_users_row .set_count(ignored_users.n_items().to_string()); @@ -146,17 +149,27 @@ mod imp { .replace(vec![public_read_receipts_binding, typing_binding]); let crypto_identity_state_handler = - session.connect_crypto_identity_state_notify(clone!(@weak obj => move |_| { - obj.update_crypto_identity(); - })); - let verification_state_handler = - session.connect_verification_state_notify(clone!(@weak obj => move |_| { + session.connect_crypto_identity_state_notify(clone!( + #[weak] + obj, + move |_| { + obj.update_crypto_identity(); + } + )); + let verification_state_handler = session.connect_verification_state_notify(clone!( + #[weak] + obj, + move |_| { obj.update_crypto_identity(); - })); - let recovery_state_handler = - session.connect_recovery_state_notify(clone!(@weak obj => move |_| { + } + )); + let recovery_state_handler = session.connect_recovery_state_notify(clone!( + #[weak] + obj, + move |_| { obj.update_recovery(); - })); + } + )); self.session.set( session, diff --git a/src/session/view/account_settings/user_sessions_page/mod.rs b/src/session/view/account_settings/user_sessions_page/mod.rs index 4049ef96..d23ed3d9 100644 --- a/src/session/view/account_settings/user_sessions_page/mod.rs +++ b/src/session/view/account_settings/user_sessions_page/mod.rs @@ -101,30 +101,40 @@ mod imp { UserSessionRow::new(user_session).upcast() }); - let other_sessions_handler = other_sessions.connect_items_changed( - clone!(@weak self as imp => move |other_sessions, _, _, _| { - imp.other_sessions_group.set_visible(other_sessions.n_items() > 0); - }), - ); + let other_sessions_handler = other_sessions.connect_items_changed(clone!( + #[weak(rename_to = imp)] + self, + move |other_sessions, _, _, _| { + imp.other_sessions_group + .set_visible(other_sessions.n_items() > 0); + } + )); self.other_sessions_handler .replace(Some(other_sessions_handler)); self.other_sessions_group .set_visible(other_sessions.n_items() > 0); - let loading_state_handler = user_sessions.connect_loading_state_notify( - clone!(@weak self as imp => move |_| { + let loading_state_handler = user_sessions.connect_loading_state_notify(clone!( + #[weak(rename_to = imp)] + self, + move |_| { imp.update_state(); - }), - ); - let is_empty_handler = - user_sessions.connect_is_empty_notify(clone!(@weak self as imp => move |_| { + } + )); + let is_empty_handler = user_sessions.connect_is_empty_notify(clone!( + #[weak(rename_to = imp)] + self, + move |_| { imp.update_state(); - })); - let current_session_handler = user_sessions.connect_current_session_notify( - clone!(@weak self as imp => move |_| { + } + )); + let current_session_handler = user_sessions.connect_current_session_notify(clone!( + #[weak(rename_to = imp)] + self, + move |_| { imp.update_current_session(); - }), - ); + } + )); self.user_sessions.set( user_sessions, diff --git a/src/session/view/account_settings/user_sessions_page/user_session_row.rs b/src/session/view/account_settings/user_sessions_page/user_session_row.rs index 1e0d0cce..af54951a 100644 --- a/src/session/view/account_settings/user_sessions_page/user_session_row.rs +++ b/src/session/view/account_settings/user_sessions_page/user_session_row.rs @@ -64,10 +64,13 @@ mod imp { let obj = self.obj(); let system_settings = Application::default().system_settings(); - let system_settings_handler = - system_settings.connect_clock_format_notify(clone!(@weak obj => move |_| { + let system_settings_handler = system_settings.connect_clock_format_notify(clone!( + #[weak] + obj, + move |_| { obj.update_last_seen_ts(); - })); + } + )); self.system_settings_handler .replace(Some(system_settings_handler)); } diff --git a/src/session/view/content/explore/mod.rs b/src/session/view/content/explore/mod.rs index ca75fb5e..6efc4a9b 100644 --- a/src/session/view/content/explore/mod.rs +++ b/src/session/view/content/explore/mod.rs @@ -74,27 +74,36 @@ mod imp { let obj = self.obj(); let adj = self.scrolled_window.vadjustment(); - adj.connect_value_changed(clone!(@weak self as imp => move |adj| { - if adj.upper() - adj.value() < adj.page_size() * 2.0 { - if let Some(public_room_list) = &*imp.public_room_list.borrow() { - public_room_list.load_public_rooms(false); + adj.connect_value_changed(clone!( + #[weak(rename_to = imp)] + self, + move |adj| { + if adj.upper() - adj.value() < adj.page_size() * 2.0 { + if let Some(public_room_list) = &*imp.public_room_list.borrow() { + public_room_list.load_public_rooms(false); + } } } - })); + )); - self.search_entry - .connect_search_changed(clone!(@weak obj => move |_| { + self.search_entry.connect_search_changed(clone!( + #[weak] + obj, + move |_| { obj.trigger_search(); - })); + } + )); - self.servers_popover.connect_selected_server_changed( - clone!(@weak obj => move |_, server| { + self.servers_popover.connect_selected_server_changed(clone!( + #[weak] + obj, + move |_, server| { if let Some(server) = server { obj.imp().servers_button.set_label(&server.name()); obj.trigger_search(); } - }), - ); + } + )); } } @@ -114,13 +123,21 @@ mod imp { self.listview .set_model(Some(>k::NoSelection::new(Some(public_room_list.clone())))); - public_room_list.connect_loading_notify(clone!(@weak obj => move |_| { - obj.update_visible_child(); - })); + public_room_list.connect_loading_notify(clone!( + #[weak] + obj, + move |_| { + obj.update_visible_child(); + } + )); - public_room_list.connect_empty_notify(clone!(@weak obj => move |_| { - obj.update_visible_child(); - })); + public_room_list.connect_empty_notify(clone!( + #[weak] + obj, + move |_| { + obj.update_visible_child(); + } + )); self.public_room_list.replace(Some(public_room_list)); obj.update_visible_child(); diff --git a/src/session/view/content/explore/public_room.rs b/src/session/view/content/explore/public_room.rs index 6d8c35d8..8bf43951 100644 --- a/src/session/view/content/explore/public_room.rs +++ b/src/session/view/content/explore/public_room.rs @@ -58,15 +58,20 @@ mod imp { self.avatar_data.set(avatar_data).unwrap(); - obj.room_list() - .connect_pending_rooms_changed(clone!(@weak obj => move |_| { + obj.room_list().connect_pending_rooms_changed(clone!( + #[weak] + obj, + move |_| { let Some(matrix_public_room) = obj.matrix_public_room() else { return; }; - obj.set_pending(obj.room_list() - .is_pending_room((*matrix_public_room.room_id).into())); - })); + obj.set_pending( + obj.room_list() + .is_pending_room((*matrix_public_room.room_id).into()), + ); + } + )); } fn dispose(&self) { @@ -121,16 +126,18 @@ impl PublicRoom { self.set_room(room); } else { let room_id = room.room_id.clone(); - let handler_id = self.room_list().connect_items_changed( - clone!(@weak self as obj => move |room_list, _, _, _| { + let handler_id = self.room_list().connect_items_changed(clone!( + #[weak(rename_to = obj)] + self, + move |room_list, _, _, _| { if let Some(room) = room_list.get(&room_id) { if let Some(handler_id) = obj.imp().room_handler.take() { obj.set_room(room); room_list.disconnect(handler_id); } } - }), - ); + } + )); imp.room_handler.replace(Some(handler_id)); } diff --git a/src/session/view/content/explore/public_room_list.rs b/src/session/view/content/explore/public_room_list.rs index 39e174a2..e82116d7 100644 --- a/src/session/view/content/explore/public_room_list.rs +++ b/src/session/view/content/explore/public_room_list.rs @@ -259,18 +259,22 @@ impl PublicRoomList { spawn!( glib::Priority::DEFAULT_IDLE, - 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 handle.await.unwrap() { - Ok(response) => obj.handle_public_rooms_response(response), - Err(error) => { - obj.set_request_sent(false); - error!("Error loading public rooms: {error}") - }, + clone!( + #[weak(rename_to = obj)] + self, + async move { + // If the search term changed we ignore the response + if obj.is_valid_response(current_search_term, current_server, current_network) { + match handle.await.unwrap() { + Ok(response) => obj.handle_public_rooms_response(response), + Err(error) => { + obj.set_request_sent(false); + error!("Error loading public rooms: {error}") + } + } } } - }) + ) ); } } diff --git a/src/session/view/content/explore/public_room_row.rs b/src/session/view/content/explore/public_room_row.rs index 1acae1fe..b954fbaa 100644 --- a/src/session/view/content/explore/public_room_row.rs +++ b/src/session/view/content/explore/public_room_row.rs @@ -63,10 +63,13 @@ mod imp { impl ObjectImpl for PublicRoomRow { fn constructed(&self) { self.parent_constructed(); - self.button - .connect_clicked(clone!(@weak self as imp => move |_| { + self.button.connect_clicked(clone!( + #[weak(rename_to = imp)] + self, + move |_| { imp.obj().join_or_view(); - })); + } + )); } } @@ -89,14 +92,20 @@ mod imp { } if public_room.matrix_public_room().is_some() { - let pending_handler = - public_room.connect_pending_notify(clone!(@weak self as imp => move |_| { + let pending_handler = public_room.connect_pending_notify(clone!( + #[weak(rename_to = imp)] + self, + move |_| { imp.update_button(); - })); - let room_handler = - public_room.connect_room_notify(clone!(@weak self as imp => move |_| { + } + )); + let room_handler = public_room.connect_room_notify(clone!( + #[weak(rename_to = imp)] + self, + move |_| { imp.update_button(); - })); + } + )); self.public_room .set(public_room, vec![pending_handler, room_handler]); @@ -225,11 +234,15 @@ impl PublicRoomRow { (id, via) }); - spawn!(clone!(@weak self as obj => async move { - if let Err(error) = room_list.join_by_id_or_alias(room_id, via).await { - toast!(obj, error); + spawn!(clone!( + #[weak(rename_to = obj)] + self, + async move { + if let Err(error) = room_list.join_by_id_or_alias(room_id, via).await { + toast!(obj, error); + } } - })); + )); } } } diff --git a/src/session/view/content/explore/server_list.rs b/src/session/view/content/explore/server_list.rs index c8935fbb..0ddb372f 100644 --- a/src/session/view/content/explore/server_list.rs +++ b/src/session/view/content/explore/server_list.rs @@ -60,9 +60,13 @@ mod imp { )]); obj.items_changed(0, 0, 1); - spawn!(clone!(@weak obj => async move { - obj.load_servers().await; - })); + spawn!(clone!( + #[weak] + obj, + async move { + obj.load_servers().await; + } + )); } } } diff --git a/src/session/view/content/explore/servers_popover.rs b/src/session/view/content/explore/servers_popover.rs index a48e7d0b..4ce32468 100644 --- a/src/session/view/content/explore/servers_popover.rs +++ b/src/session/view/content/explore/servers_popover.rs @@ -62,14 +62,16 @@ mod imp { self.parent_constructed(); let obj = self.obj(); - self.server_entry - .connect_changed(clone!(@weak obj => move |_| { - obj.update_add_server_state() - })); - self.server_entry - .connect_activate(clone!(@weak obj => move |_| { - obj.add_server() - })); + self.server_entry.connect_changed(clone!( + #[weak] + obj, + move |_| obj.update_add_server_state() + )); + self.server_entry.connect_activate(clone!( + #[weak] + obj, + move |_| obj.add_server() + )); obj.update_add_server_state(); } @@ -135,11 +137,17 @@ impl ExploreServersPopover { &self, f: F, ) -> glib::SignalHandlerId { - self.imp() - .listbox - .connect_row_selected(clone!(@weak self as obj => move |_, row| { - f(&obj, row.and_then(|row| row.downcast_ref::()).and_then(|row| row.server())); - })) + self.imp().listbox.connect_row_selected(clone!( + #[weak(rename_to = obj)] + self, + move |_, row| { + f( + &obj, + row.and_then(|row| row.downcast_ref::()) + .and_then(|row| row.server()), + ); + } + )) } /// Whether the server currently in the text entry can be added. diff --git a/src/session/view/content/invite.rs b/src/session/view/content/invite.rs index 33f2ec86..b84a65c0 100644 --- a/src/session/view/content/invite.rs +++ b/src/session/view/content/invite.rs @@ -125,18 +125,22 @@ mod imp { } if let Some(room) = &room { - let category_handler = room.connect_category_notify( - clone!(@weak obj => move |room| { + let category_handler = room.connect_category_notify(clone!( + #[weak] + obj, + move |room| { let category = room.category(); if category == RoomType::Left { - // We declined the invite or the invite was retracted, we should close the room - // if it is opened. + // We declined the invite or the invite was retracted, we should close + // the room if it is opened. let Some(session) = room.session() else { return; }; let selection = session.sidebar_list_model().selection_model(); - if let Some(selected_room) = selection.selected_item().and_downcast::() { + if let Some(selected_room) = + selection.selected_item().and_downcast::() + { if selected_room == *room { selection.set_selected_item(None::); } @@ -152,8 +156,8 @@ mod imp { room.disconnect(category_handler); } } - }), - ); + } + )); self.category_handler.replace(Some(category_handler)); } diff --git a/src/session/view/content/mod.rs b/src/session/view/content/mod.rs index c57a43a5..7624c40f 100644 --- a/src/session/view/content/mod.rs +++ b/src/session/view/content/mod.rs @@ -91,12 +91,16 @@ mod imp { fn constructed(&self) { self.parent_constructed(); - self.stack - .connect_visible_child_notify(clone!(@weak self as imp => move |_| { + self.stack.connect_visible_child_notify(clone!( + #[weak(rename_to = imp)] + self, + move |_| { if imp.visible_page() != ContentPage::Verification { - imp.identity_verification_widget.set_verification(None::); + imp.identity_verification_widget + .set_verification(None::); } - })); + } + )); if let Some(binding) = self.item_binding.take() { binding.unbind() @@ -163,15 +167,23 @@ mod imp { if let Some(item) = &item { if let Some(room) = item.downcast_ref::() { - let handler_id = room.connect_category_notify(clone!(@weak obj => move |_| { - obj.update_visible_child(); - })); + let handler_id = room.connect_category_notify(clone!( + #[weak] + obj, + move |_| { + obj.update_visible_child(); + } + )); self.signal_handler.replace(Some(handler_id)); } else if let Some(verification) = item.downcast_ref::() { - let handler_id = verification.connect_dismiss(clone!(@weak obj => move |_| { - obj.set_item(None::); - })); + let handler_id = verification.connect_dismiss(clone!( + #[weak] + obj, + move |_| { + obj.set_item(None::); + } + )); self.signal_handler.replace(Some(handler_id)); } } diff --git a/src/session/view/content/room_details/addresses_subpage/completion_popover.rs b/src/session/view/content/room_details/addresses_subpage/completion_popover.rs index e2927e6c..8490ec32 100644 --- a/src/session/view/content/room_details/addresses_subpage/completion_popover.rs +++ b/src/session/view/content/room_details/addresses_subpage/completion_popover.rs @@ -64,10 +64,13 @@ mod imp { .set_expression(Some(gtk::StringObject::this_expression("string"))); self.filtered_list.set_filter(Some(&self.filter)); - self.filtered_list - .connect_items_changed(clone!(@weak obj => move |_,_,_,_| { + self.filtered_list.connect_items_changed(clone!( + #[weak] + obj, + move |_, _, _, _| { obj.update_completion(); - })); + } + )); self.list.bind_model(Some(&self.filtered_list), |item| { let Some(item) = item.downcast_ref::() else { @@ -125,46 +128,55 @@ mod imp { if let Some(entry) = entry { let key_events = gtk::EventControllerKey::new(); - key_events.connect_key_pressed(clone!(@weak obj => @default-return glib::Propagation::Proceed, move |_, key, _, modifier| { - if modifier.is_empty() { - if obj.is_visible() { - let imp = obj.imp(); - if matches!(key, gdk::Key::Return | gdk::Key::KP_Enter | gdk::Key::ISO_Enter) { - // Activate completion. - obj.activate_selected_row(); - return glib::Propagation::Stop; - } else if matches!(key, gdk::Key::Up | gdk::Key::KP_Up) { - // Move up, if possible. - let idx = obj.selected_row_index().unwrap_or_default(); - if idx > 0 { - obj.select_row_at_index(Some(idx - 1)); + key_events.connect_key_pressed(clone!( + #[weak] + obj, + #[upgrade_or] + glib::Propagation::Proceed, + move |_, key, _, modifier| { + if modifier.is_empty() { + if obj.is_visible() { + let imp = obj.imp(); + if matches!( + key, + gdk::Key::Return | gdk::Key::KP_Enter | gdk::Key::ISO_Enter + ) { + // Activate completion. + obj.activate_selected_row(); + return glib::Propagation::Stop; + } else if matches!(key, gdk::Key::Up | gdk::Key::KP_Up) { + // Move up, if possible. + let idx = obj.selected_row_index().unwrap_or_default(); + if idx > 0 { + obj.select_row_at_index(Some(idx - 1)); + } + return glib::Propagation::Stop; + } else if matches!(key, gdk::Key::Down | gdk::Key::KP_Down) { + // Move down, if possible. + let new_idx = if let Some(idx) = obj.selected_row_index() { + idx + 1 + } else { + 0 + }; + let max = imp.filtered_list.n_items() as usize; + + if new_idx < max { + obj.select_row_at_index(Some(new_idx)); + } + return glib::Propagation::Stop; + } else if matches!(key, gdk::Key::Escape) { + // Close. + obj.popdown(); + return glib::Propagation::Stop; } - return glib::Propagation::Stop; - } else if matches!(key, gdk::Key::Down | gdk::Key::KP_Down) { - // Move down, if possible. - let new_idx = if let Some(idx) = obj.selected_row_index() { - idx + 1 - } else { - 0 - }; - let max = imp.filtered_list.n_items() as usize; - - if new_idx < max { - obj.select_row_at_index(Some(new_idx)); - } - return glib::Propagation::Stop; - } else if matches!(key, gdk::Key::Escape) { - // Close. - obj.popdown(); + } else if matches!(key, gdk::Key::Tab) { + obj.update_completion(); return glib::Propagation::Stop; } - } else if matches!(key, gdk::Key::Tab) { - obj.update_completion(); - return glib::Propagation::Stop; } + glib::Propagation::Proceed } - glib::Propagation::Proceed - })); + )); entry.add_controller(key_events.clone()); self.entry_controller.replace(Some(key_events)); @@ -175,14 +187,21 @@ mod imp { .build(); self.entry_binding.replace(Some(search_binding)); - let changed_handler = entry.connect_changed(clone!(@weak obj => move |_| { - obj.update_completion(); - })); + let changed_handler = entry.connect_changed(clone!( + #[weak] + obj, + move |_| { + obj.update_completion(); + } + )); - let state_flags_handler = - entry.connect_state_flags_changed(clone!(@weak obj => move |_, _| { + let state_flags_handler = entry.connect_state_flags_changed(clone!( + #[weak] + obj, + move |_, _| { obj.update_completion(); - })); + } + )); obj.set_parent(entry); self.entry diff --git a/src/session/view/content/room_details/addresses_subpage/mod.rs b/src/session/view/content/room_details/addresses_subpage/mod.rs index affb70d9..f444bea4 100644 --- a/src/session/view/content/room_details/addresses_subpage/mod.rs +++ b/src/session/view/content/room_details/addresses_subpage/mod.rs @@ -96,19 +96,29 @@ mod imp { self.public_addresses_list.bind_model( Some(&flattened_public_list), clone!( - @weak obj => @default-return { adw::ActionRow::new().upcast() }, + #[weak] + obj, + #[upgrade_or_else] + || { adw::ActionRow::new().upcast() }, move |item| obj.create_public_address_row(item) ), ); - self.public_addresses_add_row - .connect_changed(clone!(@weak obj => move |_| { + self.public_addresses_add_row.connect_changed(clone!( + #[weak] + obj, + move |_| { obj.update_public_addresses_add_row(); - })); + } + )); // Filter addresses already in the list. - let new_addresses_filter = gtk::CustomFilter::new( - clone!(@weak self as imp => @default-return false, move |item: &glib::Object| { + let new_addresses_filter = gtk::CustomFilter::new(clone!( + #[weak(rename_to = imp)] + self, + #[upgrade_or] + false, + move |item: &glib::Object| { let Some(item) = item.downcast_ref::() else { return false; }; @@ -127,15 +137,17 @@ mod imp { } true - }), - ); + } + )); // Update the filtered list everytime an item changes. - self.public_addresses().connect_items_changed( - clone!(@weak new_addresses_filter => move |_,_,_,_| { + self.public_addresses().connect_items_changed(clone!( + #[weak] + new_addresses_filter, + move |_, _, _, _| { new_addresses_filter.changed(gtk::FilterChange::Different); - }), - ); + } + )); let new_local_addresses = gtk::FilterListModel::new( Some(self.local_addresses.clone()), @@ -157,15 +169,21 @@ mod imp { self.local_addresses_list.bind_model( Some(&flattened_local_list), clone!( - @weak obj => @default-return { adw::ActionRow::new().upcast() }, + #[weak] + obj, + #[upgrade_or_else] + || { adw::ActionRow::new().upcast() }, move |item| obj.create_local_address_row(item) ), ); - self.local_addresses_add_row - .connect_changed(clone!(@weak obj => move |_| { + self.local_addresses_add_row.connect_changed(clone!( + #[weak] + obj, + move |_| { obj.update_local_addresses_add_row(); - })); + } + )); } fn dispose(&self) { @@ -192,10 +210,13 @@ mod imp { fn set_room(&self, room: Room) { let aliases = room.aliases(); - let aliases_changed_handler = - aliases.connect_changed(clone!(@weak self as imp => move |_| { + let aliases_changed_handler = aliases.connect_changed(clone!( + #[weak(rename_to = imp)] + self, + move |_| { imp.update_public_addresses(); - })); + } + )); self.aliases_changed_handler .replace(Some(aliases_changed_handler)); @@ -205,9 +226,13 @@ mod imp { self.update_public_addresses(); self.update_local_addresses_server(); - spawn!(clone!(@weak self as imp => async move { - imp.update_local_addresses().await; - })); + spawn!(clone!( + #[weak(rename_to = imp)] + self, + async move { + imp.update_local_addresses().await; + } + )); } /// Update the list of public addresses. @@ -382,16 +407,30 @@ impl AddressesSubpage { &[("address", alias.as_str())], ))); - address.connect_is_main_notify(clone!(@weak self as obj, @weak row => move |address| { - obj.update_public_row_is_main(&row, address.is_main()); - })); + address.connect_is_main_notify(clone!( + #[weak(rename_to = obj)] + self, + #[weak] + row, + move |address| { + obj.update_public_row_is_main(&row, address.is_main()); + } + )); self.update_public_row_is_main(&row, address.is_main()); - row.connect_remove(clone!(@weak self as obj => move |row| { - spawn!(clone!(@weak row => async move { - obj.remove_public_address(&row).await; - })); - })); + row.connect_remove(clone!( + #[weak(rename_to = obj)] + self, + move |row| { + spawn!(clone!( + #[weak] + row, + async move { + obj.remove_public_address(&row).await; + } + )); + } + )); row.upcast() } else { @@ -440,11 +479,17 @@ impl AddressesSubpage { ); button.update_property(&[gtk::accessible::Property::Label(&accessible_label)]); - button.connect_clicked(clone!(@weak self as obj, @weak row => move |_| { - spawn!(async move { - obj.set_main_public_address(&row).await; - }); - })); + button.connect_clicked(clone!( + #[weak(rename_to = obj)] + self, + #[weak] + row, + move |_| { + spawn!(async move { + obj.set_main_public_address(&row).await; + }); + } + )); row.set_extra_suffix(Some(button)); } @@ -622,11 +667,19 @@ impl AddressesSubpage { &[("address", &alias)], ))); - row.connect_remove(clone!(@weak self as obj => move |row| { - spawn!(clone!(@weak row => async move { - obj.unregister_local_address(&row).await; - })); - })); + row.connect_remove(clone!( + #[weak(rename_to = obj)] + self, + move |row| { + spawn!(clone!( + #[weak] + row, + async move { + obj.unregister_local_address(&row).await; + } + )); + } + )); row.upcast() } else { diff --git a/src/session/view/content/room_details/general_page/mod.rs b/src/session/view/content/room_details/general_page/mod.rs index a032d626..0389dc16 100644 --- a/src/session/view/content/room_details/general_page/mod.rs +++ b/src/session/view/content/room_details/general_page/mod.rs @@ -186,82 +186,131 @@ mod imp { .chain_property::("uri") .watch( Some(&avatar_data), - clone!(@weak obj, @weak avatar_data => move || { - obj.avatar_changed(avatar_data.image().and_then(|i| i.uri())); - }), + clone!( + #[weak] + obj, + #[weak] + avatar_data, + move || { + obj.avatar_changed(avatar_data.image().and_then(|i| i.uri())); + } + ), ); self.expr_watches.borrow_mut().push(expr_watch); - let membership_handler = - room.own_member() - .connect_membership_notify(clone!(@weak obj => move |_| { - obj.update_sections(); - })); + let membership_handler = room.own_member().connect_membership_notify(clone!( + #[weak] + obj, + move |_| { + obj.update_sections(); + } + )); self.membership_handler.replace(Some(membership_handler)); - let permissions_handler = - room.permissions() - .connect_changed(clone!(@weak obj => move |_| { - obj.update_upgrade_button(); - obj.update_edit_addresses_button(); - obj.update_join_rule(); - obj.update_guest_access(); - obj.update_history_visibility(); - obj.update_encryption(); + let permissions_handler = room.permissions().connect_changed(clone!( + #[weak] + obj, + move |_| { + obj.update_upgrade_button(); + obj.update_edit_addresses_button(); + obj.update_join_rule(); + obj.update_guest_access(); + obj.update_history_visibility(); + obj.update_encryption(); - spawn!(async move { - obj.update_publish().await; - }); - })); + spawn!(async move { + obj.update_publish().await; + }); + } + )); self.permissions_handler.replace(Some(permissions_handler)); let aliases = room.aliases(); - let canonical_alias_handler = - aliases.connect_canonical_alias_string_notify(clone!(@weak obj => move |_| { + let canonical_alias_handler = aliases.connect_canonical_alias_string_notify(clone!( + #[weak] + obj, + move |_| { obj.update_addresses(); - })); + } + )); self.canonical_alias_handler .replace(Some(canonical_alias_handler)); - let alt_aliases_handler = aliases.alt_aliases_model().connect_items_changed( - clone!(@weak obj => move |_,_,_,_| { + let alt_aliases_handler = aliases.alt_aliases_model().connect_items_changed(clone!( + #[weak] + obj, + move |_, _, _, _| { obj.update_addresses(); - }), - ); + } + )); self.alt_aliases_handler.replace(Some(alt_aliases_handler)); - let join_rule_handler = - room.join_rule() - .connect_changed(clone!(@weak obj => move |_| { - obj.update_join_rule(); - })); + let join_rule_handler = room.join_rule().connect_changed(clone!( + #[weak] + obj, + move |_| { + obj.update_join_rule(); + } + )); self.join_rule_handler.replace(Some(join_rule_handler)); let room_handler_ids = vec![ - room.connect_name_notify(clone!(@weak obj => move |room| { - obj.name_changed(room.name()); - })), - room.connect_topic_notify(clone!(@weak obj => move |room| { - obj.topic_changed(room.topic()); - })), - room.connect_joined_members_count_notify(clone!(@weak obj => move |room| { - obj.member_count_changed(room.joined_members_count()); - })), - room.connect_notifications_setting_notify(clone!(@weak obj => move |_| { - obj.update_notifications(); - })), - room.connect_is_tombstoned_notify(clone!(@weak obj => move |_| { - obj.update_upgrade_button(); - })), - room.connect_guests_allowed_notify(clone!(@weak obj => move |_| { - obj.update_guest_access(); - })), - room.connect_history_visibility_notify(clone!(@weak obj => move |_| { - obj.update_history_visibility(); - })), - room.connect_is_encrypted_notify(clone!(@weak obj => move |_| { - obj.update_encryption(); - })), + room.connect_name_notify(clone!( + #[weak] + obj, + move |room| { + obj.name_changed(room.name()); + } + )), + room.connect_topic_notify(clone!( + #[weak] + obj, + move |room| { + obj.topic_changed(room.topic()); + } + )), + room.connect_joined_members_count_notify(clone!( + #[weak] + obj, + move |room| { + obj.member_count_changed(room.joined_members_count()); + } + )), + room.connect_notifications_setting_notify(clone!( + #[weak] + obj, + move |_| { + obj.update_notifications(); + } + )), + room.connect_is_tombstoned_notify(clone!( + #[weak] + obj, + move |_| { + obj.update_upgrade_button(); + } + )), + room.connect_guests_allowed_notify(clone!( + #[weak] + obj, + move |_| { + obj.update_guest_access(); + } + )), + room.connect_history_visibility_notify(clone!( + #[weak] + obj, + move |_| { + obj.update_history_visibility(); + } + )), + room.connect_is_encrypted_notify(clone!( + #[weak] + obj, + move |_| { + obj.update_encryption(); + } + )), ]; obj.member_count_changed(room.joined_members_count()); @@ -278,12 +327,20 @@ mod imp { if let Some(session) = room.session() { let settings = session.notifications().settings(); let notifications_settings_handlers = vec![ - settings.connect_account_enabled_notify(clone!(@weak obj => move |_| { - obj.update_notifications(); - })), - settings.connect_session_enabled_notify(clone!(@weak obj => move |_| { - obj.update_notifications(); - })), + settings.connect_account_enabled_notify(clone!( + #[weak] + obj, + move |_| { + obj.update_notifications(); + } + )), + settings.connect_session_enabled_notify(clone!( + #[weak] + obj, + move |_| { + obj.update_notifications(); + } + )), ]; self.notifications_settings_handlers @@ -302,9 +359,13 @@ mod imp { obj.update_encryption(); obj.update_upgrade_button(); - spawn!(clone!(@weak obj => async move { - obj.update_publish().await; - })); + spawn!(clone!( + #[weak] + obj, + async move { + obj.update_publish().await; + } + )); self.load_capabilities(); } @@ -347,20 +408,22 @@ mod imp { spawn!( glib::Priority::LOW, - clone!(@weak self as imp => async move { - let handle = spawn_tokio!(async move { - client.get_capabilities().await - }); - match handle.await.unwrap() { - Ok(capabilities) => { - imp.capabilities.replace(capabilities); - } - Err(error) => { - error!("Could not get server capabilities: {error}"); - imp.capabilities.take(); + clone!( + #[weak(rename_to = imp)] + self, + async move { + let handle = spawn_tokio!(async move { client.get_capabilities().await }); + match handle.await.unwrap() { + Ok(capabilities) => { + imp.capabilities.replace(capabilities); + } + Err(error) => { + error!("Could not get server capabilities: {error}"); + imp.capabilities.take(); + } } } - }) + ) ); } } @@ -396,16 +459,24 @@ impl GeneralPage { fn init_avatar(&self) { let avatar = &*self.imp().avatar; - avatar.connect_edit_avatar(clone!(@weak self as obj => move |_, file| { - spawn!(async move { - obj.change_avatar(file).await; - }); - })); - avatar.connect_remove_avatar(clone!(@weak self as obj => move |_| { - spawn!(async move { - obj.remove_avatar().await; - }); - })); + avatar.connect_edit_avatar(clone!( + #[weak(rename_to = obj)] + self, + move |_, file| { + spawn!(async move { + obj.change_avatar(file).await; + }); + } + )); + avatar.connect_remove_avatar(clone!( + #[weak(rename_to = obj)] + self, + move |_| { + spawn!(async move { + obj.remove_avatar().await; + }); + } + )); } fn avatar_changed(&self, uri: Option) { @@ -860,17 +931,22 @@ impl GeneralPage { self.set_notifications_loading(true, setting); let settings = session.notifications().settings(); - spawn!(clone!(@weak self as obj => async move { - if settings.set_per_room_setting(room.room_id().to_owned(), setting).await.is_err() { - toast!( - obj, - gettext("Could not change notifications setting") - ); - } + spawn!(clone!( + #[weak(rename_to = obj)] + self, + async move { + if settings + .set_per_room_setting(room.room_id().to_owned(), setting) + .await + .is_err() + { + toast!(obj, gettext("Could not change notifications setting")); + } - obj.set_notifications_loading(false, setting); - obj.update_notifications(); - })); + obj.set_notifications_loading(false, setting); + obj.update_notifications(); + } + )); } /// Update the button to edit addresses. diff --git a/src/session/view/content/room_details/history_viewer/audio.rs b/src/session/view/content/room_details/history_viewer/audio.rs index 13a9cd06..e5f02d05 100644 --- a/src/session/view/content/room_details/history_viewer/audio.rs +++ b/src/session/view/content/room_details/history_viewer/audio.rs @@ -64,20 +64,32 @@ mod imp { self.list_view.set_model(Some(&model)); // Load an initial number of items - spawn!(clone!(@weak self as imp, @weak timeline => async move { - while model.n_items() < MIN_N_ITEMS { - if !timeline.load().await { - break; + spawn!(clone!( + #[weak(rename_to = imp)] + self, + #[weak] + timeline, + async move { + while model.n_items() < MIN_N_ITEMS { + if !timeline.load().await { + break; + } } - } - let adj = imp.list_view.vadjustment().unwrap(); - adj.connect_value_notify(clone!(@weak timeline => move |adj| { - if adj.value() + adj.page_size() * 2.0 >= adj.upper() { - spawn!(async move { timeline.load().await; }); - } - })); - })); + let adj = imp.list_view.vadjustment().unwrap(); + adj.connect_value_notify(clone!( + #[weak] + timeline, + move |adj| { + if adj.value() + adj.page_size() * 2.0 >= adj.upper() { + spawn!(async move { + timeline.load().await; + }); + } + } + )); + } + )); self.timeline.set(timeline).unwrap(); } diff --git a/src/session/view/content/room_details/history_viewer/audio_row.rs b/src/session/view/content/room_details/history_viewer/audio_row.rs index 15e6078f..38ba83a8 100644 --- a/src/session/view/content/room_details/history_viewer/audio_row.rs +++ b/src/session/view/content/room_details/history_viewer/audio_row.rs @@ -98,9 +98,13 @@ mod imp { } if let Some(session) = event.room().and_then(|r| r.session()) { - spawn!(clone!(@weak obj => async move { - obj.download_audio(audio, &session).await; - })); + spawn!(clone!( + #[weak] + obj, + async move { + obj.download_audio(audio, &session).await; + } + )); } } } @@ -150,16 +154,22 @@ impl AudioRow { fn prepare_audio(&self, file: gio::File) { let media_file = gtk::MediaFile::for_file(&file); - media_file.connect_error_notify(clone!(@weak self as obj => move |media_file| { + media_file.connect_error_notify(|media_file| { if let Some(error) = media_file.error() { warn!("Error reading audio file: {}", error); } - })); - media_file.connect_ended_notify(clone!(@weak self as obj => move |media_file| { - if media_file.is_ended() { - obj.imp().play_button.set_icon_name("media-playback-start-symbolic"); + }); + media_file.connect_ended_notify(clone!( + #[weak(rename_to = obj)] + self, + move |media_file| { + if media_file.is_ended() { + obj.imp() + .play_button + .set_icon_name("media-playback-start-symbolic"); + } } - })); + )); self.imp().media_file.replace(Some(media_file)); } diff --git a/src/session/view/content/room_details/history_viewer/file.rs b/src/session/view/content/room_details/history_viewer/file.rs index 5a23ecb9..11d1d7aa 100644 --- a/src/session/view/content/room_details/history_viewer/file.rs +++ b/src/session/view/content/room_details/history_viewer/file.rs @@ -64,20 +64,32 @@ mod imp { self.list_view.set_model(Some(&model)); // Load an initial number of items - spawn!(clone!(@weak self as imp, @weak timeline => async move { - while model.n_items() < MIN_N_ITEMS { - if !timeline.load().await { - break; + spawn!(clone!( + #[weak(rename_to = imp)] + self, + #[weak] + timeline, + async move { + while model.n_items() < MIN_N_ITEMS { + if !timeline.load().await { + break; + } } - } - let adj = imp.list_view.vadjustment().unwrap(); - adj.connect_value_notify(clone!(@weak timeline => move |adj| { - if adj.value() + adj.page_size() * 2.0 >= adj.upper() { - spawn!(async move { timeline.load().await; }); - } - })); - })); + let adj = imp.list_view.vadjustment().unwrap(); + adj.connect_value_notify(clone!( + #[weak] + timeline, + move |adj| { + if adj.value() + adj.page_size() * 2.0 >= adj.upper() { + spawn!(async move { + timeline.load().await; + }); + } + } + )); + } + )); self.timeline.set(timeline).unwrap(); } diff --git a/src/session/view/content/room_details/history_viewer/media.rs b/src/session/view/content/room_details/history_viewer/media.rs index 94b93232..e90116c8 100644 --- a/src/session/view/content/room_details/history_viewer/media.rs +++ b/src/session/view/content/room_details/history_viewer/media.rs @@ -66,20 +66,32 @@ mod imp { self.grid_view.set_model(Some(&model)); // Load an initial number of items. - spawn!(clone!(@weak self as imp, @weak timeline => async move { - while model.n_items() < MIN_N_ITEMS { - if !timeline.load().await { - break; + spawn!(clone!( + #[weak(rename_to = imp)] + self, + #[weak] + timeline, + async move { + while model.n_items() < MIN_N_ITEMS { + if !timeline.load().await { + break; + } } - } - let adj = imp.grid_view.vadjustment().unwrap(); - adj.connect_value_notify(clone!(@weak timeline => move |adj| { - if adj.value() + adj.page_size() * 2.0 >= adj.upper() { - spawn!(async move { timeline.load().await; }); - } - })); - })); + let adj = imp.grid_view.vadjustment().unwrap(); + adj.connect_value_notify(clone!( + #[weak] + timeline, + move |adj| { + if adj.value() + adj.page_size() * 2.0 >= adj.upper() { + spawn!(async move { + timeline.load().await; + }); + } + } + )); + } + )); self.timeline.set(timeline).unwrap(); } diff --git a/src/session/view/content/room_details/history_viewer/media_item.rs b/src/session/view/content/room_details/history_viewer/media_item.rs index 62b7533f..a4fefd9e 100644 --- a/src/session/view/content/room_details/history_viewer/media_item.rs +++ b/src/session/view/content/room_details/history_viewer/media_item.rs @@ -193,28 +193,32 @@ impl MediaItem { spawn!( glib::Priority::LOW, - clone!(@weak self as obj => async move { - let imp = obj.imp(); - - match handle.await.unwrap() { - Ok(Some(data)) => { - match gdk::Texture::from_bytes(&glib::Bytes::from(&data)) { - Ok(texture) => { - imp.picture.set_paintable(Some(&texture)); - } - Err(error) => { - warn!("Image file not supported: {}", error); + clone!( + #[weak(rename_to = obj)] + self, + async move { + let imp = obj.imp(); + + match handle.await.unwrap() { + Ok(Some(data)) => { + match gdk::Texture::from_bytes(&glib::Bytes::from(&data)) { + Ok(texture) => { + imp.picture.set_paintable(Some(&texture)); + } + Err(error) => { + warn!("Image file not supported: {}", error); + } } } - } - Ok(None) => { - warn!("Could not retrieve invalid media file"); - } - Err(error) => { - warn!("Could not retrieve media file: {}", error); + Ok(None) => { + warn!("Could not retrieve invalid media file"); + } + Err(error) => { + warn!("Could not retrieve media file: {}", error); + } } } - }) + ) ); } diff --git a/src/session/view/content/room_details/invite_subpage/list.rs b/src/session/view/content/room_details/invite_subpage/list.rs index e1f26e09..6344ade4 100644 --- a/src/session/view/content/room_details/invite_subpage/list.rs +++ b/src/session/view/content/room_details/invite_subpage/list.rs @@ -115,9 +115,13 @@ mod imp { self.search_term.replace(search_term); - spawn!(clone!(@weak obj => async move { - obj.search_users().await; - })); + spawn!(clone!( + #[weak] + obj, + async move { + obj.search_users().await; + } + )); obj.notify_search_term(); } @@ -330,12 +334,20 @@ impl InviteList { let item = InviteItem::new(user); item.set_invite_exception(invite_exception); - item.connect_is_invitee_notify(clone!(@weak self as obj => move |item| { - obj.update_invitees_for_item(item); - })); - item.connect_can_invite_notify(clone!(@weak self as obj => move |item| { - obj.update_invitees_for_item(item); - })); + item.connect_is_invitee_notify(clone!( + #[weak(rename_to = obj)] + self, + move |item| { + obj.update_invitees_for_item(item); + } + )); + item.connect_can_invite_notify(clone!( + #[weak(rename_to = obj)] + self, + move |item| { + obj.update_invitees_for_item(item); + } + )); item } diff --git a/src/session/view/content/room_details/invite_subpage/mod.rs b/src/session/view/content/room_details/invite_subpage/mod.rs index 03548a46..12740362 100644 --- a/src/session/view/content/room_details/invite_subpage/mod.rs +++ b/src/session/view/content/room_details/invite_subpage/mod.rs @@ -95,17 +95,29 @@ mod imp { let obj = self.obj(); let invite_list = self.invite_list.get_or_init(|| InviteList::new(&room)); - invite_list.connect_invitee_added(clone!(@weak self as imp => move |_, invitee| { - imp.search_entry.add_pill(&invitee.user()); - })); + invite_list.connect_invitee_added(clone!( + #[weak(rename_to = imp)] + self, + move |_, invitee| { + imp.search_entry.add_pill(&invitee.user()); + } + )); - invite_list.connect_invitee_removed(clone!(@weak self as imp => move |_, invitee| { - imp.search_entry.remove_pill(&invitee.user().identifier()); - })); + invite_list.connect_invitee_removed(clone!( + #[weak(rename_to = imp)] + self, + move |_, invitee| { + imp.search_entry.remove_pill(&invitee.user().identifier()); + } + )); - invite_list.connect_state_notify(clone!(@weak self as imp => move |_| { - imp.update_view(); - })); + invite_list.connect_state_notify(clone!( + #[weak(rename_to = imp)] + self, + move |_| { + imp.update_view(); + } + )); self.search_entry .bind_property("text", invite_list, "search-term") diff --git a/src/session/view/content/room_details/members_page/members_list_view/extra_lists.rs b/src/session/view/content/room_details/members_page/members_list_view/extra_lists.rs index 1661c0f6..69d0e1ff 100644 --- a/src/session/view/content/room_details/members_page/members_list_view/extra_lists.rs +++ b/src/session/view/content/room_details/members_page/members_list_view/extra_lists.rs @@ -46,13 +46,21 @@ mod imp { let invited_members = obj.invited().model(); let banned_members = obj.banned().model(); - invited_members.connect_items_changed(clone!(@weak obj => move |_, _, _, _| { - obj.update_invited(); - })); + invited_members.connect_items_changed(clone!( + #[weak] + obj, + move |_, _, _, _| { + obj.update_invited(); + } + )); - banned_members.connect_items_changed(clone!(@weak obj => move |_, _, _, _| { - obj.update_banned(); - })); + banned_members.connect_items_changed(clone!( + #[weak] + obj, + move |_, _, _, _| { + obj.update_banned(); + } + )); self.invited_is_empty.set(invited_members.n_items() == 0); self.banned_is_empty.set(banned_members.n_items() == 0); @@ -104,12 +112,13 @@ mod imp { self.members.disconnect_signals(); - let signal_handler_ids = - vec![ - members.connect_state_notify(clone!(@weak obj => move |members| { - obj.update_loading_state(members.state()); - })), - ]; + let signal_handler_ids = vec![members.connect_state_notify(clone!( + #[weak] + obj, + move |members| { + obj.update_loading_state(members.state()); + } + ))]; obj.update_loading_state(members.state()); self.members.set(&members, signal_handler_ids); diff --git a/src/session/view/content/room_details/members_page/members_list_view/membership_subpage_row.rs b/src/session/view/content/room_details/members_page/members_list_view/membership_subpage_row.rs index 39b9b96d..14ff9be6 100644 --- a/src/session/view/content/room_details/members_page/members_list_view/membership_subpage_row.rs +++ b/src/session/view/content/room_details/members_page/members_list_view/membership_subpage_row.rs @@ -79,12 +79,14 @@ mod imp { if let Some(item) = &item { let model = item.model(); - let items_changed_handler = model.connect_items_changed( - clone!(@weak self as imp => move |model, _, _, _| { + let items_changed_handler = model.connect_items_changed(clone!( + #[weak(rename_to = imp)] + self, + move |model, _, _, _| { imp.member_count_changed(model.n_items()); imp.obj().notify_label(); - }), - ); + } + )); self.items_changed_handler .replace(Some(items_changed_handler)); diff --git a/src/session/view/content/room_details/members_page/members_list_view/mod.rs b/src/session/view/content/room_details/members_page/members_list_view/mod.rs index aadd7b50..7007491a 100644 --- a/src/session/view/content/room_details/members_page/members_list_view/mod.rs +++ b/src/session/view/content/room_details/members_page/members_list_view/mod.rs @@ -116,8 +116,10 @@ mod imp { self.list_view.set_model(Some(>k::NoSelection::new(Some( self.filtered_model.clone(), )))); - self.list_view - .connect_activate(clone!(@weak obj => move |_, pos| { + self.list_view.connect_activate(clone!( + #[weak] + obj, + move |_, pos| { let Some(item) = obj.imp().filtered_model.item(pos) else { return; }; @@ -135,7 +137,8 @@ mod imp { ) .unwrap(); } - })); + } + )); obj.connect_tag_notify(|obj| { obj.imp().update_title(); @@ -176,10 +179,13 @@ mod imp { } if let Some(model) = &model { - let items_changed_handler = - model.connect_items_changed(clone!(@weak self as imp => move |_, _, _, _| { + let items_changed_handler = model.connect_items_changed(clone!( + #[weak(rename_to = imp)] + self, + move |_, _, _, _| { imp.update_title(); - })); + } + )); self.items_changed_handler .replace(Some(items_changed_handler)); } diff --git a/src/session/view/content/room_details/members_page/mod.rs b/src/session/view/content/room_details/members_page/mod.rs index 0aa48cec..56251984 100644 --- a/src/session/view/content/room_details/members_page/mod.rs +++ b/src/session/view/content/room_details/members_page/mod.rs @@ -80,10 +80,17 @@ mod imp { let member = room.get_or_create_members().get_or_create(user_id); let user_page = UserPage::new(&member); - user_page.connect_close(clone!(@weak obj => move |_| { - obj.imp().navigation_view.pop(); - toast!(obj, gettext("The user is not in the room members list anymore")); - })); + user_page.connect_close(clone!( + #[weak] + obj, + move |_| { + obj.imp().navigation_view.pop(); + toast!( + obj, + gettext("The user is not in the room members list anymore") + ); + } + )); obj.imp().navigation_view.push(&user_page); }, diff --git a/src/session/view/content/room_details/permissions/add_members_subpage.rs b/src/session/view/content/room_details/permissions/add_members_subpage.rs index f168dba8..6275b31b 100644 --- a/src/session/view/content/room_details/permissions/add_members_subpage.rs +++ b/src/session/view/content/room_details/permissions/add_members_subpage.rs @@ -79,15 +79,20 @@ mod imp { self.parent_constructed(); let obj = self.obj(); - self.search_entry - .connect_pill_removed(clone!(@weak self as imp => move |_, source| { + self.search_entry.connect_pill_removed(clone!( + #[weak(rename_to = imp)] + self, + move |_, source| { if let Ok(member) = source.downcast::() { imp.remove_selected(member.user_id()); } - })); + } + )); - self.list_view - .connect_activate(clone!(@weak self as imp => move |list_view, index| { + self.list_view.connect_activate(clone!( + #[weak(rename_to = imp)] + self, + move |list_view, index| { let Some(member) = list_view .model() .and_then(|m| m.item(index)) @@ -97,7 +102,8 @@ mod imp { }; imp.toggle_selected(member); - })); + } + )); // Search filter. fn search_string(member: Member) -> String { @@ -134,11 +140,13 @@ mod imp { self.filtered_model.set_filter(Some(&filter)); - self.filtered_model.connect_items_changed( - clone!(@weak self as imp => move |_, _, _, _| { + self.filtered_model.connect_items_changed(clone!( + #[weak(rename_to = imp)] + self, + move |_, _, _, _| { imp.update_visible_page(); - }), - ); + } + )); // Sort members by display name, then user ID. let display_name_expr = Member::this_expression("display-name"); @@ -158,32 +166,40 @@ mod imp { .set_model(Some(>k::NoSelection::new(Some(sorted_model)))); let factory = gtk::SignalListItemFactory::new(); - factory.connect_setup(clone!(@weak obj => move |_, item| { - let Some(item) = item.downcast_ref::() else { - error!("List item factory did not receive a list item: {item:?}"); - return; - }; - - let row = PermissionsSelectMemberRow::new(); - item.set_child(Some(&row)); - item.bind_property("item", &row, "member") - .sync_create() - .build(); - item.set_selectable(false); - - obj.connect_selection_changed(clone!(@weak row => move |obj| { - let Some(member) = row.member() else { + factory.connect_setup(clone!( + #[weak] + obj, + move |_, item| { + let Some(item) = item.downcast_ref::() else { + error!("List item factory did not receive a list item: {item:?}"); return; }; - let selected = obj - .imp() - .selected_members - .borrow() - .contains_key(member.user_id()); - row.set_selected(selected); - })); - })); + let row = PermissionsSelectMemberRow::new(); + item.set_child(Some(&row)); + item.bind_property("item", &row, "member") + .sync_create() + .build(); + item.set_selectable(false); + + obj.connect_selection_changed(clone!( + #[weak] + row, + move |obj| { + let Some(member) = row.member() else { + return; + }; + + let selected = obj + .imp() + .selected_members + .borrow() + .contains_key(member.user_id()); + row.set_selected(selected); + } + )); + } + )); self.list_view.set_factory(Some(&factory)); } } @@ -201,15 +217,23 @@ mod imp { self.permissions.set(permissions.as_ref()); if let Some(permissions) = &permissions { - self.power_level_filter.set_filter_func(clone!(@weak permissions => @default-return true, move |obj| { - let Some(member) = obj.downcast_ref::() else { - return false; - }; - - // Filter out members whose power level cannot be changed. - permissions - .can_do_to_user(member.user_id(), PowerLevelUserAction::ChangePowerLevel) - })); + self.power_level_filter.set_filter_func(clone!( + #[weak] + permissions, + #[upgrade_or] + true, + move |obj| { + let Some(member) = obj.downcast_ref::() else { + return false; + }; + + // Filter out members whose power level cannot be changed. + permissions.can_do_to_user( + member.user_id(), + PowerLevelUserAction::ChangePowerLevel, + ) + } + )); } let members = permissions diff --git a/src/session/view/content/room_details/permissions/member_power_level.rs b/src/session/view/content/room_details/permissions/member_power_level.rs index 5fff48f6..ba7743ef 100644 --- a/src/session/view/content/room_details/permissions/member_power_level.rs +++ b/src/session/view/content/room_details/permissions/member_power_level.rs @@ -56,12 +56,15 @@ mod imp { impl MemberPowerLevel { /// Set the room member. fn set_permissions(&self, permissions: &Permissions) { - let changed_handler = - permissions.connect_changed(clone!(@weak self as imp => move |_| { + let changed_handler = permissions.connect_changed(clone!( + #[weak(rename_to = imp)] + self, + move |_| { imp.update_power_level(); imp.update_role(); imp.update_editable(); - })); + } + )); self.permissions.set(permissions, vec![changed_handler]); } diff --git a/src/session/view/content/room_details/permissions/member_row.rs b/src/session/view/content/room_details/permissions/member_row.rs index 31c8cf49..7cb34e09 100644 --- a/src/session/view/content/room_details/permissions/member_row.rs +++ b/src/session/view/content/room_details/permissions/member_row.rs @@ -83,14 +83,20 @@ mod imp { self.member.disconnect_signals(); if let Some(member) = member { - let power_level_handler = - member.connect_power_level_notify(clone!(@weak self as imp => move |_| { + let power_level_handler = member.connect_power_level_notify(clone!( + #[weak(rename_to = imp)] + self, + move |_| { imp.update_power_level(); - })); - let editable_handler = - member.connect_editable_notify(clone!(@weak self as imp => move |_| { + } + )); + let editable_handler = member.connect_editable_notify(clone!( + #[weak(rename_to = imp)] + self, + move |_| { imp.update_accessible_role(); - })); + } + )); self.member .set(member, vec![power_level_handler, editable_handler]); diff --git a/src/session/view/content/room_details/permissions/members_subpage.rs b/src/session/view/content/room_details/permissions/members_subpage.rs index 313b5f71..18a38f64 100644 --- a/src/session/view/content/room_details/permissions/members_subpage.rs +++ b/src/session/view/content/room_details/permissions/members_subpage.rs @@ -120,20 +120,26 @@ mod imp { .set_model(Some(>k::NoSelection::new(Some(sorted_model)))); let factory = gtk::SignalListItemFactory::new(); - factory.connect_setup(clone!(@weak obj => move |_, item| { - let Some(item) = item.downcast_ref::() else { - error!("List item factory did not receive a list item: {item:?}"); - return; - }; - let Some(permissions) = obj.list().and_then(|l| l.permissions()) else { - return; - }; - let row = PermissionsMemberRow::new(&permissions); - item.set_child(Some(&row)); - item.bind_property("item", &row, "member").sync_create().build(); - item.set_activatable(false); - item.set_selectable(false); - })); + factory.connect_setup(clone!( + #[weak] + obj, + move |_, item| { + let Some(item) = item.downcast_ref::() else { + error!("List item factory did not receive a list item: {item:?}"); + return; + }; + let Some(permissions) = obj.list().and_then(|l| l.permissions()) else { + return; + }; + let row = PermissionsMemberRow::new(&permissions); + item.set_child(Some(&row)); + item.bind_property("item", &row, "member") + .sync_create() + .build(); + item.set_activatable(false); + item.set_selectable(false); + } + )); self.list_view.set_factory(Some(&factory)); } } diff --git a/src/session/view/content/room_details/permissions/permissions_subpage.rs b/src/session/view/content/room_details/permissions/permissions_subpage.rs index b246e7fd..4a0a3957 100644 --- a/src/session/view/content/room_details/permissions/permissions_subpage.rs +++ b/src/session/view/content/room_details/permissions/permissions_subpage.rs @@ -126,10 +126,13 @@ mod imp { impl PermissionsSubpage { /// Set the permissions to watch. fn set_permissions(&self, permissions: &Permissions) { - let changed_handler = - permissions.connect_changed(clone!(@weak self as imp => move |_| { + let changed_handler = permissions.connect_changed(clone!( + #[weak(rename_to = imp)] + self, + move |_| { imp.update(); - })); + } + )); self.permissions.set(permissions, vec![changed_handler]); @@ -138,9 +141,13 @@ mod imp { .set(privileged_members.clone()) .unwrap(); - privileged_members.connect_changed_notify(clone!(@weak self as imp => move |_| { - imp.update_changed(); - })); + privileged_members.connect_changed_notify(clone!( + #[weak(rename_to = imp)] + self, + move |_| { + imp.update_changed(); + } + )); self.members_subpage .set_list(Some(privileged_members.clone())); diff --git a/src/session/view/content/room_details/permissions/privileged_members.rs b/src/session/view/content/room_details/permissions/privileged_members.rs index 81223d08..a1c5a2ff 100644 --- a/src/session/view/content/room_details/permissions/privileged_members.rs +++ b/src/session/view/content/room_details/permissions/privileged_members.rs @@ -60,10 +60,13 @@ mod imp { impl PrivilegedMembers { /// Set the permissions to watch. fn set_permissions(&self, permissions: &Permissions) { - let changed_handler = - permissions.connect_changed(clone!(@weak self as imp => move |_| { + let changed_handler = permissions.connect_changed(clone!( + #[weak(rename_to = imp)] + self, + move |_| { imp.update(); - })); + } + )); self.permissions.set(permissions, vec![changed_handler]); self.update(); @@ -110,18 +113,25 @@ mod imp { .unwrap_or_else(|| { let user = RemoteUser::new(&session, user_id.clone()); - spawn!(clone!(@strong user => async move { - user.load_profile().await; - })); + spawn!(clone!( + #[strong] + user, + async move { + user.load_profile().await; + } + )); user.upcast() }); let member = MemberPowerLevel::new(&user, &permissions); - let handler = - member.connect_power_level_notify(clone!(@weak self as imp => move |_| { + let handler = member.connect_power_level_notify(clone!( + #[weak(rename_to = imp)] + self, + move |_| { imp.update_changed(); - })); + } + )); new_handlers.push(handler); (user_id, member) diff --git a/src/session/view/content/room_history/item_row.rs b/src/session/view/content/room_history/item_row.rs index f65e8a3e..4b06539c 100644 --- a/src/session/view/content/room_history/item_row.rs +++ b/src/session/view/content/room_history/item_row.rs @@ -114,8 +114,14 @@ mod imp { let cell: Rc>> = Rc::new(RefCell::new(None)); - let signal_id = popover.connect_closed( - clone!(@weak obj, @strong cell, @weak room_history => move |popover| { + let signal_id = popover.connect_closed(clone!( + #[weak] + obj, + #[strong] + cell, + #[weak] + room_history, + move |popover| { room_history.enable_sticky_mode(); obj.remove_css_class("has-open-popup"); @@ -123,8 +129,8 @@ mod imp { if let Some(signal_id) = cell.take() { popover.disconnect(signal_id); } - }), - ); + } + )); cell.replace(Some(signal_id)); if let Some(event) = event @@ -150,9 +156,15 @@ mod imp { // Open emoji chooser action_group.add_action_entries([gio::ActionEntry::builder("more-reactions") - .activate(clone!(@weak obj, @weak popover => move |_, _, _| { - obj.show_emoji_chooser(&popover); - })) + .activate(clone!( + #[weak] + obj, + #[weak] + popover, + move |_, _, _| { + obj.show_emoji_chooser(&popover); + } + )) .build()]); } } else { @@ -175,9 +187,13 @@ mod imp { let related_event_handler = room_history .message_toolbar() - .connect_related_event_notify(clone!(@weak obj => move |message_toolbar| { - obj.update_for_related_event(message_toolbar.related_event()); - })); + .connect_related_event_notify(clone!( + #[weak] + obj, + move |message_toolbar| { + obj.update_for_related_event(message_toolbar.related_event()); + } + )); self.message_toolbar_handler .replace(Some(related_event_handler)); } @@ -208,27 +224,41 @@ mod imp { if let Some(item) = &item { if let Some(event) = item.downcast_ref::() { - let state_notify_handler = - event.connect_state_notify(clone!(@weak obj => move |event| { + let state_notify_handler = event.connect_state_notify(clone!( + #[weak] + obj, + move |event| { obj.update_event_actions(Some(event.upcast_ref())); - })); + } + )); - let source_notify_handler = - event.connect_source_notify(clone!(@weak obj => move |event| { + let source_notify_handler = event.connect_source_notify(clone!( + #[weak] + obj, + move |event| { obj.set_event_widget(event.clone()); obj.update_event_actions(Some(event.upcast_ref())); - })); + } + )); let edit_source_notify_handler = - event.connect_latest_edit_source_notify(clone!(@weak obj => move |event| { - obj.set_event_widget(event.clone()); - obj.update_event_actions(Some(event.upcast_ref())); - })); + event.connect_latest_edit_source_notify(clone!( + #[weak] + obj, + move |event| { + obj.set_event_widget(event.clone()); + obj.update_event_actions(Some(event.upcast_ref())); + } + )); let is_highlighted_notify_handler = - event.connect_is_highlighted_notify(clone!(@weak obj => move |_| { - obj.update_highlight(); - })); + event.connect_is_highlighted_notify(clone!( + #[weak] + obj, + move |_| { + obj.update_highlight(); + } + )); self.event_handlers.replace(vec![ state_notify_handler, @@ -237,11 +267,15 @@ mod imp { is_highlighted_notify_handler, ]); - let permissions_handler = event.room().permissions().connect_changed( - clone!(@weak obj, @weak event => move |_| { + let permissions_handler = event.room().permissions().connect_changed(clone!( + #[weak] + obj, + #[weak] + event, + move |_| { obj.update_event_actions(Some(event.upcast_ref())); - }), - ); + } + )); self.permissions_handler.replace(Some(permissions_handler)); obj.set_event_widget(event.clone()); @@ -421,11 +455,14 @@ impl ItemRow { .pointing_to(&rectangle) .build(); - emoji_chooser.connect_emoji_picked(clone!(@weak self as obj => move |_, emoji| { - obj - .activate_action("event.toggle-reaction", Some(&emoji.to_variant())) - .unwrap(); - })); + emoji_chooser.connect_emoji_picked(clone!( + #[weak(rename_to = obj)] + self, + move |_, emoji| { + obj.activate_action("event.toggle-reaction", Some(&emoji.to_variant())) + .unwrap(); + } + )); emoji_chooser.connect_closed(|emoji_chooser| { emoji_chooser.unparent(); }); @@ -465,23 +502,35 @@ impl ItemRow { action_group.add_action_entries([ // Create a permalink. gio::ActionEntry::builder("permalink") - .activate(clone!(@weak self as obj, @weak event => move |_, _, _| { - spawn!(async move { - let Some(permalink) = event.matrix_to_uri().await else { - return; - }; + .activate(clone!( + #[weak(rename_to = obj)] + self, + #[weak] + event, + move |_, _, _| { + spawn!(async move { + let Some(permalink) = event.matrix_to_uri().await else { + return; + }; - obj.clipboard().set_text(&permalink.to_string()); - toast!(obj, gettext("Permalink copied to clipboard")); - }); - })) + obj.clipboard().set_text(&permalink.to_string()); + toast!(obj, gettext("Permalink copied to clipboard")); + }); + } + )) .build(), // View event details. gio::ActionEntry::builder("view-details") - .activate(clone!(@weak self as widget, @weak event => move |_, _, _| { - let dialog = EventDetailsDialog::new(&event); - dialog.present(&widget); - })) + .activate(clone!( + #[weak(rename_to = obj)] + self, + #[weak] + event, + move |_, _, _| { + let dialog = EventDetailsDialog::new(&event); + dialog.present(&obj); + } + )) .build(), ]); @@ -489,11 +538,15 @@ impl ItemRow { action_group.add_action_entries([ // Report the event. gio::ActionEntry::builder("report") - .activate(clone!(@weak self as obj => move |_, _, _| { - spawn!(async move { - obj.report_event().await; - }); - })) + .activate(clone!( + #[weak(rename_to = obj)] + self, + move |_, _, _| { + spawn!(async move { + obj.report_event().await; + }); + } + )) .build(), ]); } @@ -503,22 +556,30 @@ impl ItemRow { if matches!(state, MessageState::Sending | MessageState::Error) { // Cancel the event. action_group.add_action_entries([gio::ActionEntry::builder("cancel-send") - .activate(clone!(@weak self as obj, => move |_, _, _| { - spawn!(async move { - obj.cancel_send().await; - }); - })) + .activate(clone!( + #[weak(rename_to = obj)] + self, + move |_, _, _| { + spawn!(async move { + obj.cancel_send().await; + }); + } + )) .build()]); } if state == MessageState::Error { // Retry to send the event. action_group.add_action_entries([gio::ActionEntry::builder("retry-send") - .activate(clone!(@weak self as obj, => move |_, _, _| { - spawn!(async move { - obj.retry_send().await; - }); - })) + .activate(clone!( + #[weak(rename_to = obj)] + self, + move |_, _, _| { + spawn!(async move { + obj.retry_send().await; + }); + } + )) .build()]); } } @@ -535,11 +596,15 @@ impl ItemRow { || permissions.can_redact_other()) { action_group.add_action_entries([gio::ActionEntry::builder("remove") - .activate(clone!(@weak self as obj, => move |_, _, _| { - spawn!(async move { - obj.redact_message().await; - }); - })) + .activate(clone!( + #[weak(rename_to = obj)] + self, + move |_, _, _| { + spawn!(async move { + obj.redact_message().await; + }); + } + )) .build()]); }; @@ -547,15 +612,19 @@ impl ItemRow { if has_event_id && permissions.can_send_reaction() { action_group.add_action_entries([gio::ActionEntry::builder("toggle-reaction") .parameter_type(Some(&String::static_variant_type())) - .activate(clone!(@weak self as obj => move |_, _, variant| { - let Some(key) = variant.unwrap().get::() else { - return; - }; - - spawn!(async move { - obj.toggle_reaction(key).await; - }); - })) + .activate(clone!( + #[weak(rename_to = obj)] + self, + move |_, _, variant| { + let Some(key) = variant.unwrap().get::() else { + return; + }; + + spawn!(async move { + obj.toggle_reaction(key).await; + }); + } + )) .build()]); } @@ -563,14 +632,20 @@ impl ItemRow { action_group.add_action_entries([ // Reply. gio::ActionEntry::builder("reply") - .activate(clone!(@weak event, @weak self as widget => move |_, _, _| { - if let Some(event_id) = event.event_id() { - let _ = widget.activate_action( - "room-history.reply", - Some(&event_id.as_str().to_variant()) - ); + .activate(clone!( + #[weak] + event, + #[weak(rename_to = obj)] + self, + move |_, _, _| { + if let Some(event_id) = event.event_id() { + let _ = obj.activate_action( + "room-history.reply", + Some(&event_id.as_str().to_variant()), + ); + } } - })) + )) .build(), ]); } @@ -581,41 +656,61 @@ impl ItemRow { let body = text_message.body.clone(); action_group.add_action_entries([gio::ActionEntry::builder("copy-text") - .activate(clone!(@weak self as widget => move |_, _, _| { - widget.clipboard().set_text(&body); - toast!(widget, gettext("Text copied to clipboard")); - })) + .activate(clone!( + #[weak(rename_to = obj)] + self, + move |_, _, _| { + obj.clipboard().set_text(&body); + toast!(obj, gettext("Text copied to clipboard")); + } + )) .build()]); // Edit message. if has_event_id && is_from_own_user && permissions.can_send_message() { action_group.add_action_entries([gio::ActionEntry::builder("edit") - .activate(clone!(@weak event, @weak self as widget => move |_, _, _| { - if let Some(event_id) = event.event_id() { - let _ = widget.activate_action( - "room-history.edit", - Some(&event_id.as_str().to_variant()) - ); + .activate(clone!( + #[weak] + event, + #[weak(rename_to = obj)] + self, + move |_, _, _| { + if let Some(event_id) = event.event_id() { + let _ = obj.activate_action( + "room-history.edit", + Some(&event_id.as_str().to_variant()), + ); + } } - })) + )) .build()]); } } MessageType::File(content) => { // Save message's file. action_group.add_action_entries([gio::ActionEntry::builder("file-save") - .activate(clone!(@weak self as widget, @weak event => move |_, _, _| { - widget.save_event_file(event); - })) + .activate(clone!( + #[weak(rename_to = obj)] + self, + #[weak] + event, + move |_, _, _| { + obj.save_event_file(event); + } + )) .build()]); if let Some((caption, _)) = matrix_caption!(content) { // Copy caption. action_group.add_action_entries([gio::ActionEntry::builder("copy-text") - .activate(clone!(@weak self as widget => move |_, _, _| { - widget.clipboard().set_text(&caption); - toast!(widget, gettext("Text copied to clipboard")); - })) + .activate(clone!( + #[weak(rename_to = obj)] + self, + move |_, _, _| { + obj.clipboard().set_text(&caption); + toast!(obj, gettext("Text copied to clipboard")); + } + )) .build()]); } } @@ -624,25 +719,37 @@ impl ItemRow { let message = message.clone(); action_group.add_action_entries([gio::ActionEntry::builder("copy-text") - .activate(clone!(@weak self as widget, @weak event => move |_, _, _| { - let display_name = event.sender().display_name(); - let message = format!("{display_name} {}", message.body); - widget.clipboard().set_text(&message); - toast!(widget, gettext("Text copied to clipboard")); - })) + .activate(clone!( + #[weak(rename_to = obj)] + self, + #[weak] + event, + move |_, _, _| { + let display_name = event.sender().display_name(); + let message = format!("{display_name} {}", message.body); + obj.clipboard().set_text(&message); + toast!(obj, gettext("Text copied to clipboard")); + } + )) .build()]); // Edit message. if has_event_id && is_from_own_user && permissions.can_send_message() { action_group.add_action_entries([gio::ActionEntry::builder("edit") - .activate(clone!(@weak event, @weak self as widget => move |_, _, _| { - if let Some(event_id) = event.event_id() { - let _ = widget.activate_action( - "room-history.edit", - Some(&event_id.as_str().to_variant()) - ); + .activate(clone!( + #[weak] + event, + #[weak(rename_to = obj)] + self, + move |_, _, _| { + if let Some(event_id) = event.event_id() { + let _ = obj.activate_action( + "room-history.edit", + Some(&event_id.as_str().to_variant()), + ); + } } - })) + )) .build()]); } } @@ -651,77 +758,116 @@ impl ItemRow { let body = message.body.clone(); action_group.add_action_entries([gio::ActionEntry::builder("copy-text") - .activate(clone!(@weak self as widget => move |_, _, _| { - widget.clipboard().set_text(&body); - toast!(widget, gettext("Text copied to clipboard")); - })) + .activate(clone!( + #[weak(rename_to = obj)] + self, + move |_, _, _| { + obj.clipboard().set_text(&body); + toast!(obj, gettext("Text copied to clipboard")); + } + )) .build()]); } MessageType::Image(content) => { action_group.add_action_entries([ // Copy the texture to the clipboard. gio::ActionEntry::builder("copy-image") - .activate(clone!(@weak self as widget, @weak event => move |_, _, _| { - let texture = widget.child() - .and_downcast::() - .and_then(|r| r.texture()) - .expect("An ItemRow with an image should have a texture"); - - widget.clipboard().set_texture(&texture); - toast!(widget, gettext("Thumbnail copied to clipboard")); - })) + .activate(clone!( + #[weak(rename_to = obj)] + self, + move |_, _, _| { + let texture = obj + .child() + .and_downcast::() + .and_then(|r| r.texture()) + .expect("An ItemRow with an image should have a texture"); + + obj.clipboard().set_texture(&texture); + toast!(obj, gettext("Thumbnail copied to clipboard")); + } + )) .build(), // Save the image to a file. gio::ActionEntry::builder("save-image") - .activate(clone!(@weak self as widget, @weak event => move |_, _, _| { - widget.save_event_file(event); - })) + .activate(clone!( + #[weak(rename_to = obj)] + self, + #[weak] + event, + move |_, _, _| { + obj.save_event_file(event); + } + )) .build(), ]); if let Some((caption, _)) = matrix_caption!(content) { // Copy caption. action_group.add_action_entries([gio::ActionEntry::builder("copy-text") - .activate(clone!(@weak self as widget => move |_, _, _| { - widget.clipboard().set_text(&caption); - toast!(widget, gettext("Text copied to clipboard")); - })) + .activate(clone!( + #[weak(rename_to = obj)] + self, + move |_, _, _| { + obj.clipboard().set_text(&caption); + toast!(obj, gettext("Text copied to clipboard")); + } + )) .build()]); } } MessageType::Video(content) => { // Save the video to a file. action_group.add_action_entries([gio::ActionEntry::builder("save-video") - .activate(clone!(@weak self as widget, @weak event => move |_, _, _| { - widget.save_event_file(event); - })) + .activate(clone!( + #[weak(rename_to = obj)] + self, + #[weak] + event, + move |_, _, _| { + obj.save_event_file(event); + } + )) .build()]); if let Some((caption, _)) = matrix_caption!(content) { // Copy caption. action_group.add_action_entries([gio::ActionEntry::builder("copy-text") - .activate(clone!(@weak self as widget => move |_, _, _| { - widget.clipboard().set_text(&caption); - toast!(widget, gettext("Text copied to clipboard")); - })) + .activate(clone!( + #[weak(rename_to = obj)] + self, + move |_, _, _| { + obj.clipboard().set_text(&caption); + toast!(obj, gettext("Text copied to clipboard")); + } + )) .build()]); } } MessageType::Audio(content) => { // Save the audio to a file. action_group.add_action_entries([gio::ActionEntry::builder("save-audio") - .activate(clone!(@weak self as widget, @weak event => move |_, _, _| { - widget.save_event_file(event); - })) + .activate(clone!( + #[weak(rename_to = obj)] + self, + #[weak] + event, + move |_, _, _| { + obj.save_event_file(event); + } + )) .build()]); if let Some((caption, _)) = matrix_caption!(content) { // Copy caption. action_group.add_action_entries([gio::ActionEntry::builder("copy-text") - .activate(clone!(@weak self as widget => move |_, _, _| { - widget.clipboard().set_text(&caption); - toast!(widget, gettext("Text copied to clipboard")); - })) + .activate(clone!( + #[weak(rename_to = obj)] + self, + move |_, _, _| { + obj.clipboard().set_text(&caption); + toast!(obj, gettext("Text copied to clipboard")); + } + )) .build()]); } } @@ -739,19 +885,23 @@ impl ItemRow { /// See [`Event::get_media_content()`] for compatible events. /// Panics on an incompatible event. fn save_event_file(&self, event: Event) { - spawn!(clone!(@weak self as obj => async move { - let (filename, data) = match event.get_media_content().await { - Ok(res) => res, - Err(error) => { - error!("Could not get event file: {error}"); - toast!(obj, error.to_user_facing()); - - return; - } - }; + spawn!(clone!( + #[weak(rename_to = obj)] + self, + async move { + let (filename, data) = match event.get_media_content().await { + Ok(res) => res, + Err(error) => { + error!("Could not get event file: {error}"); + toast!(obj, error.to_user_facing()); + + return; + } + }; - save_to_file(&obj, data, filename).await; - })); + save_to_file(&obj, data, filename).await; + } + )); } /// Redact the event of this row. diff --git a/src/session/view/content/room_history/member_timestamp/row.rs b/src/session/view/content/room_history/member_timestamp/row.rs index a07c07a6..dc7631e5 100644 --- a/src/session/view/content/room_history/member_timestamp/row.rs +++ b/src/session/view/content/room_history/member_timestamp/row.rs @@ -48,10 +48,13 @@ mod imp { let obj = self.obj(); let system_settings = Application::default().system_settings(); - let system_settings_handler = - system_settings.connect_clock_format_notify(clone!(@weak obj => move |_| { + let system_settings_handler = system_settings.connect_clock_format_notify(clone!( + #[weak] + obj, + move |_| { obj.update_timestamp(); - })); + } + )); self.system_settings_handler .replace(Some(system_settings_handler)); } diff --git a/src/session/view/content/room_history/message_row/audio.rs b/src/session/view/content/room_history/message_row/audio.rs index 86b6a6a1..e67bad09 100644 --- a/src/session/view/content/room_history/message_row/audio.rs +++ b/src/session/view/content/room_history/message_row/audio.rs @@ -173,45 +173,53 @@ impl MessageAudio { spawn!( glib::Priority::LOW, - clone!(@weak self as obj => async move { - match handle.await.unwrap() { - Ok(Some(data)) => { - // The GStreamer backend doesn't work with input streams so - // we need to store the file. - // See: https://gitlab.gnome.org/GNOME/gtk/-/issues/4062 - let (file, _) = gio::File::new_tmp(None::).unwrap(); - file.replace_contents( - &data, - None, - false, - gio::FileCreateFlags::REPLACE_DESTINATION, - gio::Cancellable::NONE, - ) - .unwrap(); - obj.display_file(file); - } - Ok(None) => { - warn!("Could not retrieve invalid audio file"); - obj.set_error(gettext("Could not retrieve audio file")); - } - Err(error) => { - warn!("Could not retrieve audio file: {error}"); - obj.set_error(gettext("Could not retrieve audio file")); + clone!( + #[weak(rename_to = obj)] + self, + async move { + match handle.await.unwrap() { + Ok(Some(data)) => { + // The GStreamer backend doesn't work with input streams so + // we need to store the file. + // See: https://gitlab.gnome.org/GNOME/gtk/-/issues/4062 + let (file, _) = gio::File::new_tmp(None::).unwrap(); + file.replace_contents( + &data, + None, + false, + gio::FileCreateFlags::REPLACE_DESTINATION, + gio::Cancellable::NONE, + ) + .unwrap(); + obj.display_file(file); + } + Ok(None) => { + warn!("Could not retrieve invalid audio file"); + obj.set_error(gettext("Could not retrieve audio file")); + } + Err(error) => { + warn!("Could not retrieve audio file: {error}"); + obj.set_error(gettext("Could not retrieve audio file")); + } } } - }) + ) ); } fn display_file(&self, file: gio::File) { let media_file = gtk::MediaFile::for_file(&file); - media_file.connect_error_notify(clone!(@weak self as obj => move |media_file| { - if let Some(error) = media_file.error() { - warn!("Error reading audio file: {error}"); - obj.set_error(gettext("Error reading audio file")); + media_file.connect_error_notify(clone!( + #[weak(rename_to = obj)] + self, + move |media_file| { + if let Some(error) = media_file.error() { + warn!("Error reading audio file: {error}"); + obj.set_error(gettext("Error reading audio file")); + } } - })); + )); self.imp().player.set_media_file(Some(media_file)); self.set_state(MediaState::Ready); diff --git a/src/session/view/content/room_history/message_row/content.rs b/src/session/view/content/room_history/message_row/content.rs index 1d49e94e..3a966c23 100644 --- a/src/session/view/content/room_history/message_row/content.rs +++ b/src/session/view/content/room_history/message_row/content.rs @@ -118,11 +118,15 @@ impl MessageContent { TimelineDetails::Unavailable => { spawn!( glib::Priority::HIGH, - clone!(@weak event => async move { - if let Err(error) = event.fetch_missing_details().await { - error!("Could not fetch event details: {error}"); + clone!( + #[weak] + event, + async move { + if let Err(error) = event.fetch_missing_details().await { + error!("Could not fetch event details: {error}"); + } } - }) + ) ); } TimelineDetails::Error(error) => { diff --git a/src/session/view/content/room_history/message_row/media.rs b/src/session/view/content/room_history/message_row/media.rs index 014db095..924087fa 100644 --- a/src/session/view/content/room_history/message_row/media.rs +++ b/src/session/view/content/room_history/message_row/media.rs @@ -374,15 +374,20 @@ impl MessageMedia { spawn!( glib::Priority::LOW, - clone!(@weak self as obj => async move { - let imp = obj.imp(); - - match handle.await.unwrap() { - Ok(Some(data)) => { - match media_type { - MediaType::Image | MediaType::Sticker => { - match ImagePaintable::from_bytes(&glib::Bytes::from(&data), None) - { + clone!( + #[weak(rename_to = obj)] + self, + async move { + let imp = obj.imp(); + + match handle.await.unwrap() { + Ok(Some(data)) => { + match media_type { + MediaType::Image | MediaType::Sticker => { + match ImagePaintable::from_bytes( + &glib::Bytes::from(&data), + None, + ) { Ok(texture) => { let child = if let Some(child) = imp.media.child().and_downcast::() @@ -400,59 +405,65 @@ impl MessageMedia { if imp.media.has_css_class("content-thumbnail") { imp.media.remove_css_class("content-thumbnail"); } - } else if !imp.media.has_css_class("content-thumbnail") { + } else if !imp.media.has_css_class("content-thumbnail") + { imp.media.add_css_class("content-thumbnail"); } } Err(error) => { warn!("Image file not supported: {error}"); - imp.overlay_error.set_tooltip_text(Some(&gettext("Image file not supported"))); + imp.overlay_error.set_tooltip_text(Some(&gettext( + "Image file not supported", + ))); obj.set_state(MediaState::Error); } } - } - MediaType::Video => { - // The GStreamer backend of GtkVideo doesn't work with input streams so - // we need to store the file. - // See: https://gitlab.gnome.org/GNOME/gtk/-/issues/4062 - let (file, _) = gio::File::new_tmp(None::).unwrap(); - file.replace_contents( - &data, - None, - false, - gio::FileCreateFlags::REPLACE_DESTINATION, - gio::Cancellable::NONE, - ) - .unwrap(); - - let child = if let Some(child) = - imp.media.child().and_downcast::() - { - child - } else { - let child = VideoPlayer::new(); - imp.media.set_child(Some(&child)); - child - }; - child.set_compact(obj.compact()); - child.play_media_file(file) - } - }; - - obj.set_state(MediaState::Ready); - } - Ok(None) => { - warn!("Could not retrieve invalid media file"); - imp.overlay_error.set_tooltip_text(Some(&gettext("Could not retrieve media"))); - obj.set_state(MediaState::Error); - } - Err(error) => { - warn!("Could not retrieve media file: {error}"); - imp.overlay_error.set_tooltip_text(Some(&gettext("Could not retrieve media"))); - obj.set_state(MediaState::Error); + } + MediaType::Video => { + // The GStreamer backend of GtkVideo doesn't work with input + // streams so we need to + // store the file. See: https://gitlab.gnome.org/GNOME/gtk/-/issues/4062 + let (file, _) = gio::File::new_tmp(None::).unwrap(); + file.replace_contents( + &data, + None, + false, + gio::FileCreateFlags::REPLACE_DESTINATION, + gio::Cancellable::NONE, + ) + .unwrap(); + + let child = if let Some(child) = + imp.media.child().and_downcast::() + { + child + } else { + let child = VideoPlayer::new(); + imp.media.set_child(Some(&child)); + child + }; + child.set_compact(obj.compact()); + child.play_media_file(file) + } + }; + + obj.set_state(MediaState::Ready); + } + Ok(None) => { + warn!("Could not retrieve invalid media file"); + imp.overlay_error + .set_tooltip_text(Some(&gettext("Could not retrieve media"))); + obj.set_state(MediaState::Error); + } + Err(error) => { + warn!("Could not retrieve media file: {error}"); + imp.overlay_error + .set_tooltip_text(Some(&gettext("Could not retrieve media"))); + obj.set_state(MediaState::Error); + } } } - }) + ) ); } diff --git a/src/session/view/content/room_history/message_row/message_state_stack.rs b/src/session/view/content/room_history/message_row/message_state_stack.rs index 62c9c0f1..9f91b0de 100644 --- a/src/session/view/content/room_history/message_row/message_state_stack.rs +++ b/src/session/view/content/room_history/message_row/message_state_stack.rs @@ -74,9 +74,13 @@ mod imp { glib::timeout_add_seconds_local_once( SENT_VISIBLE_SECONDS, - clone!(@weak obj => move || { - obj.set_visible(false); - }), + clone!( + #[weak] + obj, + move || { + obj.set_visible(false); + } + ), ); } else { obj.set_visible(false); @@ -109,9 +113,13 @@ mod imp { glib::timeout_add_seconds_local_once( SENT_VISIBLE_SECONDS, - clone!(@weak stack => move || { - stack.set_visible_child_name("edited"); - }), + clone!( + #[weak] + stack, + move || { + stack.set_visible_child_name("edited"); + } + ), ); } else { stack.set_visible_child_name("edited"); diff --git a/src/session/view/content/room_history/message_row/mod.rs b/src/session/view/content/room_history/message_row/mod.rs index 9f601e74..a6e9a453 100644 --- a/src/session/view/content/room_history/message_row/mod.rs +++ b/src/session/view/content/room_history/message_row/mod.rs @@ -89,19 +89,25 @@ mod imp { self.parent_constructed(); let obj = self.obj(); - self.content - .connect_format_notify(clone!(@weak self as imp => move |content| + self.content.connect_format_notify(clone!( + #[weak(rename_to = imp)] + self, + move |content| { imp.reactions.set_visible(!matches!( content.format(), ContentFormat::Compact | ContentFormat::Ellipsized )); - )); + } + )); let system_settings = Application::default().system_settings(); - let system_settings_handler = - system_settings.connect_clock_format_notify(clone!(@weak obj => move |_| { + let system_settings_handler = system_settings.connect_clock_format_notify(clone!( + #[weak] + obj, + move |_| { obj.update_timestamp(); - })); + } + )); self.system_settings_handler .replace(Some(system_settings_handler)); } @@ -180,15 +186,23 @@ mod imp { state_binding, ]); - let timestamp_handler = event.connect_timestamp_notify(clone!(@weak obj => move |_| { - obj.update_timestamp(); - })); + let timestamp_handler = event.connect_timestamp_notify(clone!( + #[weak] + obj, + move |_| { + obj.update_timestamp(); + } + )); // Listening to changes in the source might not be enough, there are changes // that we display that don't affect the source, like related events. - let item_changed_handler = event.connect_item_changed(clone!(@weak obj => move |_| { - obj.update_content(); - })); + let item_changed_handler = event.connect_item_changed(clone!( + #[weak] + obj, + move |_| { + obj.update_content(); + } + )); self.reactions .set_reaction_list(&event.room().get_or_create_members(), &event.reactions()); diff --git a/src/session/view/content/room_history/message_row/reaction/mod.rs b/src/session/view/content/room_history/message_row/reaction/mod.rs index d3e8140d..421f47e4 100644 --- a/src/session/view/content/room_history/message_row/reaction/mod.rs +++ b/src/session/view/content/room_history/message_row/reaction/mod.rs @@ -106,10 +106,11 @@ mod imp { .sync_create() .build(); - let items_changed_handler_id = - group.connect_items_changed(clone!(@weak obj => move |group, pos, removed, added| - obj.items_changed(group, pos, removed, added) - )); + let items_changed_handler_id = group.connect_items_changed(clone!( + #[weak] + obj, + move |group, pos, removed, added| obj.items_changed(group, pos, removed, added) + )); obj.items_changed(&group, 0, self.list.n_items(), group.n_items()); self.group.set(&group, vec![items_changed_handler_id]); @@ -188,10 +189,13 @@ impl MessageReaction { .and_then(|r| r.member()) { // Listen to changes of the display name. - let handler_id = - member.connect_display_name_notify(clone!(@weak self as obj => move |member| { + let handler_id = member.connect_display_name_notify(clone!( + #[weak(rename_to = obj)] + self, + move |member| { obj.update_member_tooltip(member); - })); + } + )); imp.reaction_member.set(&member, vec![handler_id]); self.update_member_tooltip(&member); @@ -245,9 +249,9 @@ impl MessageReaction { let button = &*self.imp().button; let popover = ReactionPopover::new(&list); popover.set_parent(button); - popover.connect_closed(clone!(@weak button => move |popover| { + popover.connect_closed(|popover| { popover.unparent(); - })); + }); popover.popup(); } } diff --git a/src/session/view/content/room_history/message_row/reaction/reaction_popover.rs b/src/session/view/content/room_history/message_row/reaction/reaction_popover.rs index cdb9fa93..ea41565c 100644 --- a/src/session/view/content/room_history/message_row/reaction/reaction_popover.rs +++ b/src/session/view/content/room_history/message_row/reaction/reaction_popover.rs @@ -61,19 +61,25 @@ mod imp { self.senders.set(Some(&senders)); self.list .set_model(Some(>k::NoSelection::new(Some(senders)))); - self.list - .connect_activate(clone!(@weak obj => move |_, pos| { - let Some(member) = obj.senders() + self.list.connect_activate(clone!( + #[weak] + obj, + move |_, pos| { + let Some(member) = obj + .senders() .and_then(|list| list.item(pos)) .and_downcast::() .and_then(|ts| ts.member()) - else { return; }; + else { + return; + }; let dialog = UserProfileDialog::new(); dialog.set_room_member(member); dialog.present(&obj); obj.popdown(); - })); + } + )); } } } diff --git a/src/session/view/content/room_history/message_row/reaction_list.rs b/src/session/view/content/room_history/message_row/reaction_list.rs index d75998bc..c11fc3c0 100644 --- a/src/session/view/content/room_history/message_row/reaction_list.rs +++ b/src/session/view/content/room_history/message_row/reaction_list.rs @@ -54,7 +54,10 @@ impl MessageReactionList { self.imp().flow_box.bind_model( Some(reaction_list), clone!( - @weak members => @default-return { gtk::FlowBoxChild::new().upcast() }, + #[weak] + members, + #[upgrade_or_else] + || { gtk::FlowBoxChild::new().upcast() }, move |obj| { MessageReaction::new(members, obj.clone().downcast().unwrap()).upcast() } diff --git a/src/session/view/content/room_history/message_row/text/mod.rs b/src/session/view/content/room_history/message_row/text/mod.rs index 139b7d71..b5246daf 100644 --- a/src/session/view/content/room_history/message_row/text/mod.rs +++ b/src/session/view/content/room_history/message_row/text/mod.rs @@ -166,11 +166,15 @@ impl MessageText { self.set_is_html(true); self.set_original_text(formatted); - let handler = sender.connect_disambiguated_name_notify( - clone!(@weak self as obj, @weak room => move |sender| { + let handler = sender.connect_disambiguated_name_notify(clone!( + #[weak(rename_to = obj)] + self, + #[weak] + room, + move |sender| { obj.update_emote(&room, &sender.disambiguated_name()); - }), - ); + } + )); self.imp().sender.set(&sender, vec![handler]); return; @@ -193,11 +197,15 @@ impl MessageText { self.build_text(&body, room, Some(&sender_name)); self.set_original_text(body); - let handler = sender.connect_disambiguated_name_notify( - clone!(@weak self as obj, @weak room => move |sender| { + let handler = sender.connect_disambiguated_name_notify(clone!( + #[weak(rename_to = obj)] + self, + #[weak] + room, + move |sender| { obj.update_emote(&room, &sender.disambiguated_name()); - }), - ); + } + )); self.imp().sender.set(&sender, vec![handler]); } diff --git a/src/session/view/content/room_history/message_toolbar/completion/completion_popover.rs b/src/session/view/content/room_history/message_toolbar/completion/completion_popover.rs index adabd667..de3432cd 100644 --- a/src/session/view/content/room_history/message_toolbar/completion/completion_popover.rs +++ b/src/session/view/content/room_history/message_toolbar/completion/completion_popover.rs @@ -89,71 +89,90 @@ mod imp { if obj.parent().is_some() { let view = obj.view(); let buffer = view.buffer(); - let handler_id = - buffer.connect_cursor_position_notify(clone!(@weak obj => move |_| { + let handler_id = buffer.connect_cursor_position_notify(clone!( + #[weak] + obj, + move |_| { obj.update_completion(false); - })); + } + )); imp.buffer_handler.replace(Some((buffer, handler_id))); let key_events = gtk::EventControllerKey::new(); - key_events.connect_key_pressed(clone!(@weak obj => @default-return glib::Propagation::Proceed, move |_, key, _, modifier| { - if modifier.is_empty() { - if obj.is_visible() { - let imp = obj.imp(); - if matches!(key, gdk::Key::Return | gdk::Key::KP_Enter | gdk::Key::Tab) { - // Activate completion. - obj.activate_selected_row(); - return glib::Propagation::Stop; - } else if matches!(key, gdk::Key::Up | gdk::Key::KP_Up) { - // Move up, if possible. - let idx = obj.selected_row_index().unwrap_or_default(); - if idx > 0 { - obj.select_row_at_index(Some(idx - 1)); - } - return glib::Propagation::Stop; - } else if matches!(key, gdk::Key::Down | gdk::Key::KP_Down) { - // Move down, if possible. - let new_idx = if let Some(idx) = obj.selected_row_index() { - idx + 1 - } else { - 0 - }; - let n_members = imp.member_list.list().n_items() as usize; - let max = MAX_ROWS.min(n_members); - if new_idx < max { - obj.select_row_at_index(Some(new_idx)); + key_events.connect_key_pressed(clone!( + #[weak] + obj, + #[upgrade_or] + glib::Propagation::Proceed, + move |_, key, _, modifier| { + if modifier.is_empty() { + if obj.is_visible() { + let imp = obj.imp(); + if matches!( + key, + gdk::Key::Return | gdk::Key::KP_Enter | gdk::Key::Tab + ) { + // Activate completion. + obj.activate_selected_row(); + return glib::Propagation::Stop; + } else if matches!(key, gdk::Key::Up | gdk::Key::KP_Up) { + // Move up, if possible. + let idx = obj.selected_row_index().unwrap_or_default(); + if idx > 0 { + obj.select_row_at_index(Some(idx - 1)); + } + return glib::Propagation::Stop; + } else if matches!(key, gdk::Key::Down | gdk::Key::KP_Down) { + // Move down, if possible. + let new_idx = if let Some(idx) = obj.selected_row_index() { + idx + 1 + } else { + 0 + }; + let n_members = imp.member_list.list().n_items() as usize; + let max = MAX_ROWS.min(n_members); + if new_idx < max { + obj.select_row_at_index(Some(new_idx)); + } + return glib::Propagation::Stop; + } else if matches!(key, gdk::Key::Escape) { + // Close. + obj.inhibit(); + return glib::Propagation::Stop; } - return glib::Propagation::Stop; - } else if matches!(key, gdk::Key::Escape) { - // Close. - obj.inhibit(); + } else if matches!(key, gdk::Key::Tab) { + obj.update_completion(true); return glib::Propagation::Stop; } - } else if matches!(key, gdk::Key::Tab) { - obj.update_completion(true); - return glib::Propagation::Stop; } + glib::Propagation::Proceed } - glib::Propagation::Proceed - })); + )); view.add_controller(key_events); // Close popup when the entry is not focused. - view.connect_has_focus_notify(clone!(@weak obj => move |view| { - if !view.has_focus() && obj.get_visible() { - obj.popdown(); + view.connect_has_focus_notify(clone!( + #[weak] + obj, + move |view| { + if !view.has_focus() && obj.get_visible() { + obj.popdown(); + } } - })); + )); } }); - self.list - .connect_row_activated(clone!(@weak obj => move |_, row| { + self.list.connect_row_activated(clone!( + #[weak] + obj, + move |_, row| { if let Some(row) = row.downcast_ref::() { obj.row_activated(row); } - })); + } + )); } } diff --git a/src/session/view/content/room_history/message_toolbar/completion/member_list.rs b/src/session/view/content/room_history/message_toolbar/completion/member_list.rs index a8c341ac..4a49bb98 100644 --- a/src/session/view/content/room_history/message_toolbar/completion/member_list.rs +++ b/src/session/view/content/room_history/message_toolbar/completion/member_list.rs @@ -186,17 +186,23 @@ mod imp { } if let Some(room) = members.as_ref().and_then(|m| m.room()) { - let room_handler = - room.connect_is_direct_notify(clone!(@weak self as imp => move |_| { + let room_handler = room.connect_is_direct_notify(clone!( + #[weak(rename_to = imp)] + self, + move |_| { imp.update_at_room_model(); - })); + } + )); self.room_handler.replace(Some(room_handler)); - let permissions_handler = room.permissions().connect_can_notify_room_notify( - clone!(@weak self as imp => move |_| { - imp.update_at_room_model(); - }), - ); + let permissions_handler = + room.permissions().connect_can_notify_room_notify(clone!( + #[weak(rename_to = imp)] + self, + move |_| { + imp.update_at_room_model(); + } + )); self.permissions_handler.replace(Some(permissions_handler)); } diff --git a/src/session/view/content/room_history/message_toolbar/mod.rs b/src/session/view/content/room_history/message_toolbar/mod.rs index e11ca190..cb893d36 100644 --- a/src/session/view/content/room_history/message_toolbar/mod.rs +++ b/src/session/view/content/room_history/message_toolbar/mod.rs @@ -156,8 +156,10 @@ mod imp { let obj = self.obj(); // Clipboard. - self.message_entry - .connect_paste_clipboard(clone!(@weak obj => move |entry| { + self.message_entry.connect_paste_clipboard(clone!( + #[weak] + obj, + move |entry| { if !obj.imp().can_send_message() { return; } @@ -173,41 +175,61 @@ mod imp { obj.read_clipboard_file().await; }); } - })); - self.message_entry - .connect_copy_clipboard(clone!(@weak obj => move |entry| { + } + )); + self.message_entry.connect_copy_clipboard(clone!( + #[weak] + obj, + move |entry| { entry.stop_signal_emission_by_name("copy-clipboard"); spawn!(async move { obj.copy_buffer_selection_to_clipboard().await; }); - })); - self.message_entry - .connect_cut_clipboard(clone!(@weak obj => move |entry| { + } + )); + self.message_entry.connect_cut_clipboard(clone!( + #[weak] + obj, + move |entry| { entry.stop_signal_emission_by_name("cut-clipboard"); - spawn!(clone!(@weak entry => async move { - obj.copy_buffer_selection_to_clipboard().await; - entry.buffer().delete_selection(true, true); - })); - })); + spawn!(clone!( + #[weak] + entry, + async move { + obj.copy_buffer_selection_to_clipboard().await; + entry.buffer().delete_selection(true, true); + } + )); + } + )); // Key bindings. let key_events = gtk::EventControllerKey::new(); - key_events - .connect_key_pressed(clone!(@weak obj => @default-return glib::Propagation::Proceed, move |_, key, _, modifier| { - if modifier.is_empty() && (key == gdk::Key::Return || key == gdk::Key::KP_Enter) { - spawn!(async move { - obj.send_text_message().await; - }); - glib::Propagation::Stop - } else if modifier.is_empty() && key == gdk::Key::Escape && obj.related_event_type() != RelatedEventType::None { - obj.clear_related_event(); - glib::Propagation::Stop - } else { - glib::Propagation::Proceed + key_events.connect_key_pressed(clone!( + #[weak] + obj, + #[upgrade_or] + glib::Propagation::Proceed, + move |_, key, _, modifier| { + if modifier.is_empty() && (key == gdk::Key::Return || key == gdk::Key::KP_Enter) + { + spawn!(async move { + obj.send_text_message().await; + }); + glib::Propagation::Stop + } else if modifier.is_empty() + && key == gdk::Key::Escape + && obj.related_event_type() != RelatedEventType::None + { + obj.clear_related_event(); + glib::Propagation::Stop + } else { + glib::Propagation::Proceed + } } - })); + )); self.message_entry.add_controller(key_events); let buffer = self @@ -219,12 +241,16 @@ mod imp { crate::utils::sourceview::setup_style_scheme(&buffer); // Actions on changes in message entry. - buffer.connect_text_notify(clone!(@weak obj => move |buffer| { - let (start_iter, end_iter) = buffer.bounds(); - let is_empty = start_iter == end_iter; - obj.action_set_enabled("message-toolbar.send-text-message", !is_empty); - obj.send_typing_notification(!is_empty); - })); + buffer.connect_text_notify(clone!( + #[weak] + obj, + move |buffer| { + let (start_iter, end_iter) = buffer.bounds(); + let is_empty = start_iter == end_iter; + obj.action_set_enabled("message-toolbar.send-text-message", !is_empty); + obj.send_typing_notification(!is_empty); + } + )); let (start_iter, end_iter) = buffer.bounds(); obj.action_set_enabled("message-toolbar.send-text-message", start_iter != end_iter); @@ -283,11 +309,14 @@ mod imp { obj.clear_related_event(); if let Some(room) = &room { - let can_send_message_handler = room.permissions().connect_can_send_message_notify( - clone!(@weak self as imp => move |_| { - imp.can_send_message_updated(); - }), - ); + let can_send_message_handler = + room.permissions().connect_can_send_message_notify(clone!( + #[weak(rename_to = imp)] + self, + move |_| { + imp.can_send_message_updated(); + } + )); self.can_send_message_handler .replace(Some(can_send_message_handler)); } @@ -985,9 +1014,13 @@ impl MessageToolbar { return; } - spawn!(clone!(@weak self as obj => async move { - obj.read_clipboard_file().await; - })); + spawn!(clone!( + #[weak(rename_to = obj)] + self, + async move { + obj.read_clipboard_file().await; + } + )); } // Copy the selection in the message entry to the clipboard while replacing diff --git a/src/session/view/content/room_history/mod.rs b/src/session/view/content/room_history/mod.rs index 4d493cd5..5f0c82cc 100644 --- a/src/session/view/content/room_history/mod.rs +++ b/src/session/view/content/room_history/mod.rs @@ -252,17 +252,21 @@ mod imp { let obj = self.obj(); let factory = gtk::SignalListItemFactory::new(); - factory.connect_setup(clone!(@weak obj => move |_, item| { - let Some(item) = item.downcast_ref::() else { - error!("List item factory did not receive a list item: {item:?}"); - return; - }; - let row = ItemRow::new(&obj); - item.set_child(Some(&row)); - item.bind_property("item", &row, "item").build(); - item.set_activatable(false); - item.set_selectable(false); - })); + factory.connect_setup(clone!( + #[weak] + obj, + move |_, item| { + let Some(item) = item.downcast_ref::() else { + error!("List item factory did not receive a list item: {item:?}"); + return; + }; + let row = ItemRow::new(&obj); + item.set_child(Some(&row)); + item.bind_property("item", &row, "item").build(); + item.set_activatable(false); + item.set_selectable(false); + } + )); self.listview.set_factory(Some(&factory)); // Needed to use the natural height of GtkPictures @@ -274,44 +278,56 @@ mod imp { obj.set_sticky(true); let adj = self.listview.vadjustment().unwrap(); - adj.connect_value_changed(clone!(@weak obj => move |_| { - let imp = obj.imp(); - - obj.trigger_read_receipts_update(); - - let is_at_bottom = obj.is_at_bottom(); - if imp.is_auto_scrolling.get() { - if is_at_bottom { - imp.is_auto_scrolling.set(false); - obj.set_sticky(true); + adj.connect_value_changed(clone!( + #[weak] + obj, + move |_| { + let imp = obj.imp(); + + obj.trigger_read_receipts_update(); + + let is_at_bottom = obj.is_at_bottom(); + if imp.is_auto_scrolling.get() { + if is_at_bottom { + imp.is_auto_scrolling.set(false); + obj.set_sticky(true); + } else { + obj.scroll_down(); + } } else { - obj.scroll_down(); + obj.set_sticky(is_at_bottom); } - } else { - obj.set_sticky(is_at_bottom); - } - // Remove the typing row if we scroll up. - if !is_at_bottom { - if let Some(room) = obj.room() { - room.timeline().remove_empty_typing_row(); + // Remove the typing row if we scroll up. + if !is_at_bottom { + if let Some(room) = obj.room() { + room.timeline().remove_empty_typing_row(); + } } - } - obj.start_loading(); - })); - adj.connect_upper_notify(clone!(@weak obj => move |_| { - if obj.sticky() { - obj.scroll_down(); + obj.start_loading(); + } + )); + adj.connect_upper_notify(clone!( + #[weak] + obj, + move |_| { + if obj.sticky() { + obj.scroll_down(); + } + obj.start_loading(); } - obj.start_loading(); - })); - adj.connect_page_size_notify(clone!(@weak obj => move |_| { - if obj.sticky() { - obj.scroll_down(); + )); + adj.connect_page_size_notify(clone!( + #[weak] + obj, + move |_| { + if obj.sticky() { + obj.scroll_down(); + } + obj.start_loading(); } - obj.start_loading(); - })); + )); } fn setup_drop_target(&self) { @@ -322,8 +338,12 @@ mod imp { gdk::DragAction::COPY | gdk::DragAction::MOVE, ); - target.connect_drop( - clone!(@weak obj => @default-return false, move |_, value, _, _| { + target.connect_drop(clone!( + #[weak] + obj, + #[upgrade_or] + false, + move |_, value, _, _| { match value.get::() { Ok(file) => { spawn!(async move { @@ -333,16 +353,13 @@ mod imp { } Err(error) => { warn!("Could not get file from drop: {error:?}"); - toast!( - obj, - gettext("Error getting file from drop") - ); + toast!(obj, gettext("Error getting file from drop")); false } } - }), - ); + } + )); self.drag_overlay.set_drop_target(target); } @@ -393,34 +410,47 @@ mod imp { self.room_members .replace(Some(room.get_or_create_members())); - let membership_handler = - room.own_member() - .connect_membership_notify(clone!(@weak obj => move |_| { - obj.update_room_menu(); - })); + let membership_handler = room.own_member().connect_membership_notify(clone!( + #[weak] + obj, + move |_| { + obj.update_room_menu(); + } + )); self.membership_handler.replace(Some(membership_handler)); - let join_rule_handler = - room.join_rule() - .connect_we_can_join_notify(clone!(@weak obj => move |_| { - obj.update_room_menu(); - })); + let join_rule_handler = room.join_rule().connect_we_can_join_notify(clone!( + #[weak] + obj, + move |_| { + obj.update_room_menu(); + } + )); self.join_rule_handler.replace(Some(join_rule_handler)); - let tombstoned_handler = - room.connect_is_tombstoned_notify(clone!(@weak obj => move |_| { + let tombstoned_handler = room.connect_is_tombstoned_notify(clone!( + #[weak] + obj, + move |_| { obj.update_tombstoned_banner(); - })); + } + )); - let successor_handler = - room.connect_successor_id_string_notify(clone!(@weak obj => move |_| { + let successor_handler = room.connect_successor_id_string_notify(clone!( + #[weak] + obj, + move |_| { obj.update_tombstoned_banner(); - })); + } + )); - let successor_room_handler = - room.connect_successor_notify(clone!(@weak obj => move |_| { + let successor_room_handler = room.connect_successor_notify(clone!( + #[weak] + obj, + move |_| { obj.update_tombstoned_banner(); - })); + } + )); self.room.set( room, @@ -431,19 +461,26 @@ mod imp { ], ); - let empty_handler = timeline.connect_empty_notify(clone!(@weak obj => move |_| { - obj.update_view(); - })); + let empty_handler = timeline.connect_empty_notify(clone!( + #[weak] + obj, + move |_| { + obj.update_view(); + } + )); - let state_handler = - timeline.connect_state_notify(clone!(@weak obj => move |timeline| { + let state_handler = timeline.connect_state_notify(clone!( + #[weak] + obj, + move |timeline| { obj.update_view(); // Always test if we need to load more when timeline is ready. if timeline.state() == TimelineState::Ready { obj.start_loading(); } - })); + } + )); self.timeline_handlers .replace(vec![empty_handler, state_handler]); @@ -592,10 +629,13 @@ impl RoomHistory { }; let permissions = room.permissions(); - let can_invite_handler = - permissions.connect_can_invite_notify(clone!(@weak self as obj => move |permissions| { + let can_invite_handler = permissions.connect_can_invite_notify(clone!( + #[weak(rename_to = obj)] + self, + move |permissions| { obj.action_set_enabled("room-history.invite-members", permissions.can_invite()); - })); + } + )); self.imp() .can_invite_handler .replace(Some(can_invite_handler)); @@ -809,9 +849,13 @@ impl RoomHistory { imp.scroll_timeout .replace(Some(glib::timeout_add_local_once( SCROLL_TIMEOUT, - clone!(@weak self as obj => move || { - obj.update_read_receipts(); - }), + clone!( + #[weak(rename_to = obj)] + self, + move || { + obj.update_read_receipts(); + } + ), ))); } } @@ -827,18 +871,26 @@ impl RoomHistory { imp.read_timeout.replace(Some(glib::timeout_add_local_once( READ_TIMEOUT, - clone!(@weak self as obj => move || { - obj.update_read_marker(); - }), + clone!( + #[weak(rename_to = obj)] + self, + move || { + obj.update_read_marker(); + } + ), ))); let Some(position) = self.receipt_position() else { return; }; - spawn!(clone!(@weak self as obj => async move { - obj.send_receipt(ReceiptType::Read, position).await; - })); + spawn!(clone!( + #[weak(rename_to = obj)] + self, + async move { + obj.send_receipt(ReceiptType::Read, position).await; + } + )); } /// Update the read marker. @@ -850,9 +902,13 @@ impl RoomHistory { return; }; - spawn!(clone!(@weak self as obj => async move { - obj.send_receipt(ReceiptType::FullyRead, position).await; - })); + spawn!(clone!( + #[weak(rename_to = obj)] + self, + async move { + obj.send_receipt(ReceiptType::FullyRead, position).await; + } + )); } /// The position where a receipt should point to. diff --git a/src/session/view/content/room_history/read_receipts_list/mod.rs b/src/session/view/content/room_history/read_receipts_list/mod.rs index a258cb32..b2b10d6e 100644 --- a/src/session/view/content/room_history/read_receipts_list/mod.rs +++ b/src/session/view/content/room_history/read_receipts_list/mod.rs @@ -109,11 +109,14 @@ mod imp { .unwrap() }); - self.list - .connect_items_changed(clone!(@weak obj => move |_, _,_,_| { + self.list.connect_items_changed(clone!( + #[weak] + obj, + move |_, _, _, _| { obj.update_tooltip(); obj.update_label(); - })); + } + )); obj.set_pressed_state(false); } @@ -193,11 +196,13 @@ impl ReadReceiptsList { pub fn set_source(&self, source: &gio::ListStore) { let imp = self.imp(); - let items_changed_handler_id = source.connect_items_changed( - clone!(@weak self as obj => move |source, pos, removed, added| { + let items_changed_handler_id = source.connect_items_changed(clone!( + #[weak(rename_to = obj)] + self, + move |source, pos, removed, added| { obj.items_changed(source, pos, removed, added); - }), - ); + } + )); self.items_changed(source, 0, self.list().n_items(), source.n_items()); imp.source.set(source, vec![items_changed_handler_id]); @@ -241,10 +246,13 @@ impl ReadReceiptsList { .and_then(|r| r.member()) { // Listen to changes of the display name. - let handler_id = - member.connect_display_name_notify(clone!(@weak self as obj => move |member| { + let handler_id = member.connect_display_name_notify(clone!( + #[weak(rename_to = obj)] + self, + move |member| { obj.update_member_tooltip(member); - })); + } + )); imp.receipt_member.set(&member, vec![handler_id]); self.update_member_tooltip(&member); @@ -301,10 +309,14 @@ impl ReadReceiptsList { let popover = ReadReceiptsPopover::new(&list); popover.set_parent(self); popover.set_pointing_to(Some(&gdk::Rectangle::new(x as i32, y as i32, 0, 0))); - popover.connect_closed(clone!(@weak self as obj => move |popover| { - popover.unparent(); - obj.set_active(false); - })); + popover.connect_closed(clone!( + #[weak(rename_to = obj)] + self, + move |popover| { + popover.unparent(); + obj.set_active(false); + } + )); popover.popup(); } diff --git a/src/session/view/content/room_history/read_receipts_list/read_receipts_popover.rs b/src/session/view/content/room_history/read_receipts_list/read_receipts_popover.rs index a9bc1682..2c1118f3 100644 --- a/src/session/view/content/room_history/read_receipts_list/read_receipts_popover.rs +++ b/src/session/view/content/room_history/read_receipts_list/read_receipts_popover.rs @@ -66,19 +66,25 @@ mod imp { self.receipts.set(Some(&receipts)); self.list .set_model(Some(>k::NoSelection::new(Some(receipts)))); - self.list - .connect_activate(clone!(@weak obj => move |_, pos| { - let Some(member) = obj.receipts() + self.list.connect_activate(clone!( + #[weak] + obj, + move |_, pos| { + let Some(member) = obj + .receipts() .and_then(|list| list.item(pos)) .and_downcast::() .and_then(|ts| ts.member()) - else { return; }; + else { + return; + }; let dialog = UserProfileDialog::new(); dialog.set_room_member(member); dialog.present(&obj); obj.popdown(); - })); + } + )); } } } diff --git a/src/session/view/content/room_history/sender_avatar/mod.rs b/src/session/view/content/room_history/sender_avatar/mod.rs index 4f9c4225..23ecd3e6 100644 --- a/src/session/view/content/room_history/sender_avatar/mod.rs +++ b/src/session/view/content/room_history/sender_avatar/mod.rs @@ -215,32 +215,46 @@ mod imp { self.sender.disconnect_signals(); if let Some(sender) = sender { - let permissions_handler = sender.room().permissions().connect_changed( - clone!(@weak self as imp => move |_| { + let permissions_handler = sender.room().permissions().connect_changed(clone!( + #[weak(rename_to = imp)] + self, + move |_| { imp.update_actions(); - }), - ); + } + )); self.permissions_handler.replace(Some(permissions_handler)); - let display_name_handler = - sender.connect_display_name_notify(clone!(@weak self as imp => move |_| { + let display_name_handler = sender.connect_display_name_notify(clone!( + #[weak(rename_to = imp)] + self, + move |_| { imp.update_accessible_label(); - })); + } + )); - let membership_handler = - sender.connect_membership_notify(clone!(@weak self as imp => move |_| { + let membership_handler = sender.connect_membership_notify(clone!( + #[weak(rename_to = imp)] + self, + move |_| { imp.update_actions(); - })); + } + )); - let power_level_handler = - sender.connect_power_level_notify(clone!(@weak self as imp => move |_| { + let power_level_handler = sender.connect_power_level_notify(clone!( + #[weak(rename_to = imp)] + self, + move |_| { imp.update_actions(); - })); + } + )); - let is_ignored_handler = - sender.connect_is_ignored_notify(clone!(@weak self as imp => move |_| { + let is_ignored_handler = sender.connect_is_ignored_notify(clone!( + #[weak(rename_to = imp)] + self, + move |_| { imp.update_actions(); - })); + } + )); self.sender.set( sender, @@ -385,18 +399,25 @@ mod imp { popover.unparent(); } - let parent_handler = - popover.connect_parent_notify(clone!(@weak obj => move |popover| { + let parent_handler = popover.connect_parent_notify(clone!( + #[weak] + obj, + move |popover| { if !popover.parent().is_some_and(|w| w == obj) { let imp = obj.imp(); imp.popover.disconnect_signals(); popover.remove_child(&*imp.user_id_btn); } - })); - let closed_handler = popover.connect_closed(clone!(@weak obj => move |_| { - obj.set_active(false); - })); + } + )); + let closed_handler = popover.connect_closed(clone!( + #[weak] + obj, + move |_| { + obj.set_active(false); + } + )); popover.add_child(&*self.user_id_btn, "user-id"); popover.set_parent(&*obj); diff --git a/src/session/view/content/room_history/state_row/tombstone.rs b/src/session/view/content/room_history/state_row/tombstone.rs index aab3466d..60436572 100644 --- a/src/session/view/content/room_history/state_row/tombstone.rs +++ b/src/session/view/content/room_history/state_row/tombstone.rs @@ -49,16 +49,22 @@ mod imp { fn set_room(&self, room: Room) { let obj = self.obj(); - let successor_handler = - room.connect_successor_id_string_notify(clone!(@weak self as imp => move |room| { + let successor_handler = room.connect_successor_id_string_notify(clone!( + #[weak(rename_to = imp)] + self, + move |room| { imp.new_room_btn.set_visible(room.successor_id().is_some()); - })); + } + )); self.new_room_btn.set_visible(room.successor_id().is_some()); - let successor_room_handler = - room.connect_successor_notify(clone!(@weak obj => move |room| { + let successor_room_handler = room.connect_successor_notify(clone!( + #[weak] + obj, + move |room| { obj.update_button_label(room); - })); + } + )); obj.update_button_label(&room); self.room diff --git a/src/session/view/content/room_history/typing_row.rs b/src/session/view/content/room_history/typing_row.rs index 6b778d6e..dcc580ac 100644 --- a/src/session/view/content/room_history/typing_row.rs +++ b/src/session/view/content/room_history/typing_row.rs @@ -69,15 +69,20 @@ mod imp { self.list.disconnect_signals(); if let Some(list) = list { - let items_changed_handler_id = list.connect_items_changed( - clone!(@weak obj => move |list, _pos, removed, added| { + let items_changed_handler_id = list.connect_items_changed(clone!( + #[weak] + obj, + move |list, _pos, removed, added| { if removed != 0 || added != 0 { obj.update_label(list); } - }), - ); - let is_empty_notify_handler_id = list - .connect_is_empty_notify(clone!(@weak obj => move |_| obj.notify_is_empty())); + } + )); + let is_empty_notify_handler_id = list.connect_is_empty_notify(clone!( + #[weak] + obj, + move |_| obj.notify_is_empty() + )); self.avatar_list.bind_model(Some(list.clone()), |item| { item.downcast_ref::().unwrap().avatar_data().clone() diff --git a/src/session/view/content/room_history/verification_info_bar.rs b/src/session/view/content/room_history/verification_info_bar.rs index a55097c1..b7599929 100644 --- a/src/session/view/content/room_history/verification_info_bar.rs +++ b/src/session/view/content/room_history/verification_info_bar.rs @@ -128,17 +128,22 @@ mod imp { self.verification.disconnect_signals(); if let Some(verification) = &verification { - let user_handler = verification.user().connect_display_name_notify( - clone!(@weak self as imp => move |_| { + let user_handler = verification.user().connect_display_name_notify(clone!( + #[weak(rename_to = imp)] + self, + move |_| { imp.update_bar(); - }), - ); + } + )); self.user_handler.replace(Some(user_handler)); - let state_handler = - verification.connect_state_notify(clone!(@weak self as imp => move |_| { + let state_handler = verification.connect_state_notify(clone!( + #[weak(rename_to = imp)] + self, + move |_| { imp.update_bar(); - })); + } + )); self.verification.set(verification, vec![state_handler]); } diff --git a/src/session/view/create_dm_dialog/dm_user_list.rs b/src/session/view/create_dm_dialog/dm_user_list.rs index f2f7de78..11d90f55 100644 --- a/src/session/view/create_dm_dialog/dm_user_list.rs +++ b/src/session/view/create_dm_dialog/dm_user_list.rs @@ -80,9 +80,13 @@ mod imp { self.search_term.replace(search_term); - spawn!(clone!(@weak obj => async move { - obj.search_users().await; - })); + spawn!(clone!( + #[weak] + obj, + async move { + obj.search_users().await; + } + )); obj.notify_search_term(); } @@ -181,9 +185,13 @@ impl DmUserList { // If it is the "custom user" from the search term, fetch the avatar // and display name if add_custom && *user.user_id() == search_term { - spawn!(clone!(@weak user => async move { - user.load_profile().await; - })); + spawn!(clone!( + #[weak] + user, + async move { + user.load_profile().await; + } + )); } users.push(user); diff --git a/src/session/view/create_dm_dialog/mod.rs b/src/session/view/create_dm_dialog/mod.rs index 9440494d..c32ec1a1 100644 --- a/src/session/view/create_dm_dialog/mod.rs +++ b/src/session/view/create_dm_dialog/mod.rs @@ -88,9 +88,13 @@ mod imp { // We don't need to disconnect this signal since the `DmUserList` will be // disposed once unbound from the `gtk::ListBox` - user_list.connect_state_notify(clone!(@weak obj => move |model| { - obj.update_view(model); - })); + user_list.connect_state_notify(clone!( + #[weak] + obj, + move |model| { + obj.update_view(model); + } + )); self.search_entry .bind_property("text", &user_list, "search-term") diff --git a/src/session/view/media_viewer.rs b/src/session/view/media_viewer.rs index fd815b52..1a9af4d7 100644 --- a/src/session/view/media_viewer.rs +++ b/src/session/view/media_viewer.rs @@ -115,48 +115,68 @@ mod imp { self.parent_constructed(); let obj = self.obj(); - let target = adw::CallbackAnimationTarget::new(clone!(@weak obj => move |value| { - // This is needed to fade the header bar content - obj.imp().header_bar.set_opacity(value); - - obj.queue_draw(); - })); + let target = adw::CallbackAnimationTarget::new(clone!( + #[weak] + obj, + move |value| { + // This is needed to fade the header bar content + obj.imp().header_bar.set_opacity(value); + + obj.queue_draw(); + } + )); let animation = adw::TimedAnimation::new(&*obj, 0.0, 1.0, ANIMATION_DURATION, target); self.animation.set(animation).unwrap(); let swipe_tracker = adw::SwipeTracker::new(&*obj); swipe_tracker.set_orientation(gtk::Orientation::Vertical); - swipe_tracker.connect_update_swipe(clone!(@weak obj => move |_, progress| { - obj.imp().header_bar.set_opacity(0.0); - obj.imp().swipe_progress.set(progress); - obj.queue_allocate(); - obj.queue_draw(); - })); - swipe_tracker.connect_end_swipe(clone!(@weak obj => move |_, _, to| { - if to == 0.0 { - let target = adw::CallbackAnimationTarget::new(clone!(@weak obj => move |value| { - obj.imp().swipe_progress.set(value); - obj.queue_allocate(); - obj.queue_draw(); - })); - let swipe_progress = obj.imp().swipe_progress.get(); - let animation = adw::TimedAnimation::new( - &obj, - swipe_progress, - 0.0, - CANCEL_SWIPE_ANIMATION_DURATION, - target, - ); - animation.set_easing(adw::Easing::EaseOutCubic); - animation.connect_done(clone!(@weak obj => move |_| { + swipe_tracker.connect_update_swipe(clone!( + #[weak] + obj, + move |_, progress| { + obj.imp().header_bar.set_opacity(0.0); + obj.imp().swipe_progress.set(progress); + obj.queue_allocate(); + obj.queue_draw(); + } + )); + swipe_tracker.connect_end_swipe(clone!( + #[weak] + obj, + move |_, _, to| { + if to == 0.0 { + let target = adw::CallbackAnimationTarget::new(clone!( + #[weak] + obj, + move |value| { + obj.imp().swipe_progress.set(value); + obj.queue_allocate(); + obj.queue_draw(); + } + )); + let swipe_progress = obj.imp().swipe_progress.get(); + let animation = adw::TimedAnimation::new( + &obj, + swipe_progress, + 0.0, + CANCEL_SWIPE_ANIMATION_DURATION, + target, + ); + animation.set_easing(adw::Easing::EaseOutCubic); + animation.connect_done(clone!( + #[weak] + obj, + move |_| { + obj.imp().header_bar.set_opacity(1.0); + } + )); + animation.play(); + } else { + obj.close(); obj.imp().header_bar.set_opacity(1.0); - })); - animation.play(); - } else { - obj.close(); - obj.imp().header_bar.set_opacity(1.0); + } } - })); + )); self.swipe_tracker.set(swipe_tracker).unwrap(); // Bind `fullscreened` to the window property of the same name. @@ -169,12 +189,15 @@ mod imp { } }); - self.revealer - .connect_transition_done(clone!(@weak obj => move |revealer| { + self.revealer.connect_transition_done(clone!( + #[weak] + obj, + move |revealer| { if !revealer.reveal_child() { obj.set_visible(false); } - })); + } + )); obj.update_menu_actions(); } @@ -370,24 +393,33 @@ impl MediaViewer { spawn!( glib::Priority::LOW, - clone!(@weak self as obj => async move { - let imp = obj.imp(); - - match get_media_content(client, message).await { - Ok(( _, data)) => { - match ImagePaintable::from_bytes(&glib::Bytes::from(&data), image.info.and_then(|info| info.mimetype).as_deref()) { - Ok(texture) => { - imp.media.view_image(&texture); - return; + clone!( + #[weak(rename_to = obj)] + self, + async move { + let imp = obj.imp(); + + match get_media_content(client, message).await { + Ok((_, data)) => { + match ImagePaintable::from_bytes( + &glib::Bytes::from(&data), + image.info.and_then(|info| info.mimetype).as_deref(), + ) { + Ok(texture) => { + imp.media.view_image(&texture); + return; + } + Err(error) => { + warn!("Could not load GdkTexture from file: {error}") + } } - Err(error) => warn!("Could not load GdkTexture from file: {error}"), } + Err(error) => warn!("Could not retrieve image file: {error}"), } - Err(error) => warn!("Could not retrieve image file: {error}"), - } - imp.media.show_fallback(ContentType::Image); - }) + imp.media.show_fallback(ContentType::Image); + } + ) ); } MessageType::Video(video) => { @@ -395,32 +427,36 @@ impl MediaViewer { spawn!( glib::Priority::LOW, - clone!(@weak self as obj => async move { - let imp = obj.imp(); - - match get_media_content(client, message).await { - Ok(( _, data)) => { - // The GStreamer backend of GtkVideo doesn't work with input streams so - // we need to store the file. - // See: https://gitlab.gnome.org/GNOME/gtk/-/issues/4062 - let (file, _) = gio::File::new_tmp(None::).unwrap(); - file.replace_contents( - &data, - None, - false, - gio::FileCreateFlags::REPLACE_DESTINATION, - gio::Cancellable::NONE, - ) - .unwrap(); - - imp.media.view_file(file); - } - Err(error) => { - warn!("Could not retrieve video file: {error}"); - imp.media.show_fallback(ContentType::Video); + clone!( + #[weak(rename_to = obj)] + self, + async move { + let imp = obj.imp(); + + match get_media_content(client, message).await { + Ok((_, data)) => { + // The GStreamer backend of GtkVideo doesn't work with input + // streams so we need to + // store the file. See: https://gitlab.gnome.org/GNOME/gtk/-/issues/4062 + let (file, _) = gio::File::new_tmp(None::).unwrap(); + file.replace_contents( + &data, + None, + false, + gio::FileCreateFlags::REPLACE_DESTINATION, + gio::Cancellable::NONE, + ) + .unwrap(); + + imp.media.view_file(file); + } + Err(error) => { + warn!("Could not retrieve video file: {error}"); + imp.media.show_fallback(ContentType::Video); + } } } - }) + ) ); } _ => {} diff --git a/src/session/view/session_view.rs b/src/session/view/session_view.rs index e199fa8a..27776738 100644 --- a/src/session/view/session_view.rs +++ b/src/session/view/session_view.rs @@ -126,26 +126,43 @@ mod imp { self.parent_constructed(); let obj = self.obj(); - self.sidebar.property_expression("list-model").chain_property::("selection-model").chain_property::("selected-item").watch(glib::Object::NONE, - clone!(@weak self as imp => move || { - let show_content = imp.sidebar.list_model().is_some_and(|m| m.selection_model().selected_item().is_some()); - imp.split_view.set_show_content(show_content); - }), - ); + self.sidebar + .property_expression("list-model") + .chain_property::("selection-model") + .chain_property::("selected-item") + .watch( + glib::Object::NONE, + clone!( + #[weak(rename_to = imp)] + self, + move || { + let show_content = imp + .sidebar + .list_model() + .is_some_and(|m| m.selection_model().selected_item().is_some()); + imp.split_view.set_show_content(show_content); + } + ), + ); - self.content - .connect_item_notify(clone!(@weak obj => move |_| { + self.content.connect_item_notify(clone!( + #[weak] + obj, + move |_| { // Withdraw the notifications of the newly selected item. obj.withdraw_selected_item_notifications(); - })); + } + )); obj.connect_root_notify(|obj| { let Some(window) = obj.parent_window() else { return; }; - let handler_id = - window.connect_is_active_notify(clone!(@weak obj => move |window| { + let handler_id = window.connect_is_active_notify(clone!( + #[weak] + obj, + move |window| { if !window.is_active() { return; } @@ -153,7 +170,8 @@ mod imp { // When the window becomes active, withdraw the notifications // of the selected item. obj.withdraw_selected_item_notifications(); - })); + } + )); obj.imp().window_active_handler_id.replace(Some(handler_id)); }); } diff --git a/src/session/view/sidebar/mod.rs b/src/session/view/sidebar/mod.rs index 1bbcba69..a0c446b8 100644 --- a/src/session/view/sidebar/mod.rs +++ b/src/session/view/sidebar/mod.rs @@ -100,18 +100,22 @@ mod imp { let obj = self.obj(); let factory = gtk::SignalListItemFactory::new(); - factory.connect_setup(clone!(@weak obj => move |_, item| { - let item = match item.downcast_ref::() { - Some(item) => item, - None => { - error!("List item factory did not receive a list item: {item:?}"); - return; - } - }; - let row = Row::new(&obj); - item.set_child(Some(&row)); - item.bind_property("item", &row, "list-row").build(); - })); + factory.connect_setup(clone!( + #[weak] + obj, + move |_, item| { + let item = match item.downcast_ref::() { + Some(item) => item, + None => { + error!("List item factory did not receive a list item: {item:?}"); + return; + } + }; + let row = Row::new(&obj); + item.set_child(Some(&row)); + item.bind_property("item", &row, "list-row").build(); + } + )); self.listview.set_factory(Some(&factory)); self.listview.connect_activate(move |listview, pos| { @@ -183,24 +187,34 @@ mod imp { if let Some(user) = &user { let session = user.session(); - let offline_handler = - session.connect_offline_notify(clone!(@weak self as imp => move |_| { + let offline_handler = session.connect_offline_notify(clone!( + #[weak(rename_to = imp)] + self, + move |_| { imp.update_security_banner(); - })); - let crypto_identity_handler = session.connect_crypto_identity_state_notify( - clone!(@weak self as imp => move |_| { + } + )); + let crypto_identity_handler = session.connect_crypto_identity_state_notify(clone!( + #[weak(rename_to = imp)] + self, + move |_| { imp.update_security_banner(); - }), - ); - let verification_handler = session.connect_verification_state_notify( - clone!(@weak self as imp => move |_| { + } + )); + let verification_handler = session.connect_verification_state_notify(clone!( + #[weak(rename_to = imp)] + self, + move |_| { imp.update_security_banner(); - }), - ); - let recovery_handler = - session.connect_recovery_state_notify(clone!(@weak self as imp => move |_| { + } + )); + let recovery_handler = session.connect_recovery_state_notify(clone!( + #[weak(rename_to = imp)] + self, + move |_| { imp.update_security_banner(); - })); + } + )); self.session_handlers.replace(vec![ offline_handler, diff --git a/src/session/view/sidebar/room_row.rs b/src/session/view/sidebar/room_row.rs index d911c845..ab8909f2 100644 --- a/src/session/view/sidebar/room_row.rs +++ b/src/session/view/sidebar/room_row.rs @@ -61,17 +61,27 @@ mod imp { let drag = gtk::DragSource::builder() .actions(gdk::DragAction::MOVE) .build(); - drag.connect_prepare( - clone!(@weak obj => @default-return None, move |drag, x, y| { - obj.drag_prepare(drag, x, y) - }), - ); - drag.connect_drag_begin(clone!(@weak obj => move |_, _| { - obj.drag_begin(); - })); - drag.connect_drag_end(clone!(@weak obj => move |_, _, _| { - obj.drag_end(); - })); + drag.connect_prepare(clone!( + #[weak] + obj, + #[upgrade_or] + None, + move |drag, x, y| obj.drag_prepare(drag, x, y) + )); + drag.connect_drag_begin(clone!( + #[weak] + obj, + move |_, _| { + obj.drag_begin(); + } + )); + drag.connect_drag_end(clone!( + #[weak] + obj, + move |_, _, _| { + obj.drag_end(); + } + )); obj.add_controller(drag); } @@ -111,16 +121,27 @@ mod imp { .build(), )); - let highlight_handler = - room.connect_highlight_notify(clone!(@weak obj => move |_| { + let highlight_handler = room.connect_highlight_notify(clone!( + #[weak] + obj, + move |_| { obj.update_highlight(); - })); - let direct_handler = room.connect_is_direct_notify(clone!(@weak obj => move |_| { + } + )); + let direct_handler = room.connect_is_direct_notify(clone!( + #[weak] + obj, + move |_| { obj.update_direct_icon(); - })); - let name_handler = room.connect_display_name_notify(clone!(@weak obj => move |_| { - obj.update_accessibility_label(); - })); + } + )); + let name_handler = room.connect_display_name_notify(clone!( + #[weak] + obj, + move |_| { + obj.update_accessibility_label(); + } + )); if room.category() == RoomType::Left { self.display_name.add_css_class("dim-label"); diff --git a/src/session/view/sidebar/row.rs b/src/session/view/sidebar/row.rs index 9d4ff1a0..a01fa5f0 100644 --- a/src/session/view/sidebar/row.rs +++ b/src/session/view/sidebar/row.rs @@ -59,17 +59,27 @@ mod imp { .actions(gdk::DragAction::MOVE) .formats(&gdk::ContentFormats::for_type(Room::static_type())) .build(); - drop.connect_accept(clone!(@weak obj => @default-return false, move |_, drop| { - obj.drop_accept(drop) - })); - drop.connect_leave(clone!(@weak obj => move |_| { - obj.drop_leave(); - })); - drop.connect_drop( - clone!(@weak obj => @default-return false, move |_, v, _, _| { - obj.drop_end(v) - }), - ); + drop.connect_accept(clone!( + #[weak] + obj, + #[upgrade_or] + false, + move |_, drop| obj.drop_accept(drop) + )); + drop.connect_leave(clone!( + #[weak] + obj, + move |_| { + obj.drop_leave(); + } + )); + drop.connect_drop(clone!( + #[weak] + obj, + #[upgrade_or] + false, + move |_, v, _, _| obj.drop_end(v) + )); obj.add_controller(drop); } @@ -105,14 +115,22 @@ mod imp { let obj = self.obj(); let drop_source_type_handler = - sidebar.connect_drop_source_category_type_notify(clone!(@weak obj => move |_| { - obj.update_for_drop_source_type(); - })); + sidebar.connect_drop_source_category_type_notify(clone!( + #[weak] + obj, + move |_| { + obj.update_for_drop_source_type(); + } + )); let drop_active_target_type_handler = sidebar - .connect_drop_active_target_category_type_notify(clone!(@weak obj => move |_| { - obj.update_for_drop_active_target_type(); - })); + .connect_drop_active_target_category_type_notify(clone!( + #[weak] + obj, + move |_| { + obj.update_for_drop_active_target_type(); + } + )); self.sidebar.set( &sidebar, @@ -167,11 +185,14 @@ mod imp { child }; - let room_join_rule_handler = room.join_rule().connect_we_can_join_notify( - clone!(@weak self as imp => move |_| { - imp.update_context_menu(); - }), - ); + let room_join_rule_handler = + room.join_rule().connect_we_can_join_notify(clone!( + #[weak(rename_to = imp)] + self, + move |_| { + imp.update_context_menu(); + } + )); self.room_join_rule_handler .replace(Some(room_join_rule_handler)); @@ -260,35 +281,47 @@ mod imp { RoomType::Invited => { action_group.add_action_entries([ gio::ActionEntry::builder("accept-invite") - .activate(clone!(@weak obj => move |_, _, _| { - if let Some(room) = obj.room() { - spawn!(async move { - obj.set_room_category(&room, RoomType::Normal).await; - }); + .activate(clone!( + #[weak] + obj, + move |_, _, _| { + if let Some(room) = obj.room() { + spawn!(async move { + obj.set_room_category(&room, RoomType::Normal).await; + }); + } } - })) + )) .build(), gio::ActionEntry::builder("reject-invite") - .activate(clone!(@weak obj => move |_, _, _| { - if let Some(room) = obj.room() { - spawn!(async move { - obj.set_room_category(&room, RoomType::Left).await; - }); + .activate(clone!( + #[weak] + obj, + move |_, _, _| { + if let Some(room) = obj.room() { + spawn!(async move { + obj.set_room_category(&room, RoomType::Left).await; + }); + } } - })) + )) .build(), ]); } RoomType::Favorite | RoomType::Normal | RoomType::LowPriority => { if matches!(category, RoomType::Favorite | RoomType::LowPriority) { action_group.add_action_entries([gio::ActionEntry::builder("set-normal") - .activate(clone!(@weak obj => move |_, _, _| { - if let Some(room) = obj.room() { - spawn!(async move { - obj.set_room_category(&room, RoomType::Normal).await; - }); + .activate(clone!( + #[weak] + obj, + move |_, _, _| { + if let Some(room) = obj.room() { + spawn!(async move { + obj.set_room_category(&room, RoomType::Normal).await; + }); + } } - })) + )) .build()]); } @@ -296,13 +329,17 @@ mod imp { action_group.add_action_entries([gio::ActionEntry::builder( "set-favorite", ) - .activate(clone!(@weak obj => move |_, _, _| { - if let Some(room) = obj.room() { - spawn!(async move { - obj.set_room_category(&room, RoomType::Favorite).await; - }); + .activate(clone!( + #[weak] + obj, + move |_, _, _| { + if let Some(room) = obj.room() { + spawn!(async move { + obj.set_room_category(&room, RoomType::Favorite).await; + }); + } } - })) + )) .build()]); } @@ -310,47 +347,63 @@ mod imp { action_group.add_action_entries([gio::ActionEntry::builder( "set-lowpriority", ) - .activate(clone!(@weak obj => move |_, _, _| { - if let Some(room) = obj.room() { - spawn!(async move { - obj.set_room_category(&room, RoomType::LowPriority).await; - }); + .activate(clone!( + #[weak] + obj, + move |_, _, _| { + if let Some(room) = obj.room() { + spawn!(async move { + obj.set_room_category(&room, RoomType::LowPriority).await; + }); + } } - })) + )) .build()]); } action_group.add_action_entries([gio::ActionEntry::builder("leave") - .activate(clone!(@weak obj => move |_, _, _| { - if let Some(room) = obj.room() { - spawn!(async move { - obj.set_room_category(&room, RoomType::Left).await; - }); + .activate(clone!( + #[weak] + obj, + move |_, _, _| { + if let Some(room) = obj.room() { + spawn!(async move { + obj.set_room_category(&room, RoomType::Left).await; + }); + } } - })) + )) .build()]); } RoomType::Left => { if room.join_rule().we_can_join() { action_group.add_action_entries([gio::ActionEntry::builder("join") - .activate(clone!(@weak obj => move |_, _, _| { - if let Some(room) = obj.room() { - spawn!(async move { - obj.set_room_category(&room, RoomType::Normal).await; - }); + .activate(clone!( + #[weak] + obj, + move |_, _, _| { + if let Some(room) = obj.room() { + spawn!(async move { + obj.set_room_category(&room, RoomType::Normal).await; + }); + } } - })) + )) .build()]); } action_group.add_action_entries([gio::ActionEntry::builder("forget") - .activate(clone!(@weak obj => move |_, _, _| { - if let Some(room) = obj.room() { - spawn!(async move { - obj.forget_room(&room).await; - }); + .activate(clone!( + #[weak] + obj, + move |_, _, _| { + if let Some(room) = obj.room() { + spawn!(async move { + obj.forget_room(&room).await; + }); + } } - })) + )) .build()]); } RoomType::Outdated | RoomType::Space | RoomType::Ignored => {} @@ -442,16 +495,24 @@ impl Row { if let Ok(room) = value.get::() { if let Some(target_type) = self.room_type() { if room.category().can_change_to(target_type) { - spawn!(clone!(@weak self as obj => async move { - obj.set_room_category(&room, target_type).await; - })); + spawn!(clone!( + #[weak(rename_to = obj)] + self, + async move { + obj.set_room_category(&room, target_type).await; + } + )); ret = true; } } else if let Some(item_type) = self.item_type() { if room.category() == RoomType::Left && item_type == SidebarIconItemType::Forget { - spawn!(clone!(@strong self as obj => async move { - obj.forget_room(&room).await; - })); + spawn!(clone!( + #[strong(rename_to = obj)] + self, + async move { + obj.forget_room(&room).await; + } + )); ret = true; } } diff --git a/src/session_list/mod.rs b/src/session_list/mod.rs index a7f627f0..39efa74e 100644 --- a/src/session_list/mod.rs +++ b/src/session_list/mod.rs @@ -159,20 +159,26 @@ impl SessionList { if let Some(session) = session.downcast_ref::() { // Start listening to notifications when the session is ready. if session.state() == SessionState::Ready { - spawn!(clone!(@weak session => async move { - session.init_notifications().await - })); + spawn!(clone!( + #[weak] + session, + async move { session.init_notifications().await } + )); } else { session.connect_ready(|session| { - spawn!(clone!(@weak session => async move { - session.init_notifications().await - })); + spawn!(clone!( + #[weak] + session, + async move { session.init_notifications().await } + )); }); } - session.connect_logged_out(clone!(@weak self as obj => move |session| { - obj.remove(session.session_id()) - })); + session.connect_logged_out(clone!( + #[weak(rename_to = obj)] + self, + move |session| obj.remove(session.session_id()) + )); } let was_empty = self.is_empty(); @@ -248,9 +254,13 @@ impl SessionList { spawn!( glib::Priority::DEFAULT_IDLE, - clone!(@weak self as obj => async move { - obj.restore_stored_session(stored_session).await; - }) + clone!( + #[weak(rename_to = obj)] + self, + async move { + obj.restore_stored_session(stored_session).await; + } + ) ); } diff --git a/src/system_settings/linux.rs b/src/system_settings/linux.rs index 16994bbd..c958f64c 100644 --- a/src/system_settings/linux.rs +++ b/src/system_settings/linux.rs @@ -29,9 +29,13 @@ mod imp { self.parent_constructed(); let obj = self.obj(); - spawn!(clone!(@weak obj => async move { - obj.init().await; - })); + spawn!(clone!( + #[weak] + obj, + async move { + obj.init().await; + } + )); } } diff --git a/src/utils/expression_list_model.rs b/src/utils/expression_list_model.rs index 58ace744..a5f7f55b 100644 --- a/src/utils/expression_list_model.rs +++ b/src/utils/expression_list_model.rs @@ -75,12 +75,14 @@ impl ExpressionListModel { } let added = if let Some(model) = model { - let items_changed_handler = model.connect_items_changed( - clone!(@strong self as obj => move |_, pos, removed, added| { + let items_changed_handler = model.connect_items_changed(clone!( + #[strong(rename_to = obj)] + self, + move |_, pos, removed, added| { obj.watch_items(pos, removed, added); obj.items_changed(pos, removed, added); - }), - ); + } + )); let added = model.n_items(); imp.model.set(model, vec![items_changed_handler]); @@ -136,9 +138,15 @@ impl ExpressionListModel { for expression in &expressions { item_watches.push(expression.watch( Some(&item), - clone!(@strong self as obj, @weak item => move || { - obj.item_expr_changed(&item); - }), + clone!( + #[strong(rename_to = obj)] + self, + #[weak] + item, + move || { + obj.item_expr_changed(&item); + } + ), )); } diff --git a/src/utils/sourceview.rs b/src/utils/sourceview.rs index a58051e1..85b78771 100644 --- a/src/utils/sourceview.rs +++ b/src/utils/sourceview.rs @@ -9,9 +9,13 @@ pub fn setup_style_scheme(buffer: &sourceview::Buffer) { buffer.set_style_scheme(style_scheme().as_ref()); - manager.connect_dark_notify(glib::clone!(@weak buffer => move |_| { - buffer.set_style_scheme(style_scheme().as_ref()); - })); + manager.connect_dark_notify(glib::clone!( + #[weak] + buffer, + move |_| { + buffer.set_style_scheme(style_scheme().as_ref()); + } + )); } /// Get the style scheme for the current appearance. diff --git a/src/window.rs b/src/window.rs index 0ae5a5b2..80b41e4a 100644 --- a/src/window.rs +++ b/src/window.rs @@ -140,24 +140,29 @@ mod imp { self.load_window_size(); - self.main_stack.connect_transition_running_notify( - clone!(@weak self as imp => move |stack| - if !stack.is_transition_running() { - // Focus the default widget when the transition has ended. - imp.grab_focus(); - } - ), - ); + self.main_stack.connect_transition_running_notify(clone!( + #[weak(rename_to = imp)] + self, + move |stack| if !stack.is_transition_running() { + // Focus the default widget when the transition has ended. + imp.grab_focus(); + } + )); self.account_switcher .set_session_selection(Some(self.session_selection.clone())); - self.session_selection - .connect_selected_item_notify(clone!(@weak obj => move |_| { + self.session_selection.connect_selected_item_notify(clone!( + #[weak] + obj, + move |_| { obj.show_selected_session(); - })); - self.session_selection.connect_items_changed( - clone!(@weak obj => move |session_selection, pos, removed, added| { + } + )); + self.session_selection.connect_items_changed(clone!( + #[weak] + obj, + move |session_selection, pos, removed, added| { let n_items = session_selection.n_items(); obj.action_set_enabled("win.show-session", n_items > 0); @@ -172,7 +177,8 @@ mod imp { } for i in pos..pos + added { - let Some(session) = session_selection.item(i).and_downcast::() else { + let Some(session) = session_selection.item(i).and_downcast::() + else { continue; }; @@ -181,13 +187,12 @@ mod imp { } let settings = Application::default().settings(); - if session.session_id() == settings.string("current-session") - { + if session.session_id() == settings.string("current-session") { session_selection.set_selected(i); } } - }), - ); + } + )); let app = Application::default(); let session_list = app.session_list(); @@ -199,11 +204,15 @@ mod imp { obj.set_visible_page(WindowPage::Login); } } else { - session_list.connect_state_notify(clone!(@weak obj => move |session_list| { - if session_list.state() == LoadingState::Ready && session_list.is_empty() { - obj.set_visible_page(WindowPage::Login); + session_list.connect_state_notify(clone!( + #[weak] + obj, + move |session_list| { + if session_list.state() == LoadingState::Ready && session_list.is_empty() { + obj.set_visible_page(WindowPage::Login); + } } - })); + )); } } } @@ -373,9 +382,13 @@ impl Window { if session.state() == SessionState::Ready { self.set_visible_page(WindowPage::Session); } else { - session.connect_ready(clone!(@weak self as obj => move |_| { - obj.set_visible_page(WindowPage::Session); - })); + session.connect_ready(clone!( + #[weak(rename_to = obj)] + self, + move |_| { + obj.set_visible_page(WindowPage::Session); + } + )); self.set_visible_page(WindowPage::Loading); }