[fractal/fractal-next] room_details: Add editing of room name and topic
- From: Julian Sparber <jsparber src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [fractal/fractal-next] room_details: Add editing of room name and topic
- Date: Mon, 23 Aug 2021 15:02:20 +0000 (UTC)
commit 7ce448ba625d61fce8576416b17e946630ad81a0
Author: Kai A. Hiller <V02460 gmail com>
Date: Sat Jul 10 14:33:56 2021 +0200
room_details: Add editing of room name and topic
data/resources/ui/content-room-details.ui | 1 -
src/session/content/room_details/room_details.rs | 56 ++++++++++++++-
src/session/room/room.rs | 89 ++++++++++++++++++++++--
3 files changed, 138 insertions(+), 8 deletions(-)
---
diff --git a/data/resources/ui/content-room-details.ui b/data/resources/ui/content-room-details.ui
index 913f4f44..20cda5d0 100644
--- a/data/resources/ui/content-room-details.ui
+++ b/data/resources/ui/content-room-details.ui
@@ -69,7 +69,6 @@
<child>
<object class="GtkToggleButton" id="edit_toggle">
<property name="halign">center</property>
- <property name="label" translatable="yes">Edit Details</property>
</object>
</child>
</object>
diff --git a/src/session/content/room_details/room_details.rs
b/src/session/content/room_details/room_details.rs
index 4da4a807..10b3b313 100644
--- a/src/session/content/room_details/room_details.rs
+++ b/src/session/content/room_details/room_details.rs
@@ -1,5 +1,11 @@
use adw::subclass::prelude::*;
-use gtk::{glib, prelude::*, subclass::prelude::*, CompositeTemplate};
+use gettextrs::gettext;
+use gtk::{
+ glib::{self, clone},
+ prelude::*,
+ subclass::prelude::*,
+ CompositeTemplate,
+};
use crate::components::CustomEntry;
use crate::session::Room;
@@ -13,6 +19,12 @@ mod imp {
#[template(resource = "/org/gnome/FractalNext/content-room-details.ui")]
pub struct RoomDetails {
pub room: OnceCell<Room>,
+ #[template_child]
+ pub edit_toggle: TemplateChild<gtk::ToggleButton>,
+ #[template_child]
+ pub room_name_entry: TemplateChild<gtk::Entry>,
+ #[template_child]
+ pub room_topic_text_view: TemplateChild<gtk::TextView>,
}
#[glib::object_subclass]
@@ -66,6 +78,12 @@ mod imp {
_ => unimplemented!(),
}
}
+
+ fn constructed(&self, obj: &Self::Type) {
+ self.parent_constructed(obj);
+
+ obj.init_edit_toggle();
+ }
}
impl WidgetImpl for RoomDetails {}
@@ -96,4 +114,40 @@ impl RoomDetails {
let priv_ = imp::RoomDetails::from_instance(self);
priv_.room.set(room).expect("Room already initialized");
}
+
+ fn init_edit_toggle(&self) {
+ let priv_ = imp::RoomDetails::from_instance(self);
+ let edit_toggle = &priv_.edit_toggle;
+ let label_enabled = gettext("Save Details");
+ let label_disabled = gettext("Edit Details");
+
+ edit_toggle.set_active(false);
+ edit_toggle.set_label(&label_disabled);
+
+ // Save changes of name and topic on toggle button release.
+ edit_toggle.connect_toggled(clone!(@weak self as this => move |button| {
+ if button.is_active() {
+ button.set_label(&label_enabled);
+ return;
+ }
+ button.set_label(&label_disabled);
+
+ let priv_ = imp::RoomDetails::from_instance(&this);
+ let room = this.room();
+
+ let room_name = priv_.room_name_entry.buffer().text();
+ let topic_buffer = priv_.room_topic_text_view.buffer();
+ let topic = topic_buffer.text(&topic_buffer.start_iter(), &topic_buffer.end_iter(), true);
+ room.store_room_name(room_name);
+ room.store_topic(topic.to_string());
+ }));
+
+ // End editing on enter.
+ priv_
+ .room_name_entry
+ .connect_activate(clone!(@weak self as this => move |_entry| {
+ let priv_ = imp::RoomDetails::from_instance(&this);
+ priv_.edit_toggle.set_active(false);
+ }));
+ }
}
diff --git a/src/session/room/room.rs b/src/session/room/room.rs
index ab32b8b1..dda7f3c7 100644
--- a/src/session/room/room.rs
+++ b/src/session/room/room.rs
@@ -1,6 +1,6 @@
use gettextrs::gettext;
use gtk::{glib, glib::clone, prelude::*, subclass::prelude::*};
-use log::{debug, error, warn};
+use log::{debug, error, info, warn};
use matrix_sdk::{
deserialized_responses::{JoinedRoom, LeftRoom},
room::Room as MatrixRoom,
@@ -13,10 +13,13 @@ use matrix_sdk::{
EmoteMessageEventContent, MessageEventContent, MessageType,
TextMessageEventContent,
},
+ name::NameEventContent,
+ topic::TopicEventContent,
},
tag::TagName,
- AnyRoomAccountDataEvent, AnyStrippedStateEvent, AnySyncMessageEvent, AnySyncRoomEvent,
- AnySyncStateEvent, SyncMessageEvent, SyncStateEvent, Unsigned,
+ AnyRoomAccountDataEvent, AnyStateEventContent, AnyStrippedStateEvent,
+ AnySyncMessageEvent, AnySyncRoomEvent, AnySyncStateEvent, SyncMessageEvent,
+ SyncStateEvent, Unsigned,
},
identifiers::{EventId, RoomId, UserId},
serde::Raw,
@@ -27,7 +30,7 @@ use matrix_sdk::{
};
use serde_json::value::RawValue;
use std::cell::RefCell;
-use std::convert::TryFrom;
+use std::convert::{TryFrom, TryInto};
use crate::components::{LabelWithWidgets, Pill};
use crate::prelude::*;
@@ -93,7 +96,7 @@ mod imp {
"Display Name",
"The display name of this room",
None,
- glib::ParamFlags::READABLE,
+ glib::ParamFlags::READWRITE,
),
glib::ParamSpec::new_object(
"inviter",
@@ -146,7 +149,7 @@ mod imp {
"Topic",
"The topic of this room",
None,
- glib::ParamFlags::READABLE,
+ glib::ParamFlags::READWRITE,
),
glib::ParamSpec::new_boxed(
"latest-change",
@@ -170,6 +173,10 @@ mod imp {
) {
match pspec.name() {
"session" => self.session.set(value.get().unwrap()).unwrap(),
+ "display-name" => {
+ let room_name = value.get().unwrap();
+ obj.store_room_name(room_name)
+ }
"category" => {
let category = value.get().unwrap();
obj.set_category(category);
@@ -178,6 +185,10 @@ mod imp {
.room_id
.set(RoomId::try_from(value.get::<&str>().unwrap()).unwrap())
.unwrap(),
+ "topic" => {
+ let topic = value.get().unwrap();
+ obj.store_topic(topic);
+ }
_ => unimplemented!(),
}
}
@@ -500,6 +511,43 @@ impl Room {
);
}
+ /// Updates the Matrix room with the given name.
+ pub fn store_room_name(&self, room_name: String) {
+ if self.display_name() == room_name {
+ return;
+ }
+
+ let joined_room = match self.matrix_room() {
+ MatrixRoom::Joined(joined_room) => joined_room,
+ _ => {
+ error!("Room name can’t be changed when not a member.");
+ return;
+ }
+ };
+ let room_name = match room_name.try_into() {
+ Ok(room_name) => room_name,
+ Err(e) => {
+ error!("Invalid room name: {}", e);
+ return;
+ }
+ };
+ let name_content = NameEventContent::new(Some(room_name));
+
+ do_async(
+ glib::PRIORITY_DEFAULT_IDLE,
+ async move {
+ let content = AnyStateEventContent::RoomName(name_content);
+ joined_room.send_state_event(content, "").await
+ },
+ clone!(@weak self as obj => move |room_name| async move {
+ match room_name {
+ Ok(_room_name) => info!("Successfully updated room name"),
+ Err(error) => error!("Couldn’t update room name: {}", error),
+ };
+ }),
+ );
+ }
+
pub fn avatar(&self) -> &Avatar {
let priv_ = imp::Room::from_instance(self);
priv_.avatar.get().unwrap()
@@ -511,6 +559,35 @@ impl Room {
.filter(|topic| !topic.is_empty() && topic.find(|c: char| !c.is_whitespace()).is_some())
}
+ /// Updates the Matrix room with the given topic.
+ pub fn store_topic(&self, topic: String) {
+ if self.topic().as_ref() == Some(&topic) {
+ return;
+ }
+
+ let joined_room = match self.matrix_room() {
+ MatrixRoom::Joined(joined_room) => joined_room,
+ _ => {
+ error!("Room topic can’t be changed when not a member.");
+ return;
+ }
+ };
+
+ do_async(
+ glib::PRIORITY_DEFAULT_IDLE,
+ async move {
+ let content = AnyStateEventContent::RoomTopic(TopicEventContent::new(topic));
+ joined_room.send_state_event(content, "").await
+ },
+ clone!(@weak self as obj => move |topic| async move {
+ match topic {
+ Ok(_topic) => info!("Successfully updated room topic"),
+ Err(error) => error!("Couldn’t update topic: {}", error),
+ };
+ }),
+ );
+ }
+
pub fn power_levels(&self) -> PowerLevels {
let priv_ = imp::Room::from_instance(self);
priv_.power_levels.borrow().clone()
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]