create-dm-dialog: Port to glib::Properties
This commit is contained in:
parent
e4daec38d6
commit
7db1e462d4
|
@ -8,12 +8,13 @@ use crate::{
|
|||
};
|
||||
|
||||
mod imp {
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
#[derive(Debug, Default, glib::Properties)]
|
||||
#[properties(wrapper_type = super::DmUser)]
|
||||
pub struct DmUser {
|
||||
/// The direct chat with this user, if any.
|
||||
#[property(get, set = Self::set_direct_chat, explicit_notify, nullable)]
|
||||
pub direct_chat: glib::WeakRef<Room>,
|
||||
}
|
||||
|
||||
|
@ -24,36 +25,30 @@ mod imp {
|
|||
type ParentType = User;
|
||||
}
|
||||
|
||||
#[glib::derived_properties]
|
||||
impl ObjectImpl for DmUser {
|
||||
fn properties() -> &'static [glib::ParamSpec] {
|
||||
static PROPERTIES: Lazy<Vec<glib::ParamSpec>> = Lazy::new(|| {
|
||||
vec![glib::ParamSpecObject::builder::<Room>("direct-chat")
|
||||
.read_only()
|
||||
.build()]
|
||||
});
|
||||
|
||||
PROPERTIES.as_ref()
|
||||
}
|
||||
|
||||
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
|
||||
let obj = self.obj();
|
||||
|
||||
match pspec.name() {
|
||||
"direct-chat" => obj.direct_chat().to_value(),
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn constructed(&self) {
|
||||
self.parent_constructed();
|
||||
let obj = self.obj();
|
||||
|
||||
spawn!(clone!(@weak obj => async move {
|
||||
let direct_chat = obj.upcast_ref::<User>().direct_chat().await;
|
||||
obj.set_direct_chat(direct_chat.as_ref());
|
||||
obj.set_direct_chat(direct_chat);
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
impl DmUser {
|
||||
/// Set the direct chat with this user.
|
||||
fn set_direct_chat(&self, direct_chat: Option<Room>) {
|
||||
if self.direct_chat.upgrade() == direct_chat {
|
||||
return;
|
||||
}
|
||||
|
||||
self.direct_chat.set(direct_chat.as_ref());
|
||||
self.obj().notify_direct_chat();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glib::wrapper! {
|
||||
|
@ -77,19 +72,4 @@ impl DmUser {
|
|||
obj.set_avatar_url(avatar_url.map(std::borrow::ToOwned::to_owned));
|
||||
obj
|
||||
}
|
||||
|
||||
/// Get the direct chat with this user, if any.
|
||||
pub fn direct_chat(&self) -> Option<Room> {
|
||||
self.imp().direct_chat.upgrade()
|
||||
}
|
||||
|
||||
/// Set the direct chat with this user.
|
||||
fn set_direct_chat(&self, direct_chat: Option<&Room>) {
|
||||
if self.direct_chat().as_ref() == direct_chat {
|
||||
return;
|
||||
}
|
||||
|
||||
self.imp().direct_chat.set(direct_chat);
|
||||
self.notify("direct-chat");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,15 +21,21 @@ mod imp {
|
|||
use std::cell::{Cell, RefCell};
|
||||
|
||||
use futures_util::future::AbortHandle;
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
#[derive(Debug, Default, glib::Properties)]
|
||||
#[properties(wrapper_type = super::DmUserList)]
|
||||
pub struct DmUserList {
|
||||
pub list: RefCell<Vec<DmUser>>,
|
||||
/// The current session.
|
||||
#[property(get, construct_only)]
|
||||
pub session: glib::WeakRef<Session>,
|
||||
/// The state of the list.
|
||||
#[property(get, builder(DmUserListState::default()))]
|
||||
pub state: Cell<DmUserListState>,
|
||||
/// The search term.
|
||||
#[property(get, set = Self::set_search_term, explicit_notify, nullable)]
|
||||
pub search_term: RefCell<Option<String>>,
|
||||
pub abort_handle: RefCell<Option<AbortHandle>>,
|
||||
}
|
||||
|
@ -41,52 +47,18 @@ mod imp {
|
|||
type Interfaces = (gio::ListModel,);
|
||||
}
|
||||
|
||||
impl ObjectImpl for DmUserList {
|
||||
fn properties() -> &'static [glib::ParamSpec] {
|
||||
static PROPERTIES: Lazy<Vec<glib::ParamSpec>> = Lazy::new(|| {
|
||||
vec![
|
||||
glib::ParamSpecObject::builder::<Session>("session")
|
||||
.construct_only()
|
||||
.build(),
|
||||
glib::ParamSpecString::builder("search-term")
|
||||
.explicit_notify()
|
||||
.build(),
|
||||
glib::ParamSpecEnum::builder::<DmUserListState>("state")
|
||||
.read_only()
|
||||
.build(),
|
||||
]
|
||||
});
|
||||
|
||||
PROPERTIES.as_ref()
|
||||
}
|
||||
|
||||
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
|
||||
match pspec.name() {
|
||||
"session" => self.session.set(value.get().unwrap()),
|
||||
"search-term" => self.obj().set_search_term(value.get().unwrap()),
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
|
||||
let obj = self.obj();
|
||||
|
||||
match pspec.name() {
|
||||
"session" => obj.session().to_value(),
|
||||
"search-term" => obj.search_term().to_value(),
|
||||
"state" => obj.state().to_value(),
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
#[glib::derived_properties]
|
||||
impl ObjectImpl for DmUserList {}
|
||||
|
||||
impl ListModelImpl for DmUserList {
|
||||
fn item_type(&self) -> glib::Type {
|
||||
DmUser::static_type()
|
||||
}
|
||||
|
||||
fn n_items(&self) -> u32 {
|
||||
self.list.borrow().len() as u32
|
||||
}
|
||||
|
||||
fn item(&self, position: u32) -> Option<glib::Object> {
|
||||
self.list
|
||||
.borrow()
|
||||
|
@ -95,6 +67,26 @@ mod imp {
|
|||
.and_upcast()
|
||||
}
|
||||
}
|
||||
|
||||
impl DmUserList {
|
||||
/// Set the search term.
|
||||
fn set_search_term(&self, search_term: Option<String>) {
|
||||
let search_term = search_term.filter(|s| !s.is_empty());
|
||||
|
||||
if search_term.as_ref() == self.search_term.borrow().as_ref() {
|
||||
return;
|
||||
}
|
||||
let obj = self.obj();
|
||||
|
||||
self.search_term.replace(search_term);
|
||||
|
||||
spawn!(clone!(@weak obj => async move {
|
||||
obj.search_users().await;
|
||||
}));
|
||||
|
||||
obj.notify_search_term();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glib::wrapper! {
|
||||
|
@ -108,34 +100,6 @@ impl DmUserList {
|
|||
glib::Object::builder().property("session", session).build()
|
||||
}
|
||||
|
||||
/// The session this list refers to.
|
||||
pub fn session(&self) -> Session {
|
||||
self.imp().session.upgrade().unwrap()
|
||||
}
|
||||
|
||||
/// Set the search term.
|
||||
pub fn set_search_term(&self, search_term: Option<String>) {
|
||||
let imp = self.imp();
|
||||
let search_term = search_term.filter(|s| !s.is_empty());
|
||||
|
||||
if search_term.as_ref() == imp.search_term.borrow().as_ref() {
|
||||
return;
|
||||
}
|
||||
|
||||
imp.search_term.replace(search_term);
|
||||
|
||||
spawn!(clone!(@weak self as obj => async move {
|
||||
obj.search_users().await;
|
||||
}));
|
||||
|
||||
self.notify("search_term");
|
||||
}
|
||||
|
||||
/// The search term.
|
||||
fn search_term(&self) -> Option<String> {
|
||||
self.imp().search_term.borrow().clone()
|
||||
}
|
||||
|
||||
/// Set the state of the list.
|
||||
fn set_state(&self, state: DmUserListState) {
|
||||
let imp = self.imp();
|
||||
|
@ -148,11 +112,6 @@ impl DmUserList {
|
|||
self.notify("state");
|
||||
}
|
||||
|
||||
/// The state of the list.
|
||||
pub fn state(&self) -> DmUserListState {
|
||||
self.imp().state.get()
|
||||
}
|
||||
|
||||
fn set_list(&self, users: Vec<DmUser>) {
|
||||
let added = users.len();
|
||||
|
||||
|
@ -166,7 +125,9 @@ impl DmUserList {
|
|||
}
|
||||
|
||||
async fn search_users(&self) {
|
||||
let session = self.session();
|
||||
let Some(session) = self.session() else {
|
||||
return;
|
||||
};
|
||||
let client = session.client();
|
||||
let Some(search_term) = self.search_term() else {
|
||||
self.set_state(DmUserListState::Initial);
|
||||
|
|
|
@ -6,13 +6,15 @@ mod imp {
|
|||
use std::cell::RefCell;
|
||||
|
||||
use glib::subclass::InitializingObject;
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[derive(Debug, Default, CompositeTemplate)]
|
||||
#[derive(Debug, Default, CompositeTemplate, glib::Properties)]
|
||||
#[template(resource = "/org/gnome/Fractal/ui/session/view/create_dm_dialog/dm_user_row.ui")]
|
||||
#[properties(wrapper_type = super::DmUserRow)]
|
||||
pub struct DmUserRow {
|
||||
/// The user displayed by this row.
|
||||
#[property(get, set = Self::set_user, explicit_notify)]
|
||||
pub user: RefCell<Option<DmUser>>,
|
||||
}
|
||||
|
||||
|
@ -31,36 +33,27 @@ mod imp {
|
|||
}
|
||||
}
|
||||
|
||||
impl ObjectImpl for DmUserRow {
|
||||
fn properties() -> &'static [glib::ParamSpec] {
|
||||
static PROPERTIES: Lazy<Vec<glib::ParamSpec>> = Lazy::new(|| {
|
||||
vec![glib::ParamSpecObject::builder::<DmUser>("user")
|
||||
.explicit_notify()
|
||||
.build()]
|
||||
});
|
||||
#[glib::derived_properties]
|
||||
impl ObjectImpl for DmUserRow {}
|
||||
|
||||
PROPERTIES.as_ref()
|
||||
}
|
||||
|
||||
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
|
||||
match pspec.name() {
|
||||
"user" => self.obj().set_user(value.get().unwrap()),
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
|
||||
match pspec.name() {
|
||||
"user" => self.obj().user().to_value(),
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl WidgetImpl for DmUserRow {}
|
||||
impl ListBoxRowImpl for DmUserRow {}
|
||||
|
||||
impl DmUserRow {
|
||||
/// Set the user displayed by this row.
|
||||
fn set_user(&self, user: Option<DmUser>) {
|
||||
if self.user.borrow().clone() == user {
|
||||
return;
|
||||
}
|
||||
|
||||
self.user.replace(user);
|
||||
self.obj().notify_user();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glib::wrapper! {
|
||||
/// A row of the DM user list.
|
||||
pub struct DmUserRow(ObjectSubclass<imp::DmUserRow>)
|
||||
@extends gtk::Widget, gtk::ListBoxRow, @implements gtk::Accessible;
|
||||
}
|
||||
|
@ -69,22 +62,4 @@ impl DmUserRow {
|
|||
pub fn new(user: &DmUser) -> Self {
|
||||
glib::Object::builder().property("user", user).build()
|
||||
}
|
||||
|
||||
/// The user displayed by this row.
|
||||
pub fn user(&self) -> Option<DmUser> {
|
||||
self.imp().user.borrow().clone()
|
||||
}
|
||||
|
||||
/// Set the user displayed by this row.
|
||||
pub fn set_user(&self, user: Option<DmUser>) {
|
||||
let imp = self.imp();
|
||||
let prev_user = self.user();
|
||||
|
||||
if prev_user == user {
|
||||
return;
|
||||
}
|
||||
|
||||
imp.user.replace(user);
|
||||
self.notify("user");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,14 +17,17 @@ use crate::{
|
|||
};
|
||||
|
||||
mod imp {
|
||||
use glib::{object::WeakRef, subclass::InitializingObject};
|
||||
use glib::subclass::InitializingObject;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[derive(Debug, Default, CompositeTemplate)]
|
||||
#[derive(Debug, Default, CompositeTemplate, glib::Properties)]
|
||||
#[template(resource = "/org/gnome/Fractal/ui/session/view/create_dm_dialog/mod.ui")]
|
||||
#[properties(wrapper_type = super::CreateDmDialog)]
|
||||
pub struct CreateDmDialog {
|
||||
pub session: WeakRef<Session>,
|
||||
/// The current session.
|
||||
#[property(get, set = Self::set_session, explicit_notify)]
|
||||
pub session: glib::WeakRef<Session>,
|
||||
#[template_child]
|
||||
pub list_box: TemplateChild<gtk::ListBox>,
|
||||
#[template_child]
|
||||
|
@ -59,40 +62,56 @@ mod imp {
|
|||
}
|
||||
}
|
||||
|
||||
impl ObjectImpl for CreateDmDialog {
|
||||
fn properties() -> &'static [glib::ParamSpec] {
|
||||
use once_cell::sync::Lazy;
|
||||
static PROPERTIES: Lazy<Vec<glib::ParamSpec>> = Lazy::new(|| {
|
||||
vec![glib::ParamSpecObject::builder::<Session>("session")
|
||||
.explicit_notify()
|
||||
.build()]
|
||||
});
|
||||
|
||||
PROPERTIES.as_ref()
|
||||
}
|
||||
|
||||
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
|
||||
match pspec.name() {
|
||||
"session" => self.obj().set_session(value.get().unwrap()),
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
|
||||
match pspec.name() {
|
||||
"session" => self.obj().session().to_value(),
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
#[glib::derived_properties]
|
||||
impl ObjectImpl for CreateDmDialog {}
|
||||
|
||||
impl WidgetImpl for CreateDmDialog {}
|
||||
impl WindowImpl for CreateDmDialog {}
|
||||
impl AdwWindowImpl for CreateDmDialog {}
|
||||
|
||||
impl CreateDmDialog {
|
||||
/// Set the current session.
|
||||
pub fn set_session(&self, session: Option<Session>) {
|
||||
if self.session.upgrade() == session {
|
||||
return;
|
||||
}
|
||||
let obj = self.obj();
|
||||
|
||||
if let Some(session) = &session {
|
||||
let user_list = DmUserList::new(session);
|
||||
|
||||
// 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);
|
||||
}));
|
||||
|
||||
self.search_entry
|
||||
.bind_property("text", &user_list, "search-term")
|
||||
.sync_create()
|
||||
.build();
|
||||
|
||||
self.list_box.bind_model(Some(&user_list), |user| {
|
||||
DmUserRow::new(
|
||||
user.downcast_ref::<DmUser>()
|
||||
.expect("DmUserList must contain only `DmUser`"),
|
||||
)
|
||||
.upcast()
|
||||
});
|
||||
|
||||
obj.update_view(&user_list);
|
||||
} else {
|
||||
self.list_box.unbind_model();
|
||||
}
|
||||
|
||||
self.session.set(session.as_ref());
|
||||
obj.notify_session();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glib::wrapper! {
|
||||
/// Preference Window to display and update room details.
|
||||
/// Dialog to create a new direct chat.
|
||||
pub struct CreateDmDialog(ObjectSubclass<imp::CreateDmDialog>)
|
||||
@extends gtk::Widget, gtk::Window, adw::Window, adw::Bin, @implements gtk::Accessible;
|
||||
}
|
||||
|
@ -106,53 +125,6 @@ impl CreateDmDialog {
|
|||
.build()
|
||||
}
|
||||
|
||||
/// The current session.
|
||||
pub fn session(&self) -> Option<Session> {
|
||||
self.imp().session.upgrade()
|
||||
}
|
||||
|
||||
/// Set the current session.
|
||||
pub fn set_session(&self, session: Option<Session>) {
|
||||
let imp = self.imp();
|
||||
|
||||
if self.session() == session {
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(ref session) = session {
|
||||
let user_list = DmUserList::new(session);
|
||||
|
||||
// We don't need to disconnect this signal since the `DmUserList` will be
|
||||
// disposed once unbound from the `gtk::ListBox`
|
||||
user_list.connect_notify_local(
|
||||
Some("state"),
|
||||
clone!(@weak self as obj => move |model, _| {
|
||||
obj.update_view(model);
|
||||
}),
|
||||
);
|
||||
|
||||
imp.search_entry
|
||||
.bind_property("text", &user_list, "search-term")
|
||||
.sync_create()
|
||||
.build();
|
||||
|
||||
imp.list_box.bind_model(Some(&user_list), |user| {
|
||||
DmUserRow::new(
|
||||
user.downcast_ref::<DmUser>()
|
||||
.expect("DmUserList must contain only `DmUser`"),
|
||||
)
|
||||
.upcast()
|
||||
});
|
||||
|
||||
self.update_view(&user_list);
|
||||
} else {
|
||||
imp.list_box.unbind_model();
|
||||
}
|
||||
|
||||
imp.session.set(session.as_ref());
|
||||
self.notify("session");
|
||||
}
|
||||
|
||||
fn update_view(&self, model: &DmUserList) {
|
||||
let visible_child_name = match model.state() {
|
||||
DmUserListState::Initial => "no-search-page",
|
||||
|
|
Loading…
Reference in New Issue