From 8aab18c1ec37fd427e2dcaa2ee37be8467d15d16 Mon Sep 17 00:00:00 2001 From: fiaxh Date: Sat, 1 Jun 2019 16:00:21 +0200 Subject: Add hover effect on conversation content --- main/data/conversation_summary/view.ui | 3 +- main/data/theme.css | 4 + main/src/ui/avatar_image.vala | 4 +- .../conversation_selector.vala | 2 - .../content_item_widget_factory.vala | 1 + .../conversation_item_skeleton.vala | 79 ++++++++++----- .../ui/conversation_summary/conversation_view.vala | 111 ++++++--------------- 7 files changed, 95 insertions(+), 109 deletions(-) diff --git a/main/data/conversation_summary/view.ui b/main/data/conversation_summary/view.ui index 90d3d7c1..51133890 100644 --- a/main/data/conversation_summary/view.ui +++ b/main/data/conversation_summary/view.ui @@ -19,14 +19,13 @@ True - 15 vertical True + 15 False vertical - 15 True diff --git a/main/data/theme.css b/main/data/theme.css index 1969c80b..8a1b50ad 100644 --- a/main/data/theme.css +++ b/main/data/theme.css @@ -37,6 +37,10 @@ window.dino-main .dino-conversation .highlight-once { animation-name: highlight; } +window.dino-main .dino-conversation .message-box:hover { + background: alpha(@theme_fg_color, 0.04); +} + window.dino-main .dino-sidebar > frame { background: @insensitive_bg_color; border-left: 1px solid @borders; diff --git a/main/src/ui/avatar_image.vala b/main/src/ui/avatar_image.vala index c052270a..846bf0ff 100644 --- a/main/src/ui/avatar_image.vala +++ b/main/src/ui/avatar_image.vala @@ -5,8 +5,8 @@ using Xmpp; namespace Dino.Ui { public class AvatarImage : Misc { - public int height { get; set; default = 32; } - public int width { get; set; default = 32; } + public int height { get; set; default = 35; } + public int width { get; set; default = 35; } public bool allow_gray { get; set; default = true; } public Account account { get; private set; } public StreamInteractor stream_interactor { get; set; } diff --git a/main/src/ui/conversation_selector/conversation_selector.vala b/main/src/ui/conversation_selector/conversation_selector.vala index dd264206..290e297f 100644 --- a/main/src/ui/conversation_selector/conversation_selector.vala +++ b/main/src/ui/conversation_selector/conversation_selector.vala @@ -33,8 +33,6 @@ public class ConversationSelector : ListBox { } construct { - this.stream_interactor = stream_interactor; - get_style_context().add_class("sidebar"); set_filter_func(filter); set_header_func(header); diff --git a/main/src/ui/conversation_summary/content_item_widget_factory.vala b/main/src/ui/conversation_summary/content_item_widget_factory.vala index b784c91a..2415eb38 100644 --- a/main/src/ui/conversation_summary/content_item_widget_factory.vala +++ b/main/src/ui/conversation_summary/content_item_widget_factory.vala @@ -178,6 +178,7 @@ public class FileItemWidgetGenerator : WidgetGenerator, Object { grid.attach(image, 0, 0, 1, 1); EventBox event_box = new EventBox() { halign=Align.START, visible=true }; + event_box.events = EventMask.POINTER_MOTION_MASK; event_box.add(grid); event_box.enter_notify_event.connect(() => { toolbar_revealer.reveal_child = true; return false; }); event_box.leave_notify_event.connect(() => { toolbar_revealer.reveal_child = false; return false; }); diff --git a/main/src/ui/conversation_summary/conversation_item_skeleton.vala b/main/src/ui/conversation_summary/conversation_item_skeleton.vala index a4e45f7a..808bcf7a 100644 --- a/main/src/ui/conversation_summary/conversation_item_skeleton.vala +++ b/main/src/ui/conversation_summary/conversation_item_skeleton.vala @@ -7,22 +7,25 @@ using Dino.Entities; namespace Dino.Ui.ConversationSummary { -public class ConversationItemSkeleton : Box { +public class ConversationItemSkeleton : EventBox { private AvatarImage image = new AvatarImage() { margin_top=2, valign=Align.START, visible=true, allow_gray = false }; + public bool show_skeleton { get; set; } + public bool last_group_item { get; set; } + public StreamInteractor stream_interactor; public Conversation conversation { get; set; } - public ArrayList items = new ArrayList(); + public Plugins.MetaConversationItem item; - private Grid grid = new Grid() { visible=true }; - private HashMap item_widgets = new HashMap(); + private Box image_content_box = new Box(Orientation.HORIZONTAL, 8) { visible=true }; + private Box header_content_box = new Box(Orientation.VERTICAL, 0) { visible=true }; private DefaultSkeletonHeader default_header; public ConversationItemSkeleton(StreamInteractor stream_interactor, Conversation conversation, Plugins.MetaConversationItem item) { this.conversation = conversation; this.stream_interactor = stream_interactor; - Box image_content_box = new Box(Orientation.HORIZONTAL, 8) { visible=true }; + this.get_style_context().add_class("message-box"); if (item.requires_avatar) { image.set_jid(stream_interactor, item.jid, conversation.account); @@ -34,30 +37,44 @@ public class ConversationItemSkeleton : Box { default_header.name_label.visible = false; default_header.dot_label.visible = false; } - grid.attach(default_header, 0, 0, 1, 1); + header_content_box.add(default_header); } - add_meta_item(item); - image_content_box.add(grid); - this.add(image_content_box); - } - - public void add_meta_item(Plugins.MetaConversationItem item) { - items.add(item); + // add item + this.item = item; if (default_header != null) { default_header.add_item(item); } Widget? widget = item.get_widget(Plugins.WidgetType.GTK) as Widget; + widget.valign = Align.END; if (widget != null) { - grid.attach(widget, 0, items.size, 1, 1); - item_widgets[item] = widget; + header_content_box.add(widget); } - } - public void remove_meta_item(Plugins.MetaConversationItem item) { - item_widgets[item].destroy(); - item_widgets.unset(item); - items.remove(item); + image_content_box.add(header_content_box); + this.add(image_content_box); + + if (item.get_type().is_a(typeof(ContentMetaItem))) { + this.motion_notify_event.connect((event) => { + this.set_state_flags(StateFlags.PRELIGHT, false); + return false; + }); + this.enter_notify_event.connect((event) => { + this.set_state_flags(StateFlags.PRELIGHT, false); + return false; + }); + this.leave_notify_event.connect((event) => { + this.unset_state_flags(StateFlags.PRELIGHT); + return false; + }); + } + + this.notify["show-skeleton"].connect(update_margin); + this.notify["last-group-item"].connect(update_margin); + + this.show_skeleton = true; + this.last_group_item = true; + update_margin(); } public void update_time() { @@ -65,13 +82,29 @@ public class ConversationItemSkeleton : Box { default_header.update_time(); } } + + public void update_margin() { + image.visible = this.show_skeleton; + if (default_header != null) { + default_header.visible = this.show_skeleton; + } + image_content_box.margin_start = this.show_skeleton ? 15 : 58; + + if (this.show_skeleton && this.last_group_item) { + image_content_box.margin_top = 8; + image_content_box.margin_bottom = 8; + } else { + image_content_box.margin_top = 4; + image_content_box.margin_bottom = 4; + } + } } public class DefaultSkeletonHeader : Box { private Box box = new Box(Orientation.HORIZONTAL, 4) { visible=true }; - public Label name_label = new Label("") { use_markup=true, xalign=0, visible=true }; - public Label time_label = new Label("") { use_markup=true, xalign=0, visible=true }; - public Label dot_label = new Label("·") { use_markup=true, xalign=0, visible=true }; + public Label name_label = new Label("") { use_markup=true, valign=Align.START, xalign=0, visible=true }; + public Label time_label = new Label("") { use_markup=true, valign=Align.START, xalign=0, visible=true }; + public Label dot_label = new Label("·") { use_markup=true, valign=Align.START, xalign=0, visible=true }; public Image encryption_image = new Image(); public Image received_image = new Image(); diff --git a/main/src/ui/conversation_summary/conversation_view.vala b/main/src/ui/conversation_summary/conversation_view.vala index 3592a6c1..d73d012b 100644 --- a/main/src/ui/conversation_summary/conversation_view.vala +++ b/main/src/ui/conversation_summary/conversation_view.vala @@ -98,26 +98,19 @@ public class ConversationView : Box, Plugins.ConversationItemCollection, Plugins if (after_items.size == 40) { at_current_content = false; } - { - int h = 0, i = 0; - main.@foreach((widget) => { - if (i >= before_items.size) return; - ConversationItemSkeleton? sk = widget as ConversationItemSkeleton; - i += sk != null ? sk.items.size : 1; - int minimum_height, natural_height; - widget.get_preferred_height_for_width(main.get_allocated_width() - 2 * main.margin, out minimum_height, out natural_height); - h += minimum_height + 15; - }); - } + // Compute where to jump to for centered message, jump, highlight. reload_messages = false; Timeout.add(700, () => { int h = 0, i = 0; + bool @break = false; main.@foreach((widget) => { - if (i >= before_items.size) return; - ConversationItemSkeleton? sk = widget as ConversationItemSkeleton; - i += sk != null ? sk.items.size : 1; - h += widget.get_allocated_height() + 15; + if (widget == w || @break) { + @break = true; + return; + } + h += widget.get_allocated_height(); + i++; }); scrolled.vadjustment.value = h - scrolled.vadjustment.page_size * 1/3; w.get_style_context().add_class("highlight-once"); @@ -183,14 +176,12 @@ public class ConversationView : Box, Plugins.ConversationItemCollection, Plugins public void do_insert_item(Plugins.MetaConversationItem item) { lock (meta_items) { - if (!item.can_merge || !merge_back(item)) { - insert_new(item); + insert_new(item); + if (item as ContentMetaItem != null) { + content_items.add(item); } + meta_items.add(item); } - if (item as ContentMetaItem != null) { - content_items.add(item); - } - meta_items.add(item); inserted_item(item); } @@ -198,15 +189,12 @@ public class ConversationView : Box, Plugins.ConversationItemCollection, Plugins private void remove_item(Plugins.MetaConversationItem item) { ConversationItemSkeleton? skeleton = item_item_skeletons[item]; if (skeleton != null) { - if (skeleton.items.size > 1) { - skeleton.remove_meta_item(item); - } else { - widgets[item].destroy(); - widgets.unset(item); - skeleton.destroy(); - item_skeletons.remove(skeleton); - item_item_skeletons.unset(item); - } + widgets[item].destroy(); + widgets.unset(item); + skeleton.destroy(); + item_skeletons.remove(skeleton); + item_item_skeletons.unset(item); + content_items.remove(item); meta_items.remove(item); } @@ -242,41 +230,9 @@ public class ConversationView : Box, Plugins.ConversationItemCollection, Plugins widget.destroy(); } - private bool merge_back(Plugins.MetaConversationItem item) { - Plugins.MetaConversationItem? lower_item = meta_items.lower(item); - if (lower_item != null) { - ConversationItemSkeleton lower_skeleton = item_item_skeletons[lower_item]; - Plugins.MetaConversationItem lower_start_item = lower_skeleton.items[0]; - if (lower_start_item.can_merge && - item.display_time.difference(lower_start_item.display_time) < TimeSpan.MINUTE && - lower_start_item.jid.equals(item.jid) && - lower_start_item.encryption == item.encryption && - (item.mark == Message.Marked.WONTSEND) == (lower_start_item.mark == Message.Marked.WONTSEND)) { - lower_skeleton.add_meta_item(item); - - widgets[item] = widgets[lower_start_item]; - item_item_skeletons[item] = lower_skeleton; - - return true; - } - } - return false; - } - private Widget insert_new(Plugins.MetaConversationItem item) { Plugins.MetaConversationItem? lower_item = meta_items.lower(item); - // Does another skeleton need to be split? - if (lower_item != null) { - ConversationItemSkeleton lower_skeleton = item_item_skeletons[lower_item]; - if (lower_skeleton.items.size > 1) { - Plugins.MetaConversationItem lower_end_item = lower_skeleton.items[lower_skeleton.items.size - 1]; - if (item.sort_time.compare(lower_end_item.sort_time) < 0) { - split_at_time(lower_skeleton, item.sort_time); - } - } - } - // Fill datastructure ConversationItemSkeleton item_skeleton = new ConversationItemSkeleton(stream_interactor, conversation, item) { visible=true }; item_item_skeletons[item] = item_skeleton; @@ -297,6 +253,19 @@ public class ConversationView : Box, Plugins.ConversationItemCollection, Plugins widgets[item] = insert; main.reorder_child(insert, index); + if (lower_item != null) { + ConversationItemSkeleton lower_skeleton = item_item_skeletons[lower_item]; + Plugins.MetaConversationItem lower_start_item = lower_skeleton.item; + if (item.display_time != null && lower_start_item.display_time != null && + item.display_time.difference(lower_start_item.display_time) < TimeSpan.MINUTE && + lower_start_item.jid.equals(item.jid) && + lower_start_item.encryption == item.encryption && + (item.mark == Message.Marked.WONTSEND) == (lower_start_item.mark == Message.Marked.WONTSEND)) { + item_skeleton.show_skeleton = false; + lower_skeleton.last_group_item = false; + } + } + // If an item from the past was added, add everything between that item and the (post-)first present item if (index == 0) { Dino.Application app = Dino.Application.get_default(); @@ -313,24 +282,6 @@ public class ConversationView : Box, Plugins.ConversationItemCollection, Plugins return insert; } - private void split_at_time(ConversationItemSkeleton split_skeleton, DateTime time) { - bool already_divided = false; - int i = 0; - while(i < split_skeleton.items.size) { - Plugins.MetaConversationItem meta_item = split_skeleton.items[i]; - if (time.compare(meta_item.display_time) < 0) { - remove_item(meta_item); - if (!already_divided) { - insert_new(meta_item); - already_divided = true; - } else { - do_insert_item(meta_item); - } - } - i++; - } - } - private void on_upper_notify() { if (was_upper == null || scrolled.vadjustment.value > was_upper - was_page_size - 1) { // scrolled down or content smaller than page size if (at_current_content) { -- cgit v1.2.3-70-g09d2