From f4bd75d9c76d011e9e032a25bff943e64c0fe61a Mon Sep 17 00:00:00 2001 From: Julian Schmidhuber Date: Thu, 28 Dec 2023 16:40:17 +0100 Subject: [PATCH] prof(): Reduce memory usage by setup window --- CHANGELOG.md | 1 + src/gui/setup_window.rs | 36 ++++++++++-------------------------- src/gui/window.rs | 28 +++++++++++++++++++++++++--- 3 files changed, 36 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b68fe2a..a08c3cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - High memory usage due to having unused emoji pickers. +- High memory usage of the setup window, even if unused. ## [0.11.0] - 2023-12-25 diff --git a/src/gui/setup_window.rs b/src/gui/setup_window.rs index 96eb9ca..b593d56 100644 --- a/src/gui/setup_window.rs +++ b/src/gui/setup_window.rs @@ -1,6 +1,6 @@ -use crate::backend::{Manager, Server}; +use crate::backend::{Manager, Server, SetupResult}; use adw::prelude::GtkWindowExt; -use gdk::prelude::CastNone; +use gdk::{glib::subclass::types::ObjectSubclassIsExt, prelude::CastNone}; use glib::{Object, ObjectExt}; use gtk::glib; use libsignal_service::configuration::SignalServers; @@ -23,6 +23,10 @@ impl SetupWindow { .build() } + pub fn handle_setup_result(&self, result: &mut SetupResult) { + self.imp().handle_setup_result(result) + } + fn manager(&self) -> Manager { self.property("manager") } @@ -54,12 +58,12 @@ pub mod imp { use futures::channel::oneshot::Sender; use gdk::gdk_pixbuf::Pixbuf; use gdk::gio::ListStore; - use gdk::glib::{BoxedAnyObject, Propagation}; + use gdk::glib::Propagation; use gettextrs::gettext; use gio::MemoryInputStream; use glib::{ - clone, once_cell::sync::Lazy, subclass::InitializingObject, Bytes, ParamSpec, - ParamSpecObject, Value, + once_cell::sync::Lazy, subclass::InitializingObject, Bytes, ParamSpec, ParamSpecObject, + Value, }; use gtk::{gdk, gio, glib, PropertyExpression}; use gtk::{prelude::*, CompositeTemplate}; @@ -231,25 +235,7 @@ pub mod imp { self.obj().close(); } - fn setup_manager(&self) { - let obj = self.obj(); - let manager = obj.manager(); - - manager.connect_local( - "setup-result", - false, - clone!(@strong obj => move |r| { - // r[0] is the manager - let result = r[1].get::().expect("Setup-Result to be BoxedAnyObject"); - let result: &mut SetupResult = &mut result.borrow_mut(); - - obj.imp().handle_setup_result(result); - None - }), - ); - } - - fn handle_setup_result(&self, result: &mut SetupResult) { + pub(super) fn handle_setup_result(&self, result: &mut SetupResult) { let obj = self.obj(); match result { SetupResult::Pending(callback) => { @@ -355,8 +341,6 @@ pub mod imp { .expect("Property `manager` of `SetupWindow` has to be of type `Manager`"); self.manager.replace(man); - - self.setup_manager(); } _ => unimplemented!(), } diff --git a/src/gui/window.rs b/src/gui/window.rs index f71e1ae..fbda12d 100644 --- a/src/gui/window.rs +++ b/src/gui/window.rs @@ -90,7 +90,7 @@ pub mod imp { use adw::{subclass::prelude::*, traits::*, AboutWindow, MessageDialog}; use adw::{EntryRow, ResponseAppearance}; use gdk::gio::Cancellable; - use gdk::glib::{BindingFlags, Propagation}; + use gdk::glib::{BindingFlags, BoxedAnyObject, Propagation}; use gio::{Settings, SimpleAction, SimpleActionGroup}; use glib::{ clone, once_cell::sync::Lazy, subclass::InitializingObject, ParamSpec, ParamSpecObject, @@ -99,7 +99,7 @@ pub mod imp { use gtk::{gio, glib}; use gtk::{prelude::*, Builder, CompositeTemplate, ShortcutsWindow}; - use crate::backend::Channel; + use crate::backend::{Channel, SetupResult}; use crate::gui::channel_info_dialog::ChannelInfoDialog; use crate::gui::linked_devices_window::LinkedDevicesWindow; use crate::{ @@ -480,7 +480,29 @@ pub mod imp { obj.set_property("manager", Some(&manager)); obj.imp().setup_linked_devices_action(); - let _setup_window = SetupWindow::new(manager.clone(), &obj); + let setup_window: RefCell> = RefCell::default(); + + manager.connect_local( + "setup-result", + false, + clone!(@weak obj, @weak manager, @strong setup_window => @default-return None, move |r| { + // r[0] is the manager + let result = r[1].get::().expect("Setup-Result to be BoxedAnyObject"); + let result: &mut SetupResult = &mut result.borrow_mut(); + let mut setup_window = setup_window.borrow_mut(); + + if !matches!(result, SetupResult::Finished) || setup_window.is_some() { + let setup = setup_window.get_or_insert_with(|| SetupWindow::new(manager, &obj)); + setup.handle_setup_result(result); + + if matches!(result, SetupResult::Finished) { + *setup_window = None; + } + } + + None + }), + ); if let Err(e) = manager.init(&path).await { let dialog = ErrorDialog::new(e, &obj);