Browse Source

session-list: Create SessionListSettings to manage session settings

fractal-6
Kévin Commaille 2 years ago
parent
commit
589ae9b840
No known key found for this signature in database
GPG Key ID: 29A48C1F03620416
  1. 4
      src/session/model/mod.rs
  2. 28
      src/session/model/session.rs
  3. 93
      src/session/model/session_settings.rs
  4. 15
      src/session_list/mod.rs
  5. 114
      src/session_list/session_list_settings.rs

4
src/session/model/mod.rs

@ -3,7 +3,7 @@ mod notifications;
mod room;
mod room_list;
mod session;
mod settings;
mod session_settings;
mod sidebar;
mod user;
mod verification;
@ -19,7 +19,7 @@ pub use self::{
},
room_list::RoomList,
session::{Session, SessionState},
settings::SessionSettings,
session_settings::{SessionSettings, StoredSessionSettings},
sidebar::{
Category, CategoryType, IconItem, ItemList, ItemType, Selection, SidebarItem,
SidebarItemImpl, SidebarListModel,

28
src/session/model/session.rs

@ -42,6 +42,7 @@ use crate::{
matrix::{self, ClientSetupError},
TokioDrop,
},
Application,
};
/// The state of the session.
@ -99,12 +100,22 @@ mod imp {
glib::ParamSpecEnum::builder::<SessionState>("state")
.read_only()
.build(),
glib::ParamSpecObject::builder::<SessionSettings>("settings")
.construct_only()
.build(),
]
});
PROPERTIES.as_ref()
}
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"settings" => self.settings.set(value.get().unwrap()).unwrap(),
_ => unimplemented!(),
}
}
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
let obj = self.obj();
@ -113,6 +124,7 @@ mod imp {
"user" => obj.user().to_value(),
"offline" => obj.is_offline().to_value(),
"state" => obj.state().to_value(),
"settings" => obj.settings().to_value(),
_ => unimplemented!(),
}
}
@ -121,10 +133,6 @@ mod imp {
self.parent_constructed();
let obj = self.obj();
self.settings
.set(SessionSettings::new(obj.session_id()))
.unwrap();
self.notifications.set_session(Some(&obj));
let monitor = gio::NetworkMonitor::default();
@ -166,14 +174,22 @@ impl Session {
/// Create a new session.
pub async fn new(homeserver: Url, data: MatrixSession) -> Result<Self, ClientSetupError> {
let stored_session = StoredSession::with_login_data(homeserver, data);
let settings = Application::default()
.session_list()
.settings()
.get_or_create(stored_session.id());
Self::restore(stored_session).await
Self::restore(stored_session, settings).await
}
/// Restore a stored session.
pub async fn restore(stored_session: StoredSession) -> Result<Self, ClientSetupError> {
pub async fn restore(
stored_session: StoredSession,
settings: SessionSettings,
) -> Result<Self, ClientSetupError> {
let obj = glib::Object::builder::<Self>()
.property("info", BoxedStoredSession(stored_session.clone()))
.property("settings", settings)
.build();
let client =

93
src/session/model/settings.rs → src/session/model/session_settings.rs

@ -1,7 +1,5 @@
use gtk::{glib, prelude::*, subclass::prelude::*};
use indexmap::IndexMap;
use serde::{Deserialize, Serialize};
use tracing::error;
use crate::Application;
@ -28,6 +26,10 @@ impl Default for StoredSessionSettings {
}
}
#[derive(Clone, Debug, glib::Boxed)]
#[boxed_type(name = "BoxedStoredSessionSettings")]
pub struct BoxedStoredSessionSettings(StoredSessionSettings);
mod imp {
use std::cell::RefCell;
@ -56,6 +58,10 @@ mod imp {
glib::ParamSpecString::builder("session-id")
.construct_only()
.build(),
glib::ParamSpecBoxed::builder::<BoxedStoredSessionSettings>("stored-settings")
.write_only()
.construct_only()
.build(),
glib::ParamSpecBoolean::builder("notifications-enabled")
.default_value(true)
.explicit_notify()
@ -70,7 +76,11 @@ mod imp {
let obj = self.obj();
match pspec.name() {
"session-id" => obj.set_session_id(value.get().ok()),
"session-id" => self.session_id.set(value.get().unwrap()).unwrap(),
"stored-settings" => {
self.stored_settings
.replace(value.get::<BoxedStoredSessionSettings>().unwrap().0);
}
"notifications-enabled" => obj.set_notifications_enabled(value.get().unwrap()),
_ => unimplemented!(),
}
@ -101,34 +111,34 @@ impl SessionSettings {
.build()
}
/// Save the settings in the GSettings.
fn save(&self) {
let mut sessions = sessions();
let stored_settings = self.imp().stored_settings.borrow().clone();
/// Restore existing `SessionSettings` with the given session ID and stored
/// settings.
pub fn restore(session_id: &str, stored_settings: StoredSessionSettings) -> Self {
glib::Object::builder()
.property("session-id", session_id)
.property(
"stored-settings",
&BoxedStoredSessionSettings(stored_settings),
)
.build()
}
sessions.insert(self.session_id().to_owned(), stored_settings);
let sessions = sessions.into_iter().collect::<Vec<_>>();
/// The stored settings.
pub fn stored_settings(&self) -> StoredSessionSettings {
self.imp().stored_settings.borrow().clone()
}
if let Err(error) = Application::default()
.settings()
.set_string("sessions", &serde_json::to_string(&sessions).unwrap())
{
error!("Failed to save session settings: {error}");
}
/// Save the settings in the GSettings.
fn save(&self) {
Application::default().session_list().settings().save();
}
/// Delete the settings from the GSettings.
pub fn delete(&self) {
let mut sessions = sessions();
sessions.remove(self.session_id());
if let Err(error) = Application::default()
Application::default()
.session_list()
.settings()
.set_string("sessions", &serde_json::to_string(&sessions).unwrap())
{
error!("Failed to delete session settings: {error}");
}
.remove(self.session_id());
}
/// The ID of the session these settings are for.
@ -136,28 +146,6 @@ impl SessionSettings {
self.imp().session_id.get().unwrap()
}
/// Set the ID of the session these settings are for.
fn set_session_id(&self, session_id: Option<String>) {
let session_id = match session_id {
Some(s) => s,
None => return,
};
let imp = self.imp();
imp.session_id.set(session_id.clone()).unwrap();
if let Some(session_settings) = sessions()
.into_iter()
.find_map(|(s_id, session)| (s_id == session_id).then_some(session))
{
// Restore the settings.
imp.stored_settings.replace(session_settings);
} else {
// This is a new session, add it to the list of sessions.
self.save();
}
}
pub fn explore_custom_servers(&self) -> Vec<String> {
self.imp()
.stored_settings
@ -197,16 +185,3 @@ impl SessionSettings {
self.notify("notifications-enabled");
}
}
/// Get map of session stored in the GSettings.
fn sessions() -> IndexMap<String, StoredSessionSettings> {
let serialized = Application::default().settings().string("sessions");
match serde_json::from_str::<Vec<(String, StoredSessionSettings)>>(&serialized) {
Ok(stored_settings) => stored_settings.into_iter().collect(),
Err(error) => {
error!("Failed to load profile settings, fallback to default settings: {error}");
Default::default()
}
}
}

15
src/session_list/mod.rs

@ -6,8 +6,9 @@ use tracing::{error, info, warn};
mod failed_session;
mod new_session;
mod session_info;
mod session_list_settings;
pub use self::{failed_session::*, new_session::*, session_info::*};
pub use self::{failed_session::*, new_session::*, session_info::*, session_list_settings::*};
use crate::{
prelude::*,
secret::{self, StoredSession},
@ -31,6 +32,8 @@ mod imp {
pub error: RefCell<Option<String>>,
/// A map of session ID to session.
pub list: RefCell<IndexMap<String, SessionInfo>>,
/// The settings of the sessions.
pub settings: SessionListSettings,
}
#[glib::object_subclass]
@ -126,6 +129,11 @@ impl SessionList {
self.notify("error");
}
/// The settings of the sessions.
pub fn settings(&self) -> &SessionListSettings {
&self.imp().settings
}
/// Whether this list is empty.
pub fn is_empty(&self) -> bool {
self.imp().list.borrow().is_empty()
@ -226,6 +234,8 @@ impl SessionList {
let handle = spawn_tokio!(secret::restore_sessions());
match handle.await.unwrap() {
Ok(sessions) => {
self.settings().load();
for stored_session in sessions {
info!(
"Restoring previous session for user: {}",
@ -263,7 +273,8 @@ impl SessionList {
/// Restore a stored session.
async fn restore_stored_session(&self, session_info: StoredSession) {
match Session::restore(session_info.clone()).await {
let settings = self.settings().get_or_create(session_info.id());
match Session::restore(session_info.clone(), settings).await {
Ok(session) => {
session.prepare().await;
self.insert(session);

114
src/session_list/session_list_settings.rs

@ -0,0 +1,114 @@
use gtk::{glib, prelude::*, subclass::prelude::*};
use indexmap::IndexMap;
use tracing::error;
use crate::{
session::model::{SessionSettings, StoredSessionSettings},
Application,
};
mod imp {
use std::cell::RefCell;
use super::*;
use crate::session::model::SessionSettings;
#[derive(Debug, Default)]
pub struct SessionListSettings {
/// The settings of the sessions.
pub sessions: RefCell<IndexMap<String, SessionSettings>>,
}
#[glib::object_subclass]
impl ObjectSubclass for SessionListSettings {
const NAME: &'static str = "SessionListSettings";
type Type = super::SessionListSettings;
}
impl ObjectImpl for SessionListSettings {}
}
glib::wrapper! {
/// The settings of the list of sessions.
pub struct SessionListSettings(ObjectSubclass<imp::SessionListSettings>);
}
impl SessionListSettings {
/// Create a new `SessionListSettings`.
pub fn new() -> Self {
glib::Object::new()
}
/// Load these settings from the GSettings.
pub fn load(&self) {
let serialized = Application::default().settings().string("sessions");
let stored_sessions =
match serde_json::from_str::<Vec<(String, StoredSessionSettings)>>(&serialized) {
Ok(stored_sessions) => stored_sessions,
Err(error) => {
error!(
"Failed to load sessions settings, fallback to default settings: {error}"
);
Default::default()
}
};
let sessions = stored_sessions
.into_iter()
.map(|(session_id, stored_session)| {
let session = SessionSettings::restore(&session_id, stored_session);
(session_id, session)
})
.collect();
self.imp().sessions.replace(sessions);
}
/// Save the settings in the GSettings.
pub fn save(&self) {
let stored_sessions = self
.imp()
.sessions
.borrow()
.iter()
.map(|(session_id, session)| (session_id.to_owned(), session.stored_settings()))
.collect::<Vec<_>>();
if let Err(error) = Application::default().settings().set_string(
"sessions",
&serde_json::to_string(&stored_sessions).unwrap(),
) {
error!("Failed to save sessions settings: {error}");
}
}
/// Get or create the settings for the session with the given ID.
pub fn get_or_create(&self, session_id: &str) -> SessionSettings {
let sessions = &self.imp().sessions;
if let Some(session) = sessions.borrow().get(session_id) {
return session.clone();
};
let session = SessionSettings::new(session_id);
sessions
.borrow_mut()
.insert(session_id.to_owned(), session.clone());
self.save();
session
}
/// Remove the settings of the session with the given ID.
pub fn remove(&self, session_id: &str) {
self.imp().sessions.borrow_mut().remove(session_id);
self.save();
}
}
impl Default for SessionListSettings {
fn default() -> Self {
Self::new()
}
}
Loading…
Cancel
Save