aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfiaxh <git@lightrise.org>2024-03-02 13:18:53 +0100
committerfiaxh <git@lightrise.org>2024-03-02 13:18:53 +0100
commit4cc7e076e65c604e7a2f840ddc394ea70700577d (patch)
tree8daceda12abce2f6a92eb84b2d2e1b23f7360732
parent7e3cedaf3fa347bfa688e71b0f69e62725db395d (diff)
downloaddino-4cc7e076e65c604e7a2f840ddc394ea70700577d.tar.gz
dino-4cc7e076e65c604e7a2f840ddc394ea70700577d.zip
Add unread indicator
Co-authored-by: Alexandre Jousset <mid@gtmp.org> Co-authored-by: Aidan Epstein <aidan@jmad.org>
-rw-r--r--main/CMakeLists.txt1
-rw-r--r--main/data/style.css7
-rw-r--r--main/meson.build1
-rw-r--r--main/src/ui/conversation_content_view/conversation_view.vala3
-rw-r--r--main/src/ui/conversation_content_view/unread_indicator_populator.vala88
5 files changed, 100 insertions, 0 deletions
diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt
index 9a7cb189..ea4de99b 100644
--- a/main/CMakeLists.txt
+++ b/main/CMakeLists.txt
@@ -192,6 +192,7 @@ SOURCES
src/ui/conversation_content_view/quote_widget.vala
src/ui/conversation_content_view/reactions_widget.vala
src/ui/conversation_content_view/subscription_notification.vala
+ src/ui/conversation_content_view/unread_indicator_populator.vala
src/ui/chat_input/chat_input_controller.vala
src/ui/chat_input/chat_text_view.vala
diff --git a/main/data/style.css b/main/data/style.css
index 5fe3beae..a7a1d8df 100644
--- a/main/data/style.css
+++ b/main/data/style.css
@@ -282,6 +282,13 @@ window.dino-main .dino-chatinput-button button:checked:backdrop {
color: alpha(@theme_unfocused_selected_bg_color, 0.8);
}
+.dino-unread-line label {
+ color: @theme_selected_bg_color;
+}
+
+.dino-unread-line separator {
+ background-color: @theme_selected_bg_color;
+}
.dino-chatinput,
.dino-chatinput textview,
diff --git a/main/meson.build b/main/meson.build
index fab6ba45..1b5abcfc 100644
--- a/main/meson.build
+++ b/main/meson.build
@@ -53,6 +53,7 @@ sources = files(
'src/ui/conversation_content_view/quote_widget.vala',
'src/ui/conversation_content_view/reactions_widget.vala',
'src/ui/conversation_content_view/subscription_notification.vala',
+ 'src/ui/conversation_content_view/unread_indicator_populator.vala',
'src/ui/conversation_details.vala',
'src/ui/conversation_list_titlebar.vala',
'src/ui/conversation_selector/conversation_selector.vala',
diff --git a/main/src/ui/conversation_content_view/conversation_view.vala b/main/src/ui/conversation_content_view/conversation_view.vala
index 33cb3b22..519aa01f 100644
--- a/main/src/ui/conversation_content_view/conversation_view.vala
+++ b/main/src/ui/conversation_content_view/conversation_view.vala
@@ -87,6 +87,7 @@ public class ConversationView : Widget, Plugins.ConversationItemCollection, Plug
Application app = GLib.Application.get_default() as Application;
app.plugin_registry.register_conversation_addition_populator(new ChatStatePopulator(stream_interactor));
app.plugin_registry.register_conversation_addition_populator(new DateSeparatorPopulator(stream_interactor));
+ app.plugin_registry.register_conversation_addition_populator(new UnreadIndicatorPopulator(stream_interactor));
// Rather than connecting to the leave event of the main_event_box directly,
// we connect to the parent event box that also wraps the overlaying message_menu_box.
@@ -382,6 +383,7 @@ public class ConversationView : Widget, Plugins.ConversationItemCollection, Plug
foreach (ContentMetaItem item in items) {
do_insert_item(item);
}
+
Application app = GLib.Application.get_default() as Application;
foreach (Plugins.NotificationPopulator populator in app.plugin_registry.notification_populators) {
populator.init(conversation, this, Plugins.WidgetType.GTK4);
@@ -398,6 +400,7 @@ public class ConversationView : Widget, Plugins.ConversationItemCollection, Plug
return;
}
}
+
do_insert_item(item);
}
diff --git a/main/src/ui/conversation_content_view/unread_indicator_populator.vala b/main/src/ui/conversation_content_view/unread_indicator_populator.vala
new file mode 100644
index 00000000..79aa7576
--- /dev/null
+++ b/main/src/ui/conversation_content_view/unread_indicator_populator.vala
@@ -0,0 +1,88 @@
+using Gee;
+using Gtk;
+
+using Dino.Entities;
+using Xmpp;
+
+namespace Dino.Ui.ConversationSummary {
+
+ class UnreadIndicatorPopulator : Plugins.ConversationItemPopulator, Plugins.ConversationAdditionPopulator, Object {
+
+ public string id { get { return "unread_indicator"; } }
+
+ private StreamInteractor stream_interactor;
+ private Conversation? current_conversation;
+ private UnreadIndicatorItem? unread_indicator = null;
+ Plugins.ConversationItemCollection item_collection = null;
+
+ public UnreadIndicatorPopulator(StreamInteractor stream_interactor) {
+ this.stream_interactor = stream_interactor;
+
+ stream_interactor.get_module(ChatInteraction.IDENTITY).focused_out.connect(() => {
+ update_unread_indicator();
+ });
+
+ stream_interactor.get_module(ContentItemStore.IDENTITY).new_item.connect(() => {
+ if (!stream_interactor.get_module(ChatInteraction.IDENTITY).is_active_focus(current_conversation)) {
+ update_unread_indicator();
+ }
+ });
+ }
+
+ private void update_unread_indicator() {
+ if (current_conversation == null) return;
+
+ ContentItem? read_up_to_item = stream_interactor.get_module(ContentItemStore.IDENTITY).get_item_by_id(current_conversation, current_conversation.read_up_to_item);
+ int current_num_unread = stream_interactor.get_module(ChatInteraction.IDENTITY).get_num_unread(current_conversation);
+ if (current_num_unread == 0 && unread_indicator != null) {
+ item_collection.remove_item(unread_indicator);
+ unread_indicator = null;
+ }
+
+ if (read_up_to_item != null && current_num_unread > 0) {
+ if (unread_indicator != null) {
+ item_collection.remove_item(unread_indicator);
+ }
+
+ unread_indicator = new UnreadIndicatorItem(read_up_to_item);
+ item_collection.insert_item(unread_indicator);
+ }
+ }
+
+ public void init(Conversation conversation, Plugins.ConversationItemCollection item_collection, Plugins.WidgetType type) {
+ current_conversation = conversation;
+ this.item_collection = item_collection;
+ update_unread_indicator();
+ }
+
+ public void close(Conversation conversation) { }
+
+ public void populate_timespan(Conversation conversation, DateTime after, DateTime before) { }
+ }
+
+ private class UnreadIndicatorItem : Plugins.MetaConversationItem {
+ public UnreadIndicatorItem(ContentItem after_item) {
+ this.time = after_item.time;
+ this.secondary_sort_indicator = int.MAX;
+ }
+
+ public override Object? get_widget(Plugins.ConversationItemWidgetInterface outer, Plugins.WidgetType type) {
+ Box box = new Box(Orientation.HORIZONTAL, 10) { hexpand=true };
+ box.get_style_context().add_class("dino-unread-line");
+
+ Separator sep = new Separator(Orientation.HORIZONTAL) { valign=Align.CENTER, hexpand=true };
+ box.append(sep);
+
+ Label label = new Label(_("New")) { halign=Align.END, hexpand=false };
+ label.attributes = new Pango.AttrList();
+ label.attributes.insert(Pango.attr_weight_new(Pango.Weight.BOLD));
+ box.append(label);
+
+ return box;
+ }
+
+ public override Gee.List<Plugins.MessageAction>? get_item_actions(Plugins.WidgetType type) {
+ return null;
+ }
+ }
+}