[fractal/fractal-next] Fix Session dispose
- From: Julian Sparber <jsparber src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [fractal/fractal-next] Fix Session dispose
- Date: Sat, 9 Oct 2021 09:35:20 +0000 (UTC)
commit 5878b1abff4cdb8c1385d986c1f6a74df7d9e2bf
Author: Julian Sparber <julian sparber net>
Date: Fri Oct 8 14:08:17 2021 +0200
Fix Session dispose
We kept many references to Session, therefore we leaked it when the
application is closed.
This also removes the loading page from the `Window` and cleans up how
a Session is restored.
data/resources/ui/window.ui | 28 --------------
src/components/auth_dialog.rs | 40 +++++++-------------
src/login.rs | 17 +++++++--
.../account_settings/devices_page/device.rs | 37 +++++++------------
.../account_settings/devices_page/device_list.rs | 43 +++++++---------------
src/session/account_settings/devices_page/mod.rs | 2 +-
src/session/avatar.rs | 12 ++++--
src/session/content/explore/mod.rs | 13 +++++--
src/session/content/explore/public_room.rs | 14 ++++---
src/session/content/explore/public_room_list.rs | 28 +++++++++++---
src/session/content/mod.rs | 26 ++++++++++---
src/session/room/mod.rs | 17 ++++++---
src/session/room_creation/mod.rs | 13 +++++--
src/session/room_list.rs | 20 ++++++----
src/session/user.rs | 14 ++++---
src/window.rs | 20 ++--------
16 files changed, 170 insertions(+), 174 deletions(-)
---
diff --git a/data/resources/ui/window.ui b/data/resources/ui/window.ui
index 7cdee88e..c1696d38 100644
--- a/data/resources/ui/window.ui
+++ b/data/resources/ui/window.ui
@@ -26,34 +26,6 @@
<property name="transition-type">crossfade</property>
</object>
</child>
- <child>
- <object class="GtkWindowHandle" id="loading_page">
- <property name="child">
- <object class="GtkBox">
- <property name="orientation">vertical</property>
- <child>
- <object class="GtkHeaderBar">
- <property name="show-title-buttons">True</property>
- <style>
- <class name="flat"/>
- </style>
- </object>
- </child>
- <child>
- <object class="GtkSpinner">
- <property name="spinning">True</property>
- <property name="valign">center</property>
- <property name="halign">center</property>
- <property name="vexpand">True</property>
- <style>
- <class name="session-loading-spinner"/>
- </style>
- </object>
- </child>
- </object>
- </property>
- </object>
- </child>
</object>
</child>
</object>
diff --git a/src/components/auth_dialog.rs b/src/components/auth_dialog.rs
index 42067862..00dbd0c6 100644
--- a/src/components/auth_dialog.rs
+++ b/src/components/auth_dialog.rs
@@ -73,15 +73,16 @@ impl AuthData {
mod imp {
use super::*;
+ use glib::object::WeakRef;
use glib::subclass::{InitializingObject, Signal};
use glib::SignalHandlerId;
- use once_cell::sync::Lazy;
+ use once_cell::sync::{Lazy, OnceCell};
use std::cell::RefCell;
#[derive(Debug, Default, CompositeTemplate)]
#[template(resource = "/org/gnome/FractalNext/components-auth-dialog.ui")]
pub struct AuthDialog {
- pub session: RefCell<Option<Session>>,
+ pub session: OnceCell<WeakRef<Session>>,
#[template_child]
pub stack: TemplateChild<gtk::Stack>,
#[template_child]
@@ -129,7 +130,7 @@ mod imp {
"Session",
"The session",
Session::static_type(),
- glib::ParamFlags::READWRITE | glib::ParamFlags::EXPLICIT_NOTIFY,
+ glib::ParamFlags::READWRITE | glib::ParamFlags::CONSTRUCT_ONLY,
)]
});
@@ -138,13 +139,16 @@ mod imp {
fn set_property(
&self,
- obj: &Self::Type,
+ _obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
match pspec.name() {
- "session" => obj.set_session(value.get().unwrap()),
+ "session" => self
+ .session
+ .set(value.get::<Session>().unwrap().downgrade())
+ .unwrap(),
_ => unimplemented!(),
}
}
@@ -207,21 +211,9 @@ impl AuthDialog {
.expect("Failed to create AuthDialog")
}
- pub fn session(&self) -> Option<Session> {
+ pub fn session(&self) -> Session {
let priv_ = imp::AuthDialog::from_instance(self);
- priv_.session.borrow().clone()
- }
-
- pub fn set_session(&self, session: Option<Session>) {
- let priv_ = imp::AuthDialog::from_instance(self);
-
- if self.session() == session {
- return;
- };
-
- priv_.session.replace(session);
-
- self.notify("session");
+ priv_.session.get().unwrap().upgrade().unwrap()
}
pub async fn authenticate<
@@ -266,13 +258,7 @@ impl AuthDialog {
"m.login.password" => {
priv_.stack.set_visible_child_name("m.login.password");
if self.show_and_wait_for_response().await {
- let user_id = self
- .session()
- .unwrap()
- .user()
- .unwrap()
- .user_id()
- .to_string();
+ let user_id = self.session().user().unwrap().user_id().to_string();
let password = priv_.password.text().to_string();
let session = uiaa_info.session;
@@ -291,7 +277,7 @@ impl AuthDialog {
if let Some(session) = uiaa_info.session {
priv_.stack.set_visible_child_name("fallback");
- let client = self.session()?.client().clone();
+ let client = self.session().client().clone();
let (sender, receiver) = futures::channel::oneshot::channel();
RUNTIME.spawn(async move { sender.send(client.homeserver().await) });
let homeserver = receiver.await.unwrap();
diff --git a/src/login.rs b/src/login.rs
index fa2accd7..f5a63c3b 100644
--- a/src/login.rs
+++ b/src/login.rs
@@ -14,10 +14,12 @@ mod imp {
use super::*;
use glib::subclass::{InitializingObject, Signal};
use once_cell::sync::Lazy;
+ use std::cell::RefCell;
#[derive(Debug, Default, CompositeTemplate)]
#[template(resource = "/org/gnome/FractalNext/login.ui")]
pub struct Login {
+ pub current_session: RefCell<Option<Session>>,
#[template_child]
pub next_button: TemplateChild<gtk::Button>,
#[template_child]
@@ -135,6 +137,8 @@ impl Login {
username,
password,
);
+
+ priv_.current_session.replace(Some(session));
}
fn clean(&self) {
@@ -163,7 +167,7 @@ impl Login {
priv_.main_stack.set_sensitive(true);
}
- pub fn connect_new_session<F: Fn(&Self, &Session) + 'static>(
+ pub fn connect_new_session<F: Fn(&Self, Session) + 'static>(
&self,
f: F,
) -> glib::SignalHandlerId {
@@ -171,13 +175,19 @@ impl Login {
let obj = values[0].get::<Self>().unwrap();
let session = values[1].get::<Session>().unwrap();
- f(&obj, &session);
+ f(&obj, session);
None
})
.unwrap()
}
+ fn drop_session_reference(&self) {
+ let priv_ = imp::Login::from_instance(self);
+
+ priv_.current_session.take();
+ }
+
pub fn default_widget(&self) -> gtk::Widget {
imp::Login::from_instance(self).next_button.get().upcast()
}
@@ -188,7 +198,7 @@ impl Login {
priv_.back_to_session_button.set_visible(show);
}
- pub fn set_handler_for_prepared_session(&self, session: &Session) {
+ fn set_handler_for_prepared_session(&self, session: &Session) {
session.connect_prepared(clone!(@weak self as login => move |session| {
if let Some(error) = session.get_error() {
let error_message = &imp::Login::from_instance(&login).error_message;
@@ -202,6 +212,7 @@ impl Login {
login.emit_by_name("new-session", &[&session]).unwrap();
login.clean();
}
+ login.drop_session_reference();
}));
}
}
diff --git a/src/session/account_settings/devices_page/device.rs
b/src/session/account_settings/devices_page/device.rs
index 70862b31..9c470b0f 100644
--- a/src/session/account_settings/devices_page/device.rs
+++ b/src/session/account_settings/devices_page/device.rs
@@ -15,14 +15,14 @@ use log::error;
mod imp {
use super::*;
+ use glib::object::WeakRef;
use once_cell::sync::{Lazy, OnceCell};
- use std::cell::RefCell;
#[derive(Debug, Default)]
pub struct Device {
pub device: OnceCell<MatrixDevice>,
pub crypto_device: OnceCell<CryptoDevice>,
- pub session: RefCell<Option<Session>>,
+ pub session: OnceCell<WeakRef<Session>>,
}
#[glib::object_subclass]
@@ -41,7 +41,7 @@ mod imp {
"Session",
"The session",
Session::static_type(),
- glib::ParamFlags::READWRITE,
+ glib::ParamFlags::READWRITE | glib::ParamFlags::CONSTRUCT_ONLY,
),
glib::ParamSpec::new_string(
"device-id",
@@ -84,13 +84,16 @@ mod imp {
fn set_property(
&self,
- obj: &Self::Type,
+ _obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
match pspec.name() {
- "session" => obj.set_session(value.get().unwrap()),
+ "session" => self
+ .session
+ .set(value.get::<Session>().unwrap().downgrade())
+ .unwrap(),
_ => unimplemented!(),
}
}
@@ -116,33 +119,21 @@ glib::wrapper! {
impl Device {
pub fn new(
- session: Option<&Session>,
+ session: &Session,
device: MatrixDevice,
crypto_device: Option<CryptoDevice>,
) -> Self {
let obj: Self =
- glib::Object::new(&[("session", &session)]).expect("Failed to create Device");
+ glib::Object::new(&[("session", session)]).expect("Failed to create Device");
obj.set_matrix_device(device, crypto_device);
obj
}
- pub fn session(&self) -> Option<Session> {
- let priv_ = imp::Device::from_instance(self);
- priv_.session.borrow().clone()
- }
-
- fn set_session(&self, session: Option<Session>) {
+ pub fn session(&self) -> Session {
let priv_ = imp::Device::from_instance(self);
-
- if self.session() == session {
- return;
- };
-
- priv_.session.replace(session);
-
- self.notify("session");
+ priv_.session.get().unwrap().upgrade().unwrap()
}
fn set_matrix_device(&self, device: MatrixDevice, crypto_device: Option<CryptoDevice>) {
@@ -197,9 +188,7 @@ impl Device {
///
/// Returns `true` for success
pub async fn delete(&self, transient_for: Option<&impl IsA<gtk::Window>>) -> bool {
- let session = self
- .session()
- .expect("Session needs to be set when removing a device");
+ let session = self.session();
let client = session.client().clone();
let device_id = self.device_id().to_owned();
diff --git a/src/session/account_settings/devices_page/device_list.rs
b/src/session/account_settings/devices_page/device_list.rs
index 5ab1ddb7..65396d87 100644
--- a/src/session/account_settings/devices_page/device_list.rs
+++ b/src/session/account_settings/devices_page/device_list.rs
@@ -10,7 +10,8 @@ use crate::{session::Session, utils::do_async};
use super::{Device, DeviceItem};
mod imp {
- use once_cell::sync::Lazy;
+ use glib::object::WeakRef;
+ use once_cell::sync::{Lazy, OnceCell};
use std::cell::{Cell, RefCell};
use super::*;
@@ -18,7 +19,7 @@ mod imp {
#[derive(Debug, Default)]
pub struct DeviceList {
pub list: RefCell<Vec<DeviceItem>>,
- pub session: RefCell<Option<Session>>,
+ pub session: OnceCell<WeakRef<Session>>,
pub current_device: RefCell<Option<DeviceItem>>,
pub loading: Cell<bool>,
}
@@ -40,7 +41,7 @@ mod imp {
"Session",
"The session",
Session::static_type(),
- glib::ParamFlags::READWRITE,
+ glib::ParamFlags::READWRITE | glib::ParamFlags::CONSTRUCT_ONLY,
),
glib::ParamSpec::new_object(
"current-device",
@@ -57,13 +58,16 @@ mod imp {
fn set_property(
&self,
- obj: &Self::Type,
+ _obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
match pspec.name() {
- "session" => obj.set_session(value.get().unwrap()),
+ "session" => self
+ .session
+ .set(value.get::<Session>().unwrap().downgrade())
+ .unwrap(),
_ => unimplemented!(),
}
}
@@ -105,23 +109,9 @@ impl DeviceList {
glib::Object::new(&[("session", session)]).expect("Failed to create DeviceList")
}
- pub fn session(&self) -> Option<Session> {
+ pub fn session(&self) -> Session {
let priv_ = imp::DeviceList::from_instance(self);
- priv_.session.borrow().clone()
- }
-
- fn set_session(&self, session: Option<Session>) {
- let priv_ = imp::DeviceList::from_instance(self);
-
- if self.session() == session {
- return;
- };
-
- priv_.session.replace(session);
-
- self.load_devices();
-
- self.notify("session");
+ priv_.session.get().unwrap().upgrade().unwrap()
}
fn set_loading(&self, loading: bool) {
@@ -176,7 +166,6 @@ impl DeviceList {
response: Result<(Option<MatrixDevice>, Vec<MatrixDevice>, CryptoDevices), Error>,
) {
let session = self.session();
- let session = session.as_ref();
match response {
Ok((current_device, devices, crypto_devices)) => {
@@ -184,7 +173,7 @@ impl DeviceList {
.into_iter()
.map(|device| {
let crypto_device = crypto_devices.get(&device.device_id);
- DeviceItem::for_device(Device::new(session, device, crypto_device))
+ DeviceItem::for_device(Device::new(&session, device, crypto_device))
})
.collect();
@@ -192,7 +181,7 @@ impl DeviceList {
self.set_current_device(current_device.map(|device| {
let crypto_device = crypto_devices.get(&device.device_id);
- DeviceItem::for_device(Device::new(session, device, crypto_device))
+ DeviceItem::for_device(Device::new(&session, device, crypto_device))
}));
}
Err(error) => {
@@ -206,11 +195,7 @@ impl DeviceList {
}
pub fn load_devices(&self) {
- let client = if let Some(session) = self.session() {
- session.client().clone()
- } else {
- return;
- };
+ let client = self.session().client().clone();
self.set_loading(true);
diff --git a/src/session/account_settings/devices_page/mod.rs
b/src/session/account_settings/devices_page/mod.rs
index cfb98eab..111774a2 100644
--- a/src/session/account_settings/devices_page/mod.rs
+++ b/src/session/account_settings/devices_page/mod.rs
@@ -113,7 +113,7 @@ impl DevicesPage {
}
if let Some(ref user) = user {
- let device_list = DeviceList::new(user.session());
+ let device_list = DeviceList::new(&user.session());
priv_.other_sessions.bind_model(
Some(&device_list),
clone!(@weak device_list => @default-panic, move |item| {
diff --git a/src/session/avatar.rs b/src/session/avatar.rs
index 90f775b8..d7c62ccc 100644
--- a/src/session/avatar.rs
+++ b/src/session/avatar.rs
@@ -18,6 +18,7 @@ use crate::session::Session;
mod imp {
use super::*;
+ use glib::object::WeakRef;
use once_cell::sync::{Lazy, OnceCell};
use std::cell::{Cell, RefCell};
@@ -27,7 +28,7 @@ mod imp {
pub needed: Cell<bool>,
pub url: RefCell<Option<MxcUri>>,
pub display_name: RefCell<Option<String>>,
- pub session: OnceCell<Session>,
+ pub session: OnceCell<WeakRef<Session>>,
}
#[glib::object_subclass]
@@ -92,7 +93,10 @@ mod imp {
match pspec.name() {
"needed" => obj.set_needed(value.get().unwrap()),
"url" => obj.set_url(value.get::<Option<&str>>().unwrap().map(Into::into)),
- "session" => self.session.set(value.get().unwrap()).unwrap(),
+ "session" => self
+ .session
+ .set(value.get::<Session>().unwrap().downgrade())
+ .unwrap(),
"display-name" => {
let _ = obj.set_display_name(value.get().unwrap());
}
@@ -132,9 +136,9 @@ impl Avatar {
.expect("Failed to create Avatar")
}
- fn session(&self) -> &Session {
+ fn session(&self) -> Session {
let priv_ = imp::Avatar::from_instance(self);
- priv_.session.get().unwrap()
+ priv_.session.get().unwrap().upgrade().unwrap()
}
pub fn image(&self) -> Option<gdk::Paintable> {
diff --git a/src/session/content/explore/mod.rs b/src/session/content/explore/mod.rs
index 01d190bb..a7de1fed 100644
--- a/src/session/content/explore/mod.rs
+++ b/src/session/content/explore/mod.rs
@@ -16,6 +16,7 @@ use crate::utils::do_async;
mod imp {
use super::*;
+ use glib::object::WeakRef;
use glib::subclass::InitializingObject;
use once_cell::sync::Lazy;
use std::cell::{Cell, RefCell};
@@ -24,7 +25,7 @@ mod imp {
#[template(resource = "/org/gnome/FractalNext/content-explore.ui")]
pub struct Explore {
pub compact: Cell<bool>,
- pub session: RefCell<Option<Session>>,
+ pub session: RefCell<Option<WeakRef<Session>>>,
#[template_child]
pub stack: TemplateChild<gtk::Stack>,
#[template_child]
@@ -148,7 +149,11 @@ impl Explore {
pub fn session(&self) -> Option<Session> {
let priv_ = imp::Explore::from_instance(self);
- priv_.session.borrow().to_owned()
+ priv_
+ .session
+ .borrow()
+ .as_ref()
+ .and_then(|session| session.upgrade())
}
pub fn init(&self) {
@@ -189,7 +194,9 @@ impl Explore {
priv_.public_room_list.replace(Some(public_room_list));
}
- priv_.session.replace(session);
+ priv_
+ .session
+ .replace(session.map(|session| session.downgrade()));
self.notify("session");
}
diff --git a/src/session/content/explore/public_room.rs b/src/session/content/explore/public_room.rs
index ecf79425..baf747d1 100644
--- a/src/session/content/explore/public_room.rs
+++ b/src/session/content/explore/public_room.rs
@@ -5,13 +5,14 @@ use crate::session::{room::Room, Avatar, Session};
mod imp {
use super::*;
+ use glib::object::WeakRef;
use glib::signal::SignalHandlerId;
use once_cell::sync::{Lazy, OnceCell};
use std::cell::{Cell, RefCell};
#[derive(Debug, Default)]
pub struct PublicRoom {
- pub session: OnceCell<Session>,
+ pub session: OnceCell<WeakRef<Session>>,
pub matrix_public_room: OnceCell<PublicRoomsChunk>,
pub avatar: OnceCell<Avatar>,
pub room: OnceCell<Room>,
@@ -72,7 +73,10 @@ mod imp {
pspec: &glib::ParamSpec,
) {
match pspec.name() {
- "session" => self.session.set(value.get().unwrap()).unwrap(),
+ "session" => self
+ .session
+ .set(value.get::<Session>().unwrap().downgrade())
+ .unwrap(),
_ => unimplemented!(),
}
}
@@ -90,7 +94,7 @@ mod imp {
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
- self.avatar.set(Avatar::new(obj.session(), None)).unwrap();
+ self.avatar.set(Avatar::new(&obj.session(), None)).unwrap();
obj.session()
.room_list()
@@ -120,9 +124,9 @@ impl PublicRoom {
glib::Object::new(&[("session", session)]).expect("Failed to create Room")
}
- pub fn session(&self) -> &Session {
+ pub fn session(&self) -> Session {
let priv_ = imp::PublicRoom::from_instance(self);
- priv_.session.get().unwrap()
+ priv_.session.get().unwrap().upgrade().unwrap()
}
pub fn avatar(&self) -> &Avatar {
diff --git a/src/session/content/explore/public_room_list.rs b/src/session/content/explore/public_room_list.rs
index e94243de..7d530d1d 100644
--- a/src/session/content/explore/public_room_list.rs
+++ b/src/session/content/explore/public_room_list.rs
@@ -17,6 +17,7 @@ use matrix_sdk::ruma::{
use std::convert::TryFrom;
mod imp {
+ use glib::object::WeakRef;
use once_cell::sync::Lazy;
use std::cell::{Cell, RefCell};
@@ -32,7 +33,7 @@ mod imp {
pub loading: Cell<bool>,
pub request_sent: Cell<bool>,
pub total_room_count_estimate: Cell<Option<u64>>,
- pub session: RefCell<Option<Session>>,
+ pub session: RefCell<Option<WeakRef<Session>>>,
}
#[glib::object_subclass]
@@ -83,15 +84,13 @@ mod imp {
fn set_property(
&self,
- _obj: &Self::Type,
+ obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
match pspec.name() {
- "session" => {
- let _ = self.session.replace(value.get().unwrap());
- }
+ "session" => obj.set_session(value.get().unwrap()),
_ => unimplemented!(),
}
}
@@ -136,7 +135,24 @@ impl PublicRoomList {
pub fn session(&self) -> Option<Session> {
let priv_ = imp::PublicRoomList::from_instance(self);
- priv_.session.borrow().to_owned()
+ priv_
+ .session
+ .borrow()
+ .as_ref()
+ .and_then(|session| session.upgrade())
+ }
+
+ pub fn set_session(&self, session: Option<Session>) {
+ let priv_ = imp::PublicRoomList::from_instance(self);
+
+ if session == self.session() {
+ return;
+ }
+
+ priv_
+ .session
+ .replace(session.map(|session| session.downgrade()));
+ self.notify("session");
}
pub fn loading(&self) -> bool {
diff --git a/src/session/content/mod.rs b/src/session/content/mod.rs
index c1a08974..d07515ee 100644
--- a/src/session/content/mod.rs
+++ b/src/session/content/mod.rs
@@ -28,6 +28,7 @@ use crate::session::Session;
mod imp {
use super::*;
+ use glib::object::WeakRef;
use glib::{signal::SignalHandlerId, subclass::InitializingObject};
use once_cell::sync::Lazy;
use std::cell::{Cell, RefCell};
@@ -36,7 +37,7 @@ mod imp {
#[template(resource = "/org/gnome/FractalNext/content.ui")]
pub struct Content {
pub compact: Cell<bool>,
- pub session: RefCell<Option<Session>>,
+ pub session: RefCell<Option<WeakRef<Session>>>,
pub room: RefCell<Option<Room>>,
pub content_type: Cell<ContentType>,
pub error_list: RefCell<Option<gio::ListStore>>,
@@ -134,9 +135,7 @@ mod imp {
let compact = value.get().unwrap();
self.compact.set(compact);
}
- "session" => {
- let _ = self.session.replace(value.get().unwrap());
- }
+ "session" => obj.set_session(value.get().unwrap()),
"room" => {
let room = value.get().unwrap();
obj.set_room(room);
@@ -177,7 +176,24 @@ impl Content {
pub fn session(&self) -> Option<Session> {
let priv_ = imp::Content::from_instance(self);
- priv_.session.borrow().to_owned()
+ priv_
+ .session
+ .borrow()
+ .as_ref()
+ .and_then(|session| session.upgrade())
+ }
+
+ pub fn set_session(&self, session: Option<Session>) {
+ let priv_ = imp::Content::from_instance(self);
+
+ if session == self.session() {
+ return;
+ }
+
+ priv_
+ .session
+ .replace(session.map(|session| session.downgrade()));
+ self.notify("session");
}
pub fn content_type(&self) -> ContentType {
diff --git a/src/session/room/mod.rs b/src/session/room/mod.rs
index 175f42eb..91f285f6 100644
--- a/src/session/room/mod.rs
+++ b/src/session/room/mod.rs
@@ -61,6 +61,7 @@ use crate::RUNTIME;
mod imp {
use super::*;
+ use glib::object::WeakRef;
use glib::subclass::Signal;
use once_cell::sync::{Lazy, OnceCell};
use std::cell::Cell;
@@ -70,7 +71,7 @@ mod imp {
pub struct Room {
pub room_id: OnceCell<RoomId>,
pub matrix_room: RefCell<Option<MatrixRoom>>,
- pub session: OnceCell<Session>,
+ pub session: OnceCell<WeakRef<Session>>,
pub name: RefCell<Option<String>>,
pub avatar: OnceCell<Avatar>,
pub category: Cell<RoomType>,
@@ -189,7 +190,10 @@ mod imp {
pspec: &glib::ParamSpec,
) {
match pspec.name() {
- "session" => self.session.set(value.get().unwrap()).unwrap(),
+ "session" => self
+ .session
+ .set(value.get::<Session>().unwrap().downgrade())
+ .unwrap(),
"display-name" => {
let room_name = value.get().unwrap();
obj.store_room_name(room_name)
@@ -252,7 +256,7 @@ mod imp {
obj.set_matrix_room(obj.session().client().get_room(obj.room_id()).unwrap());
self.timeline.set(Timeline::new(obj)).unwrap();
self.avatar
- .set(Avatar::new(obj.session(), obj.matrix_room().avatar_url()))
+ .set(Avatar::new(&obj.session(), obj.matrix_room().avatar_url()))
.unwrap();
obj.load_power_levels();
@@ -278,9 +282,9 @@ impl Room {
.expect("Failed to create Room")
}
- pub fn session(&self) -> &Session {
+ pub fn session(&self) -> Session {
let priv_ = imp::Room::from_instance(self);
- priv_.session.get().unwrap()
+ priv_.session.get().unwrap().upgrade().unwrap()
}
pub fn room_id(&self) -> &RoomId {
@@ -854,7 +858,8 @@ impl Room {
/// Creates an expression that is true when the user is allowed the given action.
pub fn new_allowed_expr(&self, room_action: RoomAction) -> gtk::Expression {
- let user_id = self.session().user().unwrap().user_id();
+ let session = self.session();
+ let user_id = session.user().unwrap().user_id();
let member = self.member_by_id(user_id);
self.power_levels().new_allowed_expr(&member, room_action)
}
diff --git a/src/session/room_creation/mod.rs b/src/session/room_creation/mod.rs
index d1115d78..7ab1f462 100644
--- a/src/session/room_creation/mod.rs
+++ b/src/session/room_creation/mod.rs
@@ -30,13 +30,14 @@ const MAX_BYTES: usize = 255;
mod imp {
use super::*;
+ use glib::object::WeakRef;
use glib::subclass::InitializingObject;
use std::cell::RefCell;
#[derive(Debug, Default, CompositeTemplate)]
#[template(resource = "/org/gnome/FractalNext/room-creation.ui")]
pub struct RoomCreation {
- pub session: RefCell<Option<Session>>,
+ pub session: RefCell<Option<WeakRef<Session>>>,
#[template_child]
pub content: TemplateChild<gtk::ListBox>,
#[template_child]
@@ -171,7 +172,11 @@ impl RoomCreation {
pub fn session(&self) -> Option<Session> {
let priv_ = imp::RoomCreation::from_instance(self);
- priv_.session.borrow().clone()
+ priv_
+ .session
+ .borrow()
+ .as_ref()
+ .and_then(|session| session.upgrade())
}
fn set_session(&self, session: Option<Session>) {
@@ -187,7 +192,9 @@ impl RoomCreation {
.set_label(&[":", user.user_id().server_name().as_str()].concat());
}
- priv_.session.replace(session);
+ priv_
+ .session
+ .replace(session.map(|session| session.downgrade()));
self.notify("session");
}
diff --git a/src/session/room_list.rs b/src/session/room_list.rs
index ae860808..eae50a0a 100644
--- a/src/session/room_list.rs
+++ b/src/session/room_list.rs
@@ -16,6 +16,7 @@ use std::cell::Cell;
use std::collections::HashSet;
mod imp {
+ use glib::object::WeakRef;
use glib::subclass::Signal;
use once_cell::sync::{Lazy, OnceCell};
use std::cell::RefCell;
@@ -26,7 +27,7 @@ mod imp {
pub struct RoomList {
pub list: RefCell<IndexMap<RoomId, Room>>,
pub pending_rooms: RefCell<HashSet<RoomIdOrAliasId>>,
- pub session: OnceCell<Session>,
+ pub session: OnceCell<WeakRef<Session>>,
}
#[glib::object_subclass]
@@ -60,7 +61,10 @@ mod imp {
pspec: &glib::ParamSpec,
) {
match pspec.name() {
- "session" => self.session.set(value.get().unwrap()).unwrap(),
+ "session" => self
+ .session
+ .set(value.get::<Session>().unwrap().downgrade())
+ .unwrap(),
_ => unimplemented!(),
}
}
@@ -119,9 +123,9 @@ impl RoomList {
glib::Object::new(&[("session", session)]).expect("Failed to create RoomList")
}
- pub fn session(&self) -> &Session {
+ pub fn session(&self) -> Session {
let priv_ = imp::RoomList::from_instance(self);
- priv_.session.get().unwrap()
+ priv_.session.get().unwrap().upgrade().unwrap()
}
pub fn is_pending_room(&self, identifier: &RoomIdOrAliasId) -> bool {
@@ -244,7 +248,7 @@ impl RoomList {
let mut list = priv_.list.borrow_mut();
for matrix_room in matrix_rooms {
let room_id = matrix_room.room_id().to_owned();
- let room = Room::new(session, &room_id);
+ let room = Room::new(&session, &room_id);
list.insert(room_id, room);
}
}
@@ -266,7 +270,7 @@ impl RoomList {
.entry(room_id.clone())
.or_insert_with(|| {
added += 1;
- Room::new(session, &room_id)
+ Room::new(&session, &room_id)
})
.clone();
@@ -281,7 +285,7 @@ impl RoomList {
.entry(room_id.clone())
.or_insert_with(|| {
added += 1;
- Room::new(session, &room_id)
+ Room::new(&session, &room_id)
})
.clone();
@@ -296,7 +300,7 @@ impl RoomList {
.entry(room_id.clone())
.or_insert_with(|| {
added += 1;
- Room::new(session, &room_id)
+ Room::new(&session, &room_id)
})
.clone();
diff --git a/src/session/user.rs b/src/session/user.rs
index 21c56b09..71e83bfa 100644
--- a/src/session/user.rs
+++ b/src/session/user.rs
@@ -5,6 +5,7 @@ use crate::session::{Avatar, Session};
mod imp {
use super::*;
+ use glib::object::WeakRef;
use once_cell::sync::{Lazy, OnceCell};
use std::{cell::RefCell, convert::TryInto};
@@ -12,7 +13,7 @@ mod imp {
pub struct User {
pub user_id: OnceCell<UserId>,
pub display_name: RefCell<Option<String>>,
- pub session: OnceCell<Session>,
+ pub session: OnceCell<WeakRef<Session>>,
pub avatar: OnceCell<Avatar>,
}
@@ -73,7 +74,10 @@ mod imp {
let user_id = value.get::<&str>().unwrap().try_into().unwrap();
self.user_id.set(user_id).unwrap();
}
- "session" => self.session.set(value.get().unwrap()).unwrap(),
+ "session" => self
+ .session
+ .set(value.get::<Session>().unwrap().downgrade())
+ .unwrap(),
_ => unimplemented!(),
}
}
@@ -91,7 +95,7 @@ mod imp {
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
- let avatar = Avatar::new(obj.session(), None);
+ let avatar = Avatar::new(&obj.session(), None);
self.avatar.set(avatar).unwrap();
obj.bind_property("display-name", obj.avatar(), "display-name")
@@ -115,9 +119,9 @@ impl User {
}
pub trait UserExt: IsA<User> {
- fn session(&self) -> &Session {
+ fn session(&self) -> Session {
let priv_ = imp::User::from_instance(self.upcast_ref());
- priv_.session.get().unwrap()
+ priv_.session.get().unwrap().upgrade().unwrap()
}
fn user_id(&self) -> &UserId {
diff --git a/src/window.rs b/src/window.rs
index 513a8e5c..538698b2 100644
--- a/src/window.rs
+++ b/src/window.rs
@@ -26,8 +26,6 @@ mod imp {
#[template_child]
pub sessions: TemplateChild<gtk::Stack>,
#[template_child]
- pub loading_page: TemplateChild<gtk::WindowHandle>,
- #[template_child]
pub error_list: TemplateChild<gio::ListStore>,
}
@@ -66,7 +64,7 @@ mod imp {
self.login
.connect_new_session(clone!(@weak obj => move |_login, session| {
- obj.add_session(session);
+ obj.add_session(&session);
obj.switch_to_sessions_page();
}));
@@ -115,16 +113,11 @@ impl Window {
fn restore_sessions(&self) {
match secret::restore_sessions() {
Ok(sessions) => {
- let login = &imp::Window::from_instance(self).login.get();
- let n = sessions.len();
for stored_session in sessions {
let session = Session::new();
- login.set_handler_for_prepared_session(&session);
session.login_with_previous_session(stored_session);
- }
-
- if n > 0 {
- self.switch_to_loading_page();
+ self.add_session(&session);
+ self.switch_to_sessions_page();
}
}
Err(error) => warn!("Failed to restore previous sessions: {:?}", error),
@@ -171,13 +164,6 @@ impl Window {
priv_.main_stack.set_visible_child(&priv_.sessions.get());
}
- pub fn switch_to_loading_page(&self) {
- let priv_ = imp::Window::from_instance(self);
- priv_
- .main_stack
- .set_visible_child(&priv_.loading_page.get());
- }
-
pub fn switch_to_login_page(&self) {
let priv_ = imp::Window::from_instance(self);
priv_
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]