Port to new clone! macro

This commit is contained in:
DaPigGuy 2024-07-18 05:19:46 -07:00
parent 6663f1e399
commit d5645fb101
Failed to generate hash of commit
14 changed files with 603 additions and 306 deletions

View file

@ -72,15 +72,29 @@ mod imp {
let window = app.active_window();
let preferences = PreferencesWindow::new(model);
preferences.set_has_set_password(app.can_be_locked());
preferences.connect_restore_completed(clone!(@weak window =>move |_| {
window.providers().refilter();
window.imp().toast_overlay.add_toast(adw::Toast::new(&gettext("Accounts restored successfully")));
}));
preferences.connect_has_set_password_notify(clone!(@weak app => move |pref| {
app.set_can_be_locked(pref.has_set_password());
}));
preferences.connect_restore_completed(clone!(
#[weak]
window,
move |_| {
window.providers().refilter();
window
.imp()
.toast_overlay
.add_toast(adw::Toast::new(&gettext(
"Accounts restored successfully",
)));
}
));
preferences.connect_has_set_password_notify(clone!(
#[weak]
app,
move |pref| {
app.set_can_be_locked(pref.has_set_password());
}
));
preferences.present(Some(&window));
}).build();
})
.build();
// About
let about_action = gio::ActionEntry::builder("about")
@ -111,9 +125,13 @@ mod imp {
let model = &app.imp().model;
let window = app.active_window();
let providers = ProvidersDialog::new(model);
providers.connect_changed(clone!(@weak window => move |_| {
window.providers().refilter();
}));
providers.connect_changed(clone!(
#[weak]
window,
move |_| {
window.providers().refilter();
}
));
providers.present(Some(&window));
})
.build();
@ -151,21 +169,31 @@ mod imp {
}
});
SETTINGS.connect_auto_lock_changed(clone!(@weak app => move |auto_lock| {
if auto_lock {
app.restart_lock_timeout();
} else {
app.cancel_lock_timeout();
SETTINGS.connect_auto_lock_changed(clone!(
#[weak]
app,
move |auto_lock| {
if auto_lock {
app.restart_lock_timeout();
} else {
app.cancel_lock_timeout();
}
}
}));
));
SETTINGS.connect_auto_lock_timeout_changed(clone!(@weak app => move |_| {
app.restart_lock_timeout()
}));
SETTINGS.connect_auto_lock_timeout_changed(clone!(
#[weak]
app,
move |_| app.restart_lock_timeout()
));
spawn(clone!(@strong app => async move {
app.start_search_provider().await;
}));
spawn(clone!(
#[strong]
app,
async move {
app.start_search_provider().await;
}
));
}
fn activate(&self) {
@ -331,19 +359,27 @@ impl Application {
timeout,
None,
glib::Priority::HIGH,
clone!(@strong tx => move || {
let Some(tx) = tx.lock().unwrap().take() else {
return glib::ControlFlow::Break;
};
tx.send(()).unwrap();
glib::ControlFlow::Break
}),
clone!(
#[strong]
tx,
move || {
let Some(tx) = tx.lock().unwrap().take() else {
return glib::ControlFlow::Break;
};
tx.send(()).unwrap();
glib::ControlFlow::Break
}
),
);
spawn(clone!(@strong self as app => async move {
if let Ok(()) = rx.await {
app.set_is_locked(true);
spawn(clone!(
#[strong(rename_to = app)]
self,
async move {
if let Ok(()) = rx.await {
app.set_is_locked(true);
}
}
}));
));
id.attach(Some(&glib::MainContext::default()));
imp.lock_timeout_id.replace(Some(id));
}
@ -393,9 +429,13 @@ impl Application {
};
glib::timeout_add_seconds_local_once(
provider.period(),
glib::clone!(@weak self as app => move || {
app.withdraw_notification(&id);
}),
glib::clone!(
#[weak(rename_to = app)]
self,
move || {
app.withdraw_notification(&id);
}
),
);
}
SearchProviderAction::InitialResultSet(terms, sender) => {

View file

@ -208,25 +208,30 @@ impl Account {
let results = DieselAccount::belonging_to(&dip)
.load::<DieselAccount>(&mut conn)?
.into_iter()
.filter_map(clone!(@strong p => move |account| {
match Self::new(
account.id as u32,
&account.name,
&account.token_id,
account.counter as u32,
&p,
None,
)
{
Ok(account) => Some(account),
Err(e) => {
let name = account.name;
let provider = p.name();
tracing::error!("Failed to load account '{name}' / '{provider}' with error {e}");
None
.filter_map(clone!(
#[strong]
p,
move |account| {
match Self::new(
account.id as u32,
&account.name,
&account.token_id,
account.counter as u32,
&p,
None,
) {
Ok(account) => Some(account),
Err(e) => {
let name = account.name;
let provider = p.name();
tracing::error!(
"Failed to load account '{name}' / '{provider}' with error {e}"
);
None
}
}
}
}));
));
Ok(results)
}

View file

@ -396,10 +396,16 @@ impl Provider {
Method::TOTP | Method::Steam => {
let source_id = glib::timeout_add_seconds_local(
1,
clone!(@weak self as provider => @default-return glib::ControlFlow::Break, move || {
provider.tick();
glib::ControlFlow::Continue
}),
clone!(
#[weak(rename_to = provider)]
self,
#[upgrade_or]
glib::ControlFlow::Break,
move || {
provider.tick();
glib::ControlFlow::Continue
}
),
);
self.imp().tick_callback.replace(Some(source_id));
}
@ -464,15 +470,19 @@ impl Provider {
}
pub fn filter(&self, text: String) {
let filter = gtk::CustomFilter::new(
glib::clone!(@weak self as provider => @default-return false, move |obj| {
let filter = gtk::CustomFilter::new(glib::clone!(
#[weak(rename_to = provider)]
self,
#[upgrade_or]
false,
move |obj| {
let account = obj.downcast_ref::<Account>().unwrap();
let account_name = account.name();
let provider_name = provider.name();
Self::tokenize_search(&account_name, &provider_name, &text)
}),
);
}
));
self.imp().filter_model.set_filter(Some(&filter));
}

View file

@ -120,19 +120,24 @@ mod imp {
let provider = aperture::DeviceProvider::instance();
self.provider.set(provider.clone()).unwrap();
self.viewfinder
.connect_state_notify(glib::clone!(@weak obj => move |_| {
self.viewfinder.connect_state_notify(glib::clone!(
#[weak]
obj,
move |_| {
obj.update_viewfinder_state();
}));
}
));
obj.update_viewfinder_state();
self.viewfinder.connect_code_detected(
glib::clone!(@weak obj => move|_, code_type, code| {
self.viewfinder.connect_code_detected(glib::clone!(
#[weak]
obj,
move |_, code_type, code| {
if matches!(code_type, aperture::CodeType::Qr) {
obj.emit_by_name::<()>("code-detected", &[&code]);
}
}),
);
}
));
let popover = gtk::Popover::new();
popover.add_css_class("menu");
@ -147,34 +152,48 @@ mod imp {
.set_child(Some(&camera_row));
});
let selection = &self.selection;
factory.connect_bind(glib::clone!(@weak selection => move |_, item| {
let item = item.downcast_ref::<gtk::ListItem>().unwrap();
let child = item.child().unwrap();
let row = child.downcast_ref::<CameraRow>().unwrap();
factory.connect_bind(glib::clone!(
#[weak]
selection,
move |_, item| {
let item = item.downcast_ref::<gtk::ListItem>().unwrap();
let child = item.child().unwrap();
let row = child.downcast_ref::<CameraRow>().unwrap();
let item = item.item().and_downcast::<aperture::Camera>().unwrap();
row.set_label(&item.display_name());
let item = item.item().and_downcast::<aperture::Camera>().unwrap();
row.set_label(&item.display_name());
selection.connect_selected_item_notify(glib::clone!(@weak row, @weak item => move |selection| {
if let Some(selected_item) = selection.selected_item() {
row.set_selected(selected_item == item);
} else {
row.set_selected(false);
}
}));
}));
selection.connect_selected_item_notify(glib::clone!(
#[weak]
row,
#[weak]
item,
move |selection| {
if let Some(selected_item) = selection.selected_item() {
row.set_selected(selected_item == item);
} else {
row.set_selected(false);
}
}
));
}
));
let list_view = gtk::ListView::new(Some(self.selection.clone()), Some(factory));
popover.set_child(Some(&list_view));
self.selection.connect_selected_item_notify(
glib::clone!(@weak obj, @weak popover => move |selection| {
self.selection.connect_selected_item_notify(glib::clone!(
#[weak]
obj,
#[weak]
popover,
move |selection| {
if let Some(selected_item) = selection.selected_item() {
let camera = selected_item.downcast_ref::<aperture::Camera>();
obj.imp().viewfinder.set_camera(camera);
}
popover.popdown();
}),
);
}
));
self.camera_selection_button.set_popover(Some(&popover));
}
@ -198,10 +217,16 @@ impl Camera {
self.connect_local(
"close",
false,
clone!(@weak self as camera => @default-return None, move |_| {
callback(&camera);
None
}),
clone!(
#[weak(rename_to = camera)]
self,
#[upgrade_or]
None,
move |_| {
callback(&camera);
None
}
),
)
}
@ -212,11 +237,17 @@ impl Camera {
self.connect_local(
"code-detected",
false,
clone!(@weak self as camera => @default-return None, move |args| {
let code = args[1].get::<String>().unwrap();
callback(&camera, code);
None
}),
clone!(
#[weak(rename_to = camera)]
self,
#[upgrade_or]
None,
move |args| {
let code = args[1].get::<String>().unwrap();
callback(&camera, code);
None
}
),
)
}

View file

@ -51,11 +51,17 @@ impl ErrorRevealer {
imp.revealer.set_reveal_child(true);
glib::timeout_add_seconds_local(
2,
glib::clone!(@weak self as error_revealer => @default-return glib::ControlFlow::Break, move || {
error_revealer.imp().revealer.set_reveal_child(false);
error_revealer.set_visible(false);
glib::ControlFlow::Break
}),
glib::clone!(
#[weak(rename_to = error_revealer)]
self,
#[upgrade_or]
glib::ControlFlow::Break,
move || {
error_revealer.imp().revealer.set_reveal_child(false);
error_revealer.set_visible(false);
glib::ControlFlow::Break
}
),
);
}
}

View file

@ -78,8 +78,13 @@ impl CameraPage {
let src = Rc::new(Cell::new(None));
src.set(Some(imp.camera.connect_code_detected(clone!(
@weak self as camera_page, @strong src, @strong tx
=> move |_, code| {
#[weak(rename_to = camera_page)]
self,
#[strong]
src,
#[strong]
tx,
move |_, code| {
match tx.take().unwrap().send(code) {
Ok(()) => (),
Err(_) => {
@ -126,8 +131,13 @@ impl CameraPage {
let src = Rc::new(Cell::new(None));
src.set(Some(imp.camera.connect_code_detected(clone!(
@weak self as camera_page, @strong src, @strong tx
=> move |_, code| {
#[weak(rename_to = camera_page)]
self,
#[strong]
src,
#[strong]
tx,
move |_, code| {
match tx.take().unwrap().send(code) {
Ok(()) => (),
Err(_) => {

View file

@ -69,9 +69,13 @@ mod imp {
self.status_page.set_icon_name(Some(config::APP_ID));
page.reset_validation();
// Reset the validation whenever the password state changes
page.connect_has_set_password_notify(clone!(@weak page => move |_| {
page.reset_validation();
}));
page.connect_has_set_password_notify(clone!(
#[weak]
page,
move |_| {
page.reset_validation();
}
));
}
}
@ -123,8 +127,11 @@ impl PasswordPage {
fn reset_validation(&self) {
let imp = self.imp();
if self.has_set_password() {
imp.current_password_entry
.connect_changed(clone!(@weak self as page => move |_| page.validate(None)));
imp.current_password_entry.connect_changed(clone!(
#[weak(rename_to = page)]
self,
move |_| page.validate(None)
));
} else if let Some(handler_id) = imp.default_password_signal.borrow_mut().take() {
imp.current_password_entry.disconnect(handler_id);
}
@ -133,18 +140,34 @@ impl PasswordPage {
fn setup_actions(&self) {
let actions = self.actions();
let save_password = gio::ActionEntry::builder("save_password")
.activate(clone!(@weak self as page => move |_, _, _| {
spawn(clone!(@weak page => async move {
page.save().await;
}));
}))
.activate(clone!(
#[weak(rename_to = page)]
self,
move |_, _, _| {
spawn(clone!(
#[weak]
page,
async move {
page.save().await;
}
));
}
))
.build();
let reset_password = gio::ActionEntry::builder("reset_password")
.activate(clone!(@weak self as page => move |_, _, _| {
spawn(clone!(@weak page => async move {
page.reset_password().await;
}));
}))
.activate(clone!(
#[weak(rename_to = page)]
self,
move |_, _, _| {
spawn(clone!(
#[weak]
page,
async move {
page.reset_password().await;
}
));
}
))
.build();
actions.add_action_entries([save_password, reset_password]);

View file

@ -132,10 +132,16 @@ impl PreferencesWindow {
self.connect_local(
"restore-completed",
false,
clone!(@weak self as win => @default-return None, move |_| {
callback(&win);
None
}),
clone!(
#[weak(rename_to = win)]
self,
#[upgrade_or]
None,
move |_| {
callback(&win);
None
}
),
)
}
@ -219,14 +225,24 @@ impl PreferencesWindow {
}
let action = gio::ActionEntry::builder(T::IDENTIFIER)
.activate(clone!(@weak self as win => move |_, _,_| {
spawn(clone!(@weak win => async move {
if let Err(err) = win.backup_into_file::<T>(filters).await {
tracing::error!("Failed to backup into a file {err}");
win.add_toast(adw::Toast::new(&gettext("Failed to create a backup")));
}
}));
}))
.activate(clone!(
#[weak(rename_to = win)]
self,
move |_, _, _| {
spawn(clone!(
#[weak]
win,
async move {
if let Err(err) = win.backup_into_file::<T>(filters).await {
tracing::error!("Failed to backup into a file {err}");
win.add_toast(adw::Toast::new(&gettext(
"Failed to create a backup",
)));
}
}
));
}
))
.build();
imp.backup_actions.add_action_entries([action]);
}
@ -330,49 +346,94 @@ impl PreferencesWindow {
}
if T::SCANNABLE {
let camera_action = gio::ActionEntry::builder(&format!("{}.camera", T::IDENTIFIER))
.activate(clone!(@weak self as win=> move |_, _, _| {
win.imp().actions.activate_action("show_camera_page", None);
spawn(clone!(@weak win => async move {
if let Err(err) = win.restore_from_camera::<T, T::Item>().await {
tracing::error!("Failed to restore from camera {err}");
win.add_toast(adw::Toast::new(&gettext("Failed to restore from camera")));
}
}));
}))
.activate(clone!(
#[weak(rename_to = win)]
self,
move |_, _, _| {
win.imp().actions.activate_action("show_camera_page", None);
spawn(clone!(
#[weak]
win,
async move {
if let Err(err) = win.restore_from_camera::<T, T::Item>().await {
tracing::error!("Failed to restore from camera {err}");
win.add_toast(adw::Toast::new(&gettext(
"Failed to restore from camera",
)));
}
}
));
}
))
.build();
let screenshot_action =
gio::ActionEntry::builder(&format!("{}.screenshot", T::IDENTIFIER))
.activate(clone!(@weak self as win => move |_, _, _| {
spawn(clone!(@weak win => async move {
if let Err(err) = win.restore_from_screenshot::<T, T::Item>().await {
tracing::error!("Failed to restore from a screenshot {err}");
win.add_toast(adw::Toast::new(&gettext("Failed to restore from a screenshot")));
}
}));
}))
.activate(clone!(
#[weak(rename_to = win)]
self,
move |_, _, _| {
spawn(clone!(
#[weak]
win,
async move {
if let Err(err) =
win.restore_from_screenshot::<T, T::Item>().await
{
tracing::error!(
"Failed to restore from a screenshot {err}"
);
win.add_toast(adw::Toast::new(&gettext(
"Failed to restore from a screenshot",
)));
}
}
));
}
))
.build();
let file_action = gio::ActionEntry::builder(&format!("{}.file", T::IDENTIFIER))
.activate(clone!(@weak self as win => move |_, _, _| {
spawn(clone!(@weak win => async move {
if let Err(err) = win.restore_from_image::<T, T::Item>().await {
tracing::error!("Failed to restore from an image {err}");
win.add_toast(adw::Toast::new(&gettext("Failed to restore from an image")));
}
}));
}))
.activate(clone!(
#[weak(rename_to = win)]
self,
move |_, _, _| {
spawn(clone!(
#[weak]
win,
async move {
if let Err(err) = win.restore_from_image::<T, T::Item>().await {
tracing::error!("Failed to restore from an image {err}");
win.add_toast(adw::Toast::new(&gettext(
"Failed to restore from an image",
)));
}
}
));
}
))
.build();
imp.restore_actions
.add_action_entries([camera_action, file_action, screenshot_action]);
} else {
let action = gio::ActionEntry::builder(T::IDENTIFIER)
.activate(clone!(@weak self as win => move |_, _, _| {
spawn(clone!(@weak win => async move {
if let Err(err) = win.restore_from_file::<T, T::Item>(filters).await {
tracing::error!("Failed to restore from a file {err}");
win.add_toast(adw::Toast::new(&gettext("Failed to restore from a file")));
}
}));
}))
.activate(clone!(
#[weak(rename_to = win)]
self,
move |_, _, _| {
spawn(clone!(
#[weak]
win,
async move {
if let Err(err) = win.restore_from_file::<T, T::Item>(filters).await
{
tracing::error!("Failed to restore from a file {err}");
win.add_toast(adw::Toast::new(&gettext(
"Failed to restore from a file",
)));
}
}
));
}
))
.build();
imp.restore_actions.add_action_entries([action]);
@ -494,42 +555,66 @@ impl PreferencesWindow {
fn setup_actions(&self) {
let imp = self.imp();
imp.camera_page
.connect_map(clone!(@weak self as win => move |_| {
imp.camera_page.connect_map(clone!(
#[weak(rename_to = win)]
self,
move |_| {
win.set_search_enabled(false);
}));
}
));
imp.camera_page
.connect_unmap(clone!(@weak self as win => move |_| {
imp.camera_page.connect_unmap(clone!(
#[weak(rename_to = win)]
self,
move |_| {
win.set_search_enabled(true);
}));
}
));
imp.password_page
.connect_map(clone!(@weak self as win => move |_| {
imp.password_page.connect_map(clone!(
#[weak(rename_to = win)]
self,
move |_| {
win.set_search_enabled(false);
}));
}
));
imp.password_page
.connect_unmap(clone!(@weak self as win => move |_| {
imp.password_page.connect_unmap(clone!(
#[weak(rename_to = win)]
self,
move |_| {
win.set_search_enabled(true);
}));
}
));
let show_camera_page = gio::ActionEntry::builder("show_camera_page")
.activate(clone!(@weak self as win => move |_, _, _| {
win.push_subpage(&win.imp().camera_page);
}))
.activate(clone!(
#[weak(rename_to = win)]
self,
move |_, _, _| {
win.push_subpage(&win.imp().camera_page);
}
))
.build();
let show_password_page = gio::ActionEntry::builder("show_password_page")
.activate(clone!(@weak self as win => move |_, _, _| {
win.push_subpage(&win.imp().password_page);
}))
.activate(clone!(
#[weak(rename_to = win)]
self,
move |_, _, _| {
win.push_subpage(&win.imp().password_page);
}
))
.build();
let close_page = gio::ActionEntry::builder("close_page")
.activate(clone!(@weak self as win => move |_, _, _| {
win.pop_subpage();
}))
.activate(clone!(
#[weak(rename_to = win)]
self,
move |_, _, _| {
win.pop_subpage();
}
))
.build();
imp.actions

View file

@ -92,15 +92,20 @@ mod imp {
let obj = self.obj();
self.placeholder_page.set_icon_name(Some(config::APP_ID));
self.filter_model.set_model(Some(&obj.model()));
self.filter_model.connect_items_changed(
clone!(@weak obj as dialog => move |model, _, _, _| {
self.filter_model.connect_items_changed(clone!(
#[weak(rename_to = dialog)]
obj,
move |model, _, _, _| {
if model.n_items() == 0 {
dialog.imp().search_stack.set_visible_child_name("no-results");
dialog
.imp()
.search_stack
.set_visible_child_name("no-results");
} else {
dialog.imp().search_stack.set_visible_child_name("results");
}
}),
);
}
));
let sorter = gtk::StringSorter::builder()
.ignore_case(true)
@ -141,10 +146,16 @@ impl ProvidersDialog {
self.connect_local(
"changed",
false,
clone!(@weak self as dialog => @default-return None, move |_| {
callback(&dialog);
None
}),
clone!(
#[weak(rename_to = dialog)]
self,
#[upgrade_or]
None,
move |_| {
callback(&dialog);
None
}
),
)
}

View file

@ -83,10 +83,13 @@ mod imp {
self.spinner.start();
obj.on_provider_image_changed();
}
let signal_id =
provider.connect_image_uri_notify(clone!(@weak obj as image => move |_| {
let signal_id = provider.connect_image_uri_notify(clone!(
#[weak(rename_to = image)]
obj,
move |_| {
image.on_provider_image_changed();
}));
}
));
self.signal_id.replace(Some(signal_id));
return;
} else if let (Some(signal_id), Some(provider)) =
@ -175,38 +178,44 @@ impl ProviderImage {
let join_handle = RUNTIME.spawn(future);
imp.join_handle.borrow_mut().replace(join_handle);
spawn(clone!(@weak self as this => async move {
let imp = this.imp();
imp.was_downloaded.set(true);
let image_path = match receiver.await {
// TODO: handle network failure and other errors differently
Ok(None) => {
imp.image.set_icon_name(Some("provider-fallback"));
"invalid".to_string()
}
Ok(Some(cache_name)) => {
if imp.size.get() == 32 {
imp.image
.set_from_file(Some(&FAVICONS_PATH.join(format!("{cache_name}_32x32"))));
} else {
imp.image
.set_from_file(Some(&FAVICONS_PATH.join(format!("{cache_name}_96x96"))));
spawn(clone!(
#[weak(rename_to = this)]
self,
async move {
let imp = this.imp();
imp.was_downloaded.set(true);
let image_path = match receiver.await {
// TODO: handle network failure and other errors differently
Ok(None) => {
imp.image.set_icon_name(Some("provider-fallback"));
"invalid".to_string()
}
cache_name
Ok(Some(cache_name)) => {
if imp.size.get() == 32 {
imp.image.set_from_file(Some(
&FAVICONS_PATH.join(format!("{cache_name}_32x32")),
));
} else {
imp.image.set_from_file(Some(
&FAVICONS_PATH.join(format!("{cache_name}_96x96")),
));
}
cache_name
}
Err(e) => {
tracing::error!("Failed to receive data {e}");
return;
}
};
if let Some(provider) = this.provider() {
let guard = provider.freeze_notify();
provider.set_image_uri(image_path);
drop(guard);
}
Err(e) => {
tracing::error!("Failed to receive data {e}");
return;
}
};
if let Some(provider) = this.provider() {
let guard = provider.freeze_notify();
provider.set_image_uri(image_path);
drop(guard);
imp.stack.set_visible_child_name("image");
imp.spinner.stop();
}
imp.stack.set_visible_child_name("image");
imp.spinner.stop();
}));
));
}
}
}
@ -228,19 +237,28 @@ impl ProviderImage {
self.bind_property("size", &*imp.image, "pixel-size")
.sync_create()
.build();
SETTINGS.connect_download_favicons_changed(clone!(@weak self as image => move |state| {
if state && !image.imp().was_downloaded.get() {
image.fetch();
SETTINGS.connect_download_favicons_changed(clone!(
#[weak(rename_to = image)]
self,
move |state| {
if state && !image.imp().was_downloaded.get() {
image.fetch();
}
}
}));
));
SETTINGS.connect_download_favicons_metered_changed(
clone!(@weak self as image => move |state| {
SETTINGS.connect_download_favicons_metered_changed(clone!(
#[weak(rename_to = image)]
self,
move |state| {
let network_monitor = gio::NetworkMonitor::default();
if !image.imp().was_downloaded.get() && (network_monitor.is_network_metered() && state) || !network_monitor.is_network_metered() {
image.fetch();
}
}),
);
if !image.imp().was_downloaded.get()
&& (network_monitor.is_network_metered() && state)
|| !network_monitor.is_network_metered()
{
image.fetch();
}
}
));
}
}

View file

@ -132,18 +132,30 @@ impl ProvidersList {
imp.providers_list.bind_model(
Some(&sort_model),
clone!(@strong self as list => move |obj| {
let provider = obj.downcast_ref::<Provider>().unwrap();
let row = ProviderRow::new(provider);
row.connect_changed(clone!(@weak list => move |_| {
list.refilter();
}));
row.connect_shared(clone!(@weak list => move |_, account| {
list.emit_by_name::<()>("shared", &[&account]);
}));
clone!(
#[strong(rename_to = list)]
self,
move |obj| {
let provider = obj.downcast_ref::<Provider>().unwrap();
let row = ProviderRow::new(provider);
row.connect_changed(clone!(
#[weak]
list,
move |_| {
list.refilter();
}
));
row.connect_shared(clone!(
#[weak]
list,
move |_, account| {
list.emit_by_name::<()>("shared", &[&account]);
}
));
row.upcast::<gtk::Widget>()
}),
row.upcast::<gtk::Widget>()
}
),
);
}
}

View file

@ -93,10 +93,16 @@ impl ProviderRow {
self.connect_local(
"changed",
false,
clone!(@weak self as row => @default-return None, move |_| {
callback(&row);
None
}),
clone!(
#[weak(rename_to = row)]
self,
#[upgrade_or]
None,
move |_| {
callback(&row);
None
}
),
)
}
@ -107,11 +113,17 @@ impl ProviderRow {
self.connect_local(
"shared",
false,
clone!(@weak self as row => @default-return None, move |args| {
let account = args[1].get::<Account>().unwrap();
callback(&row, account);
None
}),
clone!(
#[weak(rename_to = row)]
self,
#[upgrade_or]
None,
move |args| {
let account = args[1].get::<Account>().unwrap();
callback(&row, account);
None
}
),
)
}
@ -141,9 +153,13 @@ impl ProviderRow {
} else {
// Update the progress bar whnever the remaining-time is updated
self.tick_progressbar();
provider.connect_remaining_time_notify(clone!(@weak self as row => move |_| {
row.tick_progressbar();
}));
provider.connect_remaining_time_notify(clone!(
#[weak(rename_to = row)]
self,
move |_| {
row.tick_progressbar();
}
));
}
provider
@ -158,23 +174,39 @@ impl ProviderRow {
let sort_model =
gtk::SortListModel::new(Some(provider.accounts().clone()), Some(sorter.clone()));
let create_callback = clone!(@strong self as provider_row, @strong sorter, @strong provider => move |account: &glib::Object| {
let account = account.downcast_ref::<Account>().unwrap();
let row = AccountRow::new(account);
let create_callback = clone!(
#[strong(rename_to = provider_row)]
self,
#[strong]
sorter,
move |account: &glib::Object| {
let account = account.downcast_ref::<Account>().unwrap();
let row = AccountRow::new(account);
row.connect_activated(
clone!(@weak account, @weak provider_row => move |_| {
provider_row.emit_by_name::<()>("shared", &[&account]);
}),
);
row.connect_activated(clone!(
#[weak]
account,
#[weak]
provider_row,
move |_| {
provider_row.emit_by_name::<()>("shared", &[&account]);
}
));
account.connect_name_notify(clone!(@weak provider_row, @weak sorter => move |_| {
// Re-sort in case the name was updated
sorter.changed(gtk::SorterChange::Different);
provider_row.emit_by_name::<()>("changed", &[]);
}));
row.upcast::<gtk::Widget>()
});
account.connect_name_notify(clone!(
#[weak]
provider_row,
#[weak]
sorter,
move |_| {
// Re-sort in case the name was updated
sorter.changed(gtk::SorterChange::Different);
provider_row.emit_by_name::<()>("changed", &[]);
}
));
row.upcast::<gtk::Widget>()
}
);
imp.accounts_list
.bind_model(Some(&sort_model), create_callback);

View file

@ -32,17 +32,21 @@ mod imp {
self.parent_constructed();
let obj = self.obj();
obj.set_activatable(true);
obj.connect_activated(clone!(@weak obj as row => move |_| {
if let Some(uri) = row.imp().uri.borrow().clone() {
spawn(async move {
let file = gio::File::for_uri(&uri);
let launcher = gtk::FileLauncher::new(Some(&file));
if let Err(err) = launcher.launch_future(gtk::Window::NONE).await {
tracing::error!("Failed to open URI {err}");
}
});
};
}));
obj.connect_activated(clone!(
#[weak(rename_to = row)]
obj,
move |_| {
if let Some(uri) = row.imp().uri.borrow().clone() {
spawn(async move {
let file = gio::File::for_uri(&uri);
let launcher = gtk::FileLauncher::new(Some(&file));
if let Err(err) = launcher.launch_future(gtk::Window::NONE).await {
tracing::error!("Failed to open URI {err}");
}
});
};
}
));
let image_suffix = gtk::Image::from_icon_name("link-symbolic");
image_suffix.set_accessible_role(gtk::AccessibleRole::Presentation);

View file

@ -129,14 +129,16 @@ mod imp {
let win = self.obj();
self.providers.set_model(win.model());
self.providers
.model()
.connect_items_changed(clone!(@weak win => move |_, _,_,_| {
// We do a check on set_view to ensure we always use the right page
if !win.app().is_locked() {
win.set_view(View::Accounts);
self.providers.model().connect_items_changed(clone!(
#[weak]
win,
move |_, _, _, _| {
// We do a check on set_view to ensure we always use the right page
if !win.app().is_locked() {
win.set_view(View::Accounts);
}
}
}));
));
win.set_icon_name(Some(config::APP_ID));
self.empty_status_page.set_icon_name(Some(config::APP_ID));
@ -191,15 +193,19 @@ mod imp {
let win = self.obj();
let app = win.app();
win.action_set_enabled("win.add_account", !app.is_locked());
app.connect_is_locked_notify(clone!(@weak win => move |app| {
let is_locked = app.is_locked();
win.action_set_enabled("win.add_account", !is_locked);
if is_locked{
win.set_view(View::Login);
} else {
win.set_view(View::Accounts);
};
}));
app.connect_is_locked_notify(clone!(
#[weak]
win,
move |app| {
let is_locked = app.is_locked();
win.action_set_enabled("win.add_account", !is_locked);
if is_locked {
win.set_view(View::Login);
} else {
win.set_view(View::Accounts);
};
}
));
if app.is_locked() {
win.set_view(View::Login);
}
@ -274,9 +280,13 @@ impl Window {
dialog.set_from_otp_uri(uri);
}
dialog.connect_added(clone!(@weak self as win => move |_| {
win.providers().refilter();
}));
dialog.connect_added(clone!(
#[weak(rename_to = win)]
self,
move |_| {
win.providers().refilter();
}
));
dialog.present(Some(self));
}