[fractal/fractal-next] content: Move room history to it's own widget
- From: Julian Sparber <jsparber src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [fractal/fractal-next] content: Move room history to it's own widget
- Date: Mon, 24 May 2021 14:16:36 +0000 (UTC)
commit df5408cc8cf2b81993ab3c52b6c6680c176ed516
Author: Julian Sparber <julian sparber net>
Date: Wed May 19 09:57:06 2021 +0200
content: Move room history to it's own widget
This will allow us to add different content widgets, e.g. for invites
data/resources/resources.gresource.xml | 1 +
data/resources/ui/content-room-history.ui | 151 +++++++++++++++++++
data/resources/ui/content.ui | 145 +------------------
po/POTFILES.in | 2 +
src/meson.build | 1 +
src/session/content/content.rs | 118 +--------------
src/session/content/mod.rs | 2 +
src/session/content/room_history.rs | 233 ++++++++++++++++++++++++++++++
8 files changed, 399 insertions(+), 254 deletions(-)
---
diff --git a/data/resources/resources.gresource.xml b/data/resources/resources.gresource.xml
index de778fa9..5acbb7e1 100644
--- a/data/resources/resources.gresource.xml
+++ b/data/resources/resources.gresource.xml
@@ -3,6 +3,7 @@
<gresource prefix="/org/gnome/FractalNext/">
<file compressed="true" preprocess="xml-stripblanks" alias="shortcuts.ui">ui/shortcuts.ui</file>
<file compressed="true" preprocess="xml-stripblanks" alias="content.ui">ui/content.ui</file>
+ <file compressed="true" preprocess="xml-stripblanks"
alias="content-room-history.ui">ui/content-room-history.ui</file>
<file compressed="true" preprocess="xml-stripblanks" alias="content-item.ui">ui/content-item.ui</file>
<file compressed="true" preprocess="xml-stripblanks"
alias="content-message-row.ui">ui/content-message-row.ui</file>
<file compressed="true" preprocess="xml-stripblanks"
alias="content-divider-row.ui">ui/content-divider-row.ui</file>
diff --git a/data/resources/ui/content-room-history.ui b/data/resources/ui/content-room-history.ui
new file mode 100644
index 00000000..97509615
--- /dev/null
+++ b/data/resources/ui/content-room-history.ui
@@ -0,0 +1,151 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="ContentRoomHistory" parent="AdwBin">
+ <property name="vexpand">True</property>
+ <property name="hexpand">True</property>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="AdwHeaderBar" id="headerbar">
+ <property name="show-start-title-buttons" bind-source="ContentRoomHistory"
bind-property="compact" bind-flags="sync-create"/>
+ <child type="start">
+ <object class="GtkButton" id="back">
+ <property name="visible" bind-source="ContentRoomHistory" bind-property="compact"
bind-flags="sync-create"/>
+ <property name="icon-name">go-previous-symbolic</property>
+ <property name="action-name">content.go-back</property>
+ </object>
+ </child>
+ <child type="title">
+ <object class="AdwWindowTitle">
+ <binding name="title">
+ <lookup name="display-name">
+ <lookup name="room">ContentRoomHistory</lookup>
+ </lookup>
+ </binding>
+ <binding name="subtitle">
+ <lookup name="topic">
+ <lookup name="room">ContentRoomHistory</lookup>
+ </lookup>
+ </binding>
+ </object>
+ </child>
+ <child type="end">
+ <object class="GtkMenuButton" id="room_menu">
+ <property name="icon-name">view-more-symbolic</property>
+ </object>
+ </child>
+ <child type="end">
+ <object class="GtkToggleButton" id="search_content_button">
+ <property name="icon-name">system-search-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSearchBar" id="room_search">
+ <property name="search-mode-enabled" bind-source="search_content_button" bind-property="active"/>
+ <property name="child">
+ <object class="AdwClamp">
+ <property name="hexpand">True</property>
+ <child>
+ <object class="GtkSearchEntry"/>
+ </child>
+ </object>
+ </property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolled_window">
+ <property name="vexpand">True</property>
+ <property name="hscrollbar-policy">never</property>
+ <style>
+ <class name="content"/>
+ </style>
+ <property name="child">
+ <object class="AdwClampScrollable">
+ <property name="vexpand">True</property>
+ <property name="hexpand">True</property>
+ <property name="child">
+ <object class="GtkListView" id="listview">
+ <style>
+ <class name="navigation-sidebar"/>
+ </style>
+ <property name="factory">
+ <object class="GtkBuilderListItemFactory">
+ <property name="resource">/org/gnome/FractalNext/content-item.ui</property>
+ </object>
+ </property>
+ <accessibility>
+ <property name="label" translatable="yes">Room History</property>
+ </accessibility>
+ </object>
+ </property>
+ </object>
+ </property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSeparator"/>
+ </child>
+ <child>
+ <object class="AdwClamp">
+ <child>
+ <object class="GtkBox">
+ <property name="spacing">6</property>
+ <style>
+ <class name="send-message-area"/>
+ </style>
+ <child>
+ <object class="GtkButton">
+ <property name="icon-name">mail-attachment-symbolic</property>
+ <property name="action-name">room-history.select-file</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkMenuButton" id="markdown_button">
+ <property name="direction">up</property>
+ <property name="icon-name">format-justify-left-symbolic</property>
+ <property name="popover">
+ <object class="MarkdownPopover">
+ <property name="markdown-enabled" bind-source="ContentRoomHistory"
bind-property="markdown-enabled" bind-flags="sync-create | bidirectional"/>
+ </object>
+ </property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolled_window">
+ <property name="vexpand">True</property>
+ <property name="hexpand">True</property>
+ <property name="vscrollbar-policy">external</property>
+ <property name="max-content-height">200</property>
+ <property name="propagate-natural-height">True</property>
+ <property name="child">
+ <object class="GtkSourceView" id="message_entry">
+ <property name="hexpand">True</property>
+ </object>
+ </property>
+ <style>
+ <class name="message-entry"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton">
+ <property name="icon-name">send-symbolic</property>
+ <property name="focus-on-click">False</property>
+ <property name="action-name">room-history.send-text-message</property>
+ <style>
+ <class name="suggested-action"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
+
diff --git a/data/resources/ui/content.ui b/data/resources/ui/content.ui
index 25395e48..332a6054 100644
--- a/data/resources/ui/content.ui
+++ b/data/resources/ui/content.ui
@@ -3,149 +3,16 @@
<template class="Content" parent="AdwBin">
<property name="vexpand">True</property>
<property name="hexpand">True</property>
- <child>
- <object class="GtkBox">
- <property name="orientation">vertical</property>
+ <property name="child">
+ <object class="GtkStack">
<child>
- <object class="AdwHeaderBar" id="headerbar">
- <property name="show-start-title-buttons" bind-source="Content" bind-property="compact"
bind-flags="sync-create"/>
- <child type="start">
- <object class="GtkButton" id="back">
- <property name="visible" bind-source="Content" bind-property="compact"
bind-flags="sync-create"/>
- <property name="icon-name">go-previous-symbolic</property>
- <property name="action-name">content.go-back</property>
- </object>
- </child>
- <child type="title">
- <object class="AdwWindowTitle">
- <binding name="title">
- <lookup name="display-name">
- <lookup name="room">Content</lookup>
- </lookup>
- </binding>
- <binding name="subtitle">
- <lookup name="topic">
- <lookup name="room">Content</lookup>
- </lookup>
- </binding>
- </object>
- </child>
- <child type="end">
- <object class="GtkMenuButton" id="room_menu">
- <property name="icon-name">view-more-symbolic</property>
- </object>
- </child>
- <child type="end">
- <object class="GtkToggleButton" id="search_content_button">
- <property name="icon-name">system-search-symbolic</property>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkSearchBar" id="room_search">
- <property name="search-mode-enabled" bind-source="search_content_button" bind-property="active"/>
- <property name="child">
- <object class="AdwClamp">
- <property name="hexpand">True</property>
- <child>
- <object class="GtkSearchEntry"/>
- </child>
- </object>
- </property>
- </object>
- </child>
- <child>
- <object class="GtkScrolledWindow" id="scrolled_window">
- <property name="vexpand">True</property>
- <property name="hscrollbar-policy">never</property>
- <style>
- <class name="content"/>
- </style>
- <property name="child">
- <object class="AdwClampScrollable">
- <property name="vexpand">True</property>
- <property name="hexpand">True</property>
- <property name="child">
- <object class="GtkListView" id="listview">
- <style>
- <class name="navigation-sidebar"/>
- </style>
- <property name="factory">
- <object class="GtkBuilderListItemFactory">
- <property name="resource">/org/gnome/FractalNext/content-item.ui</property>
- </object>
- </property>
- <accessibility>
- <property name="label" translatable="yes">Room History</property>
- </accessibility>
- </object>
- </property>
- </object>
- </property>
- </object>
- </child>
- <child>
- <object class="GtkSeparator"/>
- </child>
- <child>
- <object class="AdwClamp">
- <child>
- <object class="GtkBox">
- <property name="spacing">6</property>
- <style>
- <class name="send-message-area"/>
- </style>
- <child>
- <object class="GtkButton">
- <property name="icon-name">mail-attachment-symbolic</property>
- <property name="action-name">content.select-file</property>
- </object>
- </child>
- <child>
- <object class="GtkMenuButton" id="markdown_button">
- <property name="direction">up</property>
- <property name="icon-name">format-justify-left-symbolic</property>
- <property name="popover">
- <object class="MarkdownPopover">
- <property name="markdown-enabled" bind-source="Content"
bind-property="markdown-enabled" bind-flags="sync-create | bidirectional"/>
- </object>
- </property>
- </object>
- </child>
- <child>
- <object class="GtkScrolledWindow" id="scrolled_window">
- <property name="vexpand">True</property>
- <property name="hexpand">True</property>
- <property name="vscrollbar-policy">external</property>
- <property name="max-content-height">200</property>
- <property name="propagate-natural-height">True</property>
- <property name="child">
- <object class="GtkSourceView" id="message_entry">
- <property name="hexpand">True</property>
- </object>
- </property>
- <style>
- <class name="message-entry"/>
- </style>
- </object>
- </child>
- <child>
- <object class="GtkButton">
- <property name="icon-name">send-symbolic</property>
- <property name="focus-on-click">False</property>
- <property name="action-name">content.send-text-message</property>
- <style>
- <class name="suggested-action"/>
- </style>
- </object>
- </child>
- </object>
- </child>
+ <object class="ContentRoomHistory">
+ <property name="compact" bind-source="Content" bind-property="compact" bind-flags="sync-create"/>
+ <property name="room" bind-source="Content" bind-property="room" bind-flags="sync-create"/>
</object>
</child>
</object>
- </child>
+ </property>
</template>
</interface>
diff --git a/po/POTFILES.in b/po/POTFILES.in
index e9636663..1ef516a9 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -10,6 +10,7 @@ data/resources/ui/content-item-row-menu.ui
data/resources/ui/content-item.ui
data/resources/ui/content-markdown-popover.ui
data/resources/ui/content-message-row.ui
+data/resources/ui/content-room-history.ui
data/resources/ui/content-state-row.ui
data/resources/ui/content.ui
data/resources/ui/context-menu-bin.ui
@@ -39,6 +40,7 @@ src/session/content/item_row.rs
src/session/content/markdown_popover.rs
src/session/content/message_row.rs
src/session/content/mod.rs
+src/session/content/room_history.rs
src/session/content/state_row.rs
src/session/mod.rs
src/session/room/event.rs
diff --git a/src/meson.build b/src/meson.build
index d40c17af..1606799e 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -38,6 +38,7 @@ sources = files(
'session/content/markdown_popover.rs',
'session/content/message_row.rs',
'session/content/mod.rs',
+ 'session/content/room_history.rs',
'session/content/state_row.rs',
'session/room/event.rs',
'session/room/highlight_flags.rs',
diff --git a/src/session/content/content.rs b/src/session/content/content.rs
index 5e1ec760..901dce20 100644
--- a/src/session/content/content.rs
+++ b/src/session/content/content.rs
@@ -1,14 +1,9 @@
-use crate::session::{content::ItemRow, content::MarkdownPopover, room::Room};
+use crate::session::{content::RoomHistory, room::Room};
use adw::subclass::prelude::*;
-use gtk::{
- gdk, glib, glib::clone, glib::signal::Inhibit, prelude::*, subclass::prelude::*,
- CompositeTemplate,
-};
-use sourceview::prelude::*;
+use gtk::{glib, prelude::*, subclass::prelude::*, CompositeTemplate};
mod imp {
use super::*;
- use crate::Application;
use glib::subclass::InitializingObject;
use std::cell::{Cell, RefCell};
@@ -17,17 +12,6 @@ mod imp {
pub struct Content {
pub compact: Cell<bool>,
pub room: RefCell<Option<Room>>,
- pub md_enabled: Cell<bool>,
- #[template_child]
- pub headerbar: TemplateChild<adw::HeaderBar>,
- #[template_child]
- pub listview: TemplateChild<gtk::ListView>,
- #[template_child]
- pub scrolled_window: TemplateChild<gtk::ScrolledWindow>,
- #[template_child]
- pub message_entry: TemplateChild<sourceview::View>,
- #[template_child]
- pub markdown_button: TemplateChild<gtk::MenuButton>,
}
#[glib::object_subclass]
@@ -37,17 +21,13 @@ mod imp {
type ParentType = adw::Bin;
fn class_init(klass: &mut Self::Class) {
- ItemRow::static_type();
- MarkdownPopover::static_type();
+ RoomHistory::static_type();
Self::bind_template(klass);
klass.set_accessible_role(gtk::AccessibleRole::Group);
klass.install_action("content.go-back", None, move |widget, _, _| {
widget.set_room(None);
});
- klass.install_action("content.send-text-message", None, move |widget, _, _| {
- widget.send_text_message();
- });
}
fn instance_init(obj: &InitializingObject<Self>) {
@@ -74,13 +54,6 @@ mod imp {
Room::static_type(),
glib::ParamFlags::READWRITE | glib::ParamFlags::EXPLICIT_NOTIFY,
),
- glib::ParamSpec::new_boolean(
- "markdown-enabled",
- "Markdown enabled",
- "Whether or not to do markdown formatting when sending messages",
- false,
- glib::ParamFlags::READWRITE,
- ),
]
});
@@ -103,15 +76,6 @@ mod imp {
let room = value.get().unwrap();
obj.set_room(room);
}
- "markdown-enabled" => {
- let md_enabled = value.get().unwrap();
- self.md_enabled.set(md_enabled);
- self.markdown_button.set_icon_name(if md_enabled {
- "format-indent-more-symbolic"
- } else {
- "format-justify-left-symbolic"
- });
- }
_ => unimplemented!(),
}
}
@@ -120,66 +84,9 @@ mod imp {
match pspec.name() {
"compact" => self.compact.get().to_value(),
"room" => obj.room().to_value(),
- "markdown-enabled" => self.md_enabled.get().to_value(),
_ => unimplemented!(),
}
}
-
- fn constructed(&self, obj: &Self::Type) {
- let adj = self.scrolled_window.vadjustment().unwrap();
- // TODO: make sure that we have enough messages to fill at least to scroll pages, if the room
history is long enough
-
- adj.connect_value_changed(clone!(@weak obj => move |adj| {
- // Load more message when the user gets close to the end of the known room history
- // Use the page size twice to detect if the user gets close the end
- if adj.value() < adj.page_size() * 2.0 {
- if let Some(room) = obj.room() {
- room.load_previous_events();
- }
- }
- }));
-
- let key_events = gtk::EventControllerKey::new();
- self.message_entry.add_controller(&key_events);
-
- key_events
- .connect_key_pressed(clone!(@weak obj => @default-return Inhibit(false), move |_, key, _,
modifier| {
- if !modifier.contains(gdk::ModifierType::SHIFT_MASK) && (key == gdk::keys::constants::Return
|| key == gdk::keys::constants::KP_Enter) {
- obj.activate_action("content.send-text-message", None);
- Inhibit(true)
- } else {
- Inhibit(false)
- }
- }));
-
- let buffer = self
- .message_entry
- .buffer()
- .downcast::<sourceview::Buffer>()
- .unwrap();
-
- buffer.connect_text_notify(clone!(@weak obj => move |buffer| {
- let (start_iter, end_iter) = buffer.bounds();
- obj.action_set_enabled("content.send-text-message", start_iter != end_iter);
- }));
-
- let (start_iter, end_iter) = buffer.bounds();
- obj.action_set_enabled("content.send-text-message", start_iter != end_iter);
-
- let md_lang =
- sourceview::LanguageManager::default().and_then(|lm| lm.language("markdown"));
- buffer.set_language(md_lang.as_ref());
- obj.bind_property("markdown-enabled", &buffer, "highlight-syntax")
- .flags(glib::BindingFlags::SYNC_CREATE)
- .build();
-
- let settings = Application::default().settings();
- settings
- .bind("markdown-enabled", obj, "markdown-enabled")
- .build();
-
- self.parent_constructed(obj);
- }
}
impl WidgetImpl for Content {}
@@ -203,12 +110,6 @@ impl Content {
return;
}
- // TODO: use gtk::MultiSelection to allow selection
- let model = room
- .as_ref()
- .and_then(|room| Some(gtk::NoSelection::new(Some(room.timeline()))));
-
- priv_.listview.set_model(model.as_ref());
priv_.room.replace(room);
self.notify("room");
}
@@ -217,17 +118,4 @@ impl Content {
let priv_ = imp::Content::from_instance(self);
priv_.room.borrow().clone()
}
-
- pub fn send_text_message(&self) {
- let priv_ = imp::Content::from_instance(self);
- let buffer = priv_.message_entry.buffer();
- let (start_iter, end_iter) = buffer.bounds();
- let body = buffer.text(&start_iter, &end_iter, true);
-
- if let Some(room) = &*priv_.room.borrow() {
- room.send_text_message(body.as_str(), priv_.md_enabled.get());
- }
-
- buffer.set_text("");
- }
}
diff --git a/src/session/content/mod.rs b/src/session/content/mod.rs
index 40ec26b2..2aa007f0 100644
--- a/src/session/content/mod.rs
+++ b/src/session/content/mod.rs
@@ -3,6 +3,7 @@ mod divider_row;
mod item_row;
mod markdown_popover;
mod message_row;
+mod room_history;
mod state_row;
pub use self::content::Content;
@@ -10,4 +11,5 @@ use self::divider_row::DividerRow;
use self::item_row::ItemRow;
use self::markdown_popover::MarkdownPopover;
use self::message_row::MessageRow;
+use self::room_history::RoomHistory;
use self::state_row::StateRow;
diff --git a/src/session/content/room_history.rs b/src/session/content/room_history.rs
new file mode 100644
index 00000000..764bea01
--- /dev/null
+++ b/src/session/content/room_history.rs
@@ -0,0 +1,233 @@
+use crate::session::{content::ItemRow, content::MarkdownPopover, room::Room};
+use adw::subclass::prelude::*;
+use gtk::{
+ gdk, glib, glib::clone, glib::signal::Inhibit, prelude::*, subclass::prelude::*,
+ CompositeTemplate,
+};
+use sourceview::prelude::*;
+
+mod imp {
+ use super::*;
+ use crate::Application;
+ use glib::subclass::InitializingObject;
+ use std::cell::{Cell, RefCell};
+
+ #[derive(Debug, Default, CompositeTemplate)]
+ #[template(resource = "/org/gnome/FractalNext/content-room-history.ui")]
+ pub struct RoomHistory {
+ pub compact: Cell<bool>,
+ pub room: RefCell<Option<Room>>,
+ pub md_enabled: Cell<bool>,
+ #[template_child]
+ pub headerbar: TemplateChild<adw::HeaderBar>,
+ #[template_child]
+ pub listview: TemplateChild<gtk::ListView>,
+ #[template_child]
+ pub scrolled_window: TemplateChild<gtk::ScrolledWindow>,
+ #[template_child]
+ pub message_entry: TemplateChild<sourceview::View>,
+ #[template_child]
+ pub markdown_button: TemplateChild<gtk::MenuButton>,
+ }
+
+ #[glib::object_subclass]
+ impl ObjectSubclass for RoomHistory {
+ const NAME: &'static str = "ContentRoomHistory";
+ type Type = super::RoomHistory;
+ type ParentType = adw::Bin;
+
+ fn class_init(klass: &mut Self::Class) {
+ ItemRow::static_type();
+ MarkdownPopover::static_type();
+ Self::bind_template(klass);
+ klass.set_accessible_role(gtk::AccessibleRole::Group);
+ klass.install_action(
+ "room-history.send-text-message",
+ None,
+ move |widget, _, _| {
+ widget.send_text_message();
+ },
+ );
+ }
+
+ fn instance_init(obj: &InitializingObject<Self>) {
+ obj.init_template();
+ }
+ }
+
+ impl ObjectImpl for RoomHistory {
+ fn properties() -> &'static [glib::ParamSpec] {
+ use once_cell::sync::Lazy;
+ static PROPERTIES: Lazy<Vec<glib::ParamSpec>> = Lazy::new(|| {
+ vec![
+ glib::ParamSpec::new_boolean(
+ "compact",
+ "Compact",
+ "Wheter a compact view is used or not",
+ false,
+ glib::ParamFlags::READWRITE,
+ ),
+ glib::ParamSpec::new_object(
+ "room",
+ "Room",
+ "The room currently shown",
+ Room::static_type(),
+ glib::ParamFlags::READWRITE | glib::ParamFlags::EXPLICIT_NOTIFY,
+ ),
+ glib::ParamSpec::new_boolean(
+ "markdown-enabled",
+ "Markdown enabled",
+ "Whether or not to do markdown formatting when sending messages",
+ false,
+ glib::ParamFlags::READWRITE,
+ ),
+ ]
+ });
+
+ PROPERTIES.as_ref()
+ }
+
+ fn set_property(
+ &self,
+ obj: &Self::Type,
+ _id: usize,
+ value: &glib::Value,
+ pspec: &glib::ParamSpec,
+ ) {
+ match pspec.name() {
+ "compact" => {
+ let compact = value.get().unwrap();
+ self.compact.set(compact);
+ }
+ "room" => {
+ let room = value.get().unwrap();
+ obj.set_room(room);
+ }
+ "markdown-enabled" => {
+ let md_enabled = value.get().unwrap();
+ self.md_enabled.set(md_enabled);
+ self.markdown_button.set_icon_name(if md_enabled {
+ "format-indent-more-symbolic"
+ } else {
+ "format-justify-left-symbolic"
+ });
+ }
+ _ => unimplemented!(),
+ }
+ }
+
+ fn property(&self, obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
+ match pspec.name() {
+ "compact" => self.compact.get().to_value(),
+ "room" => obj.room().to_value(),
+ "markdown-enabled" => self.md_enabled.get().to_value(),
+ _ => unimplemented!(),
+ }
+ }
+
+ fn constructed(&self, obj: &Self::Type) {
+ let adj = self.scrolled_window.vadjustment().unwrap();
+ // TODO: make sure that we have enough messages to fill at least to scroll pages, if the room
history is long enough
+
+ adj.connect_value_changed(clone!(@weak obj => move |adj| {
+ // Load more message when the user gets close to the end of the known room history
+ // Use the page size twice to detect if the user gets close the end
+ if adj.value() < adj.page_size() * 2.0 {
+ if let Some(room) = obj.room() {
+ room.load_previous_events();
+ }
+ }
+ }));
+
+ let key_events = gtk::EventControllerKey::new();
+ self.message_entry.add_controller(&key_events);
+
+ key_events
+ .connect_key_pressed(clone!(@weak obj => @default-return Inhibit(false), move |_, key, _,
modifier| {
+ if !modifier.contains(gdk::ModifierType::SHIFT_MASK) && (key == gdk::keys::constants::Return
|| key == gdk::keys::constants::KP_Enter) {
+ obj.activate_action("content.send-text-message", None);
+ Inhibit(true)
+ } else {
+ Inhibit(false)
+ }
+ }));
+
+ let buffer = self
+ .message_entry
+ .buffer()
+ .downcast::<sourceview::Buffer>()
+ .unwrap();
+
+ buffer.connect_text_notify(clone!(@weak obj => move |buffer| {
+ let (start_iter, end_iter) = buffer.bounds();
+ obj.action_set_enabled("content.send-text-message", start_iter != end_iter);
+ }));
+
+ let (start_iter, end_iter) = buffer.bounds();
+ obj.action_set_enabled("content.send-text-message", start_iter != end_iter);
+
+ let md_lang =
+ sourceview::LanguageManager::default().and_then(|lm| lm.language("markdown"));
+ buffer.set_language(md_lang.as_ref());
+ obj.bind_property("markdown-enabled", &buffer, "highlight-syntax")
+ .flags(glib::BindingFlags::SYNC_CREATE)
+ .build();
+
+ let settings = Application::default().settings();
+ settings
+ .bind("markdown-enabled", obj, "markdown-enabled")
+ .build();
+
+ self.parent_constructed(obj);
+ }
+ }
+
+ impl WidgetImpl for RoomHistory {}
+ impl BinImpl for RoomHistory {}
+}
+
+glib::wrapper! {
+ pub struct RoomHistory(ObjectSubclass<imp::RoomHistory>)
+ @extends gtk::Widget, adw::Bin, @implements gtk::Accessible;
+}
+
+impl RoomHistory {
+ pub fn new() -> Self {
+ glib::Object::new(&[]).expect("Failed to create RoomHistory")
+ }
+
+ pub fn set_room(&self, room: Option<Room>) {
+ let priv_ = imp::RoomHistory::from_instance(self);
+
+ if self.room() == room {
+ return;
+ }
+
+ // TODO: use gtk::MultiSelection to allow selection
+ let model = room
+ .as_ref()
+ .and_then(|room| Some(gtk::NoSelection::new(Some(room.timeline()))));
+
+ priv_.listview.set_model(model.as_ref());
+ priv_.room.replace(room);
+ self.notify("room");
+ }
+
+ pub fn room(&self) -> Option<Room> {
+ let priv_ = imp::RoomHistory::from_instance(self);
+ priv_.room.borrow().clone()
+ }
+
+ pub fn send_text_message(&self) {
+ let priv_ = imp::RoomHistory::from_instance(self);
+ let buffer = priv_.message_entry.buffer();
+ let (start_iter, end_iter) = buffer.bounds();
+ let body = buffer.text(&start_iter, &end_iter, true);
+
+ if let Some(room) = &*priv_.room.borrow() {
+ room.send_text_message(body.as_str(), priv_.md_enabled.get());
+ }
+
+ buffer.set_text("");
+ }
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]