diff options
-rw-r--r-- | libdino/src/service/chat_interaction.vala | 18 | ||||
-rw-r--r-- | main/data/conversation_row.ui | 28 | ||||
-rw-r--r-- | main/data/theme.css | 8 | ||||
-rw-r--r-- | main/src/ui/conversation_selector/conversation_selector_row.vala | 20 |
4 files changed, 63 insertions, 11 deletions
diff --git a/libdino/src/service/chat_interaction.vala b/libdino/src/service/chat_interaction.vala index c832aeca..d777db90 100644 --- a/libdino/src/service/chat_interaction.vala +++ b/libdino/src/service/chat_interaction.vala @@ -32,11 +32,19 @@ public class ChatInteraction : StreamInteractionModule, Object { stream_interactor.get_module(ContentItemStore.IDENTITY).new_item.connect(new_item); } - public bool has_unread(Conversation conversation) { - ContentItem? last_content_item = stream_interactor.get_module(ContentItemStore.IDENTITY).get_latest(conversation); - if (last_content_item == null) return false; - - return last_content_item.id != conversation.read_up_to_item; + public int get_num_unread(Conversation conversation) { + ContentItem? read_up_to_item = stream_interactor.get_module(ContentItemStore.IDENTITY).get_item_by_id(conversation, conversation.read_up_to_item); + if (read_up_to_item == null) return 0; + + Database db = Dino.Application.get_default().db; + string local_time = read_up_to_item.sort_time.to_unix().to_string(); + string time = read_up_to_item.display_time.to_unix().to_string(); + string id = read_up_to_item.id.to_string(); + return (int)db.content_item.select() + .where(@"local_time > ? OR (local_time = ? AND time > ?) OR (local_time = ? AND time = ? AND id > ?)", { local_time, local_time, time, local_time, time, id }) + .with(db.content_item.conversation_id, "=", conversation.id) + .with(db.content_item.hide, "=", false) + .count(); } public bool is_active_focus(Conversation? conversation = null) { diff --git a/main/data/conversation_row.ui b/main/data/conversation_row.ui index 7772c907..8d257201 100644 --- a/main/data/conversation_row.ui +++ b/main/data/conversation_row.ui @@ -46,7 +46,7 @@ <child> <object class="GtkRevealer" id="time_revealer"> <property name="transition-type">slide-right</property> - <property name="transition-duration">100</property> + <property name="transition-duration">50</property> <property name="reveal-child">True</property> <property name="visible">True</property> <child> @@ -71,6 +71,7 @@ <object class="GtkLabel" id="nick_label"> <property name="max_width_chars">15</property> <property name="ellipsize">end</property> + <property name="valign">end</property> <property name="xalign">0</property> <style> <class name="dim-label"/> @@ -86,12 +87,36 @@ <property name="max_width_chars">1</property> <property name="ellipsize">end</property> <property name="expand">True</property> + <property name="valign">end</property> <property name="xalign">0</property> <attributes> <attribute name="scale" value="0.8"/> </attributes> </object> </child> + <child> + <object class="GtkRevealer" id="unread_count_revealer"> + <property name="transition-type">slide-right</property> + <property name="transition-duration">50</property> + <property name="reveal-child">True</property> + <property name="visible">True</property> + <child> + <object class="GtkLabel" id="unread_count_label"> + <property name="vexpand">False</property> + <property name="visible">False</property> + <property name="margin-start">15</property> + <property name="xalign">0.5</property> + <attributes> + <attribute name="scale" value="0.6"/> + <attribute name="weight" value="PANGO_WEIGHT_BOLD"/> + </attributes> + <style> + <class name="unread-count"/> + </style> + </object> + </child> + </object> + </child> </object> </child> </object> @@ -116,6 +141,7 @@ <object class="GtkButton" id="x_button"> <property name="vexpand">False</property> <property name="visible">True</property> + <property name="margin-start">5</property> <style> <class name="conversation_list_row_xbutton"/> <class name="circular"/> diff --git a/main/data/theme.css b/main/data/theme.css index fb6e2b11..09e282ec 100644 --- a/main/data/theme.css +++ b/main/data/theme.css @@ -42,6 +42,14 @@ window.dino-main .dino-conversation .message-box:hover { background: alpha(@theme_fg_color, 0.04); } +window.dino-main .unread-count { + background-color: alpha(@theme_fg_color, 0.8); + color: @theme_base_color; + font-family: monospace; + border-radius: 999em; + padding: .2em .41em; +} + window.dino-main .dino-sidebar > frame { background: @insensitive_bg_color; border-left: 1px solid @borders; diff --git a/main/src/ui/conversation_selector/conversation_selector_row.vala b/main/src/ui/conversation_selector/conversation_selector_row.vala index a5148a8f..7c25ee8d 100644 --- a/main/src/ui/conversation_selector/conversation_selector_row.vala +++ b/main/src/ui/conversation_selector/conversation_selector_row.vala @@ -17,9 +17,11 @@ public class ConversationSelectorRow : ListBoxRow { [GtkChild] protected Label time_label; [GtkChild] protected Label nick_label; [GtkChild] protected Label message_label; + [GtkChild] protected Label unread_count_label; [GtkChild] protected Button x_button; [GtkChild] protected Revealer time_revealer; [GtkChild] protected Revealer xbutton_revealer; + [GtkChild] protected Revealer unread_count_revealer; [GtkChild] public Revealer main_revealer; public Conversation conversation { get; private set; } @@ -27,7 +29,7 @@ public class ConversationSelectorRow : ListBoxRow { protected const int AVATAR_SIZE = 40; protected ContentItem? last_content_item; - protected bool read = true; + protected int num_unread = 0; protected StreamInteractor stream_interactor; @@ -202,21 +204,27 @@ public class ConversationSelectorRow : ListBoxRow { } protected void update_read() { - bool current_read_status = !stream_interactor.get_module(ChatInteraction.IDENTITY).has_unread(conversation); - if (read == current_read_status) return; - read = current_read_status; + int current_num_unread = stream_interactor.get_module(ChatInteraction.IDENTITY).get_num_unread(conversation); + if (num_unread == current_num_unread) return; + num_unread = current_num_unread; + + if (num_unread == 0) { + unread_count_label.visible = false; - if (read) { name_label.attributes.filter((attr) => attr.equal(attr_weight_new(Weight.BOLD))); time_label.attributes.filter((attr) => attr.equal(attr_weight_new(Weight.BOLD))); nick_label.attributes.filter((attr) => attr.equal(attr_weight_new(Weight.BOLD))); message_label.attributes.filter((attr) => attr.equal(attr_weight_new(Weight.BOLD))); } else { + unread_count_label.label = num_unread.to_string(); + unread_count_label.visible = true; + name_label.attributes.insert(attr_weight_new(Weight.BOLD)); time_label.attributes.insert(attr_weight_new(Weight.BOLD)); nick_label.attributes.insert(attr_weight_new(Weight.BOLD)); message_label.attributes.insert(attr_weight_new(Weight.BOLD)); } + name_label.label = name_label.label; // TODO initializes redrawing, which would otherwise not happen. nicer? time_label.label = time_label.label; nick_label.label = nick_label.label; @@ -227,9 +235,11 @@ public class ConversationSelectorRow : ListBoxRow { StateFlags curr_flags = get_state_flags(); if ((curr_flags & StateFlags.PRELIGHT) != 0) { time_revealer.set_reveal_child(false); + unread_count_revealer.set_reveal_child(false); xbutton_revealer.set_reveal_child(true); } else { time_revealer.set_reveal_child(true); + unread_count_revealer.set_reveal_child(true); xbutton_revealer.set_reveal_child(false); } } |