diff options
author | fiaxh <git@lightrise.org> | 2020-04-03 22:49:59 +0200 |
---|---|---|
committer | fiaxh <git@lightrise.org> | 2020-04-03 22:49:59 +0200 |
commit | 871ff33ac79f3d17b0260b8bfcd27780038edd6d (patch) | |
tree | f8079e29db5d0f9294fbfbfb47b93b0403249cc9 /main/src/ui/conversation_content_view | |
parent | 1c8e15c408f57d93461e6adb33c4c4415ac49267 (diff) | |
download | dino-871ff33ac79f3d17b0260b8bfcd27780038edd6d.tar.gz dino-871ff33ac79f3d17b0260b8bfcd27780038edd6d.zip |
Add support for last message correction
Diffstat (limited to 'main/src/ui/conversation_content_view')
9 files changed, 308 insertions, 169 deletions
diff --git a/main/src/ui/conversation_content_view/chat_state_populator.vala b/main/src/ui/conversation_content_view/chat_state_populator.vala index 0438e014..545d2c6d 100644 --- a/main/src/ui/conversation_content_view/chat_state_populator.vala +++ b/main/src/ui/conversation_content_view/chat_state_populator.vala @@ -64,10 +64,6 @@ class ChatStatePopulator : Plugins.ConversationItemPopulator, Plugins.Conversati private class MetaChatStateItem : Plugins.MetaConversationItem { public override DateTime sort_time { get; set; default=new DateTime.now_utc().add_years(10); } - public override bool can_merge { get; set; default=false; } - public override bool requires_avatar { get; set; default=false; } - public override bool requires_header { get; set; default=false; } - private StreamInteractor stream_interactor; private Conversation conversation; private Gee.List<Jid> jids = new ArrayList<Jid>(); @@ -93,6 +89,8 @@ private class MetaChatStateItem : Plugins.MetaConversationItem { return image_content_box; } + public override Gee.List<Plugins.MessageAction>? get_item_actions(Plugins.WidgetType type) { return null; } + public void set_new(Gee.List<Jid> jids) { this.jids = jids; update(); diff --git a/main/src/ui/conversation_content_view/content_item_widget_factory.vala b/main/src/ui/conversation_content_view/content_item_widget_factory.vala deleted file mode 100644 index da092e34..00000000 --- a/main/src/ui/conversation_content_view/content_item_widget_factory.vala +++ /dev/null @@ -1,114 +0,0 @@ -using Gee; -using Gdk; -using Gtk; -using Pango; -using Xmpp; - -using Dino.Entities; - -namespace Dino.Ui.ConversationSummary { - -public class ContentItemWidgetFactory : Object { - - private StreamInteractor stream_interactor; - private HashMap<string, WidgetGenerator> generators = new HashMap<string, WidgetGenerator>(); - - public ContentItemWidgetFactory(StreamInteractor stream_interactor) { - this.stream_interactor = stream_interactor; - - generators[MessageItem.TYPE] = new MessageItemWidgetGenerator(stream_interactor); - generators[FileItem.TYPE] = new FileItemWidgetGenerator(stream_interactor); - } - - public Widget? get_widget(ContentItem item) { - WidgetGenerator? generator = generators[item.type_]; - if (generator != null) { - return (Widget?) generator.get_widget(item); - } - return null; - } - - public void register_widget_generator(WidgetGenerator generator) { - generators[generator.handles_type] = generator; - } -} - -public interface WidgetGenerator : Object { - public abstract string handles_type { get; set; } - public abstract Object get_widget(ContentItem item); -} - -public class MessageItemWidgetGenerator : WidgetGenerator, Object { - - public string handles_type { get; set; default=MessageItem.TYPE; } - - private StreamInteractor stream_interactor; - - public MessageItemWidgetGenerator(StreamInteractor stream_interactor) { - this.stream_interactor = stream_interactor; - } - - public Object get_widget(ContentItem item) { - MessageItem message_item = item as MessageItem; - Conversation conversation = message_item.conversation; - Message message = message_item.message; - - Label label = new Label("") { use_markup=true, xalign=0, selectable=true, wrap=true, wrap_mode=Pango.WrapMode.WORD_CHAR, vexpand=true, visible=true }; - string markup_text = message.body; - if (markup_text.length > 10000) { - markup_text = markup_text.substring(0, 10000) + " [" + _("Message too long") + "]"; - } - if (message_item.message.body.has_prefix("/me")) { - markup_text = markup_text.substring(3); - } - - if (conversation.type_ == Conversation.Type.GROUPCHAT) { - markup_text = Util.parse_add_markup(markup_text, conversation.nickname, true, true); - } else { - markup_text = Util.parse_add_markup(markup_text, null, true, true); - } - - if (message_item.message.body.has_prefix("/me")) { - string display_name = Util.get_participant_display_name(stream_interactor, conversation, message.from); - update_me_style(stream_interactor, message.real_jid ?? message.from, display_name, conversation.account, label, markup_text); - label.realize.connect(() => update_me_style(stream_interactor, message.real_jid ?? message.from, display_name, conversation.account, label, markup_text)); - label.style_updated.connect(() => update_me_style(stream_interactor, message.real_jid ?? message.from, display_name, conversation.account, label, markup_text)); - } - - int only_emoji_count = Util.get_only_emoji_count(markup_text); - if (only_emoji_count != -1) { - string size_str = only_emoji_count < 5 ? "xx-large" : "large"; - markup_text = @"<span size=\'$size_str\'>" + markup_text + "</span>"; - } - - label.label = markup_text; - return label; - } - - public static void update_me_style(StreamInteractor stream_interactor, Jid jid, string display_name, Account account, Label label, string action_text) { - string color = Util.get_name_hex_color(stream_interactor, account, jid, Util.is_dark_theme(label)); - label.label = @"<span color=\"#$(color)\">$(Markup.escape_text(display_name))</span>" + action_text; - } -} - -public class FileItemWidgetGenerator : WidgetGenerator, Object { - - public StreamInteractor stream_interactor; - public string handles_type { get; set; default=FileItem.TYPE; } - - private const int MAX_HEIGHT = 300; - private const int MAX_WIDTH = 600; - - public FileItemWidgetGenerator(StreamInteractor stream_interactor) { - this.stream_interactor = stream_interactor; - } - - public Object get_widget(ContentItem item) { - FileItem file_item = item as FileItem; - FileTransfer transfer = file_item.file_transfer; - - return new FileWidget(stream_interactor, transfer) { visible=true }; - } -} - -} diff --git a/main/src/ui/conversation_content_view/content_populator.vala b/main/src/ui/conversation_content_view/content_populator.vala index e8eee06c..2a0f8ac1 100644 --- a/main/src/ui/conversation_content_view/content_populator.vala +++ b/main/src/ui/conversation_content_view/content_populator.vala @@ -9,13 +9,11 @@ namespace Dino.Ui.ConversationSummary { public class ContentProvider : ContentItemCollection, Object { private StreamInteractor stream_interactor; - private ContentItemWidgetFactory widget_factory; private Conversation? current_conversation; private Plugins.ConversationItemCollection? item_collection; public ContentProvider(StreamInteractor stream_interactor) { this.stream_interactor = stream_interactor; - this.widget_factory = new ContentItemWidgetFactory(stream_interactor); } public void init(Plugins.ConversationItemCollection item_collection, Conversation conversation, Plugins.WidgetType type) { @@ -28,7 +26,7 @@ public class ContentProvider : ContentItemCollection, Object { } public void insert_item(ContentItem item) { - item_collection.insert_item(new ContentMetaItem(item, widget_factory)); + item_collection.insert_item(create_content_meta_item(item)); } public void remove_item(ContentItem item) { } @@ -38,7 +36,7 @@ public class ContentProvider : ContentItemCollection, Object { Gee.List<ContentItem> items = stream_interactor.get_module(ContentItemStore.IDENTITY).get_n_latest(conversation, n); Gee.List<ContentMetaItem> ret = new ArrayList<ContentMetaItem>(); foreach (ContentItem item in items) { - ret.add(new ContentMetaItem(item, widget_factory)); + ret.add(create_content_meta_item(item)); } return ret; } @@ -47,7 +45,7 @@ public class ContentProvider : ContentItemCollection, Object { Gee.List<ContentMetaItem> ret = new ArrayList<ContentMetaItem>(); Gee.List<ContentItem> items = stream_interactor.get_module(ContentItemStore.IDENTITY).get_before(conversation, before_item, n); foreach (ContentItem item in items) { - ret.add(new ContentMetaItem(item, widget_factory)); + ret.add(create_content_meta_item(item)); } return ret; } @@ -56,26 +54,30 @@ public class ContentProvider : ContentItemCollection, Object { Gee.List<ContentMetaItem> ret = new ArrayList<ContentMetaItem>(); Gee.List<ContentItem> items = stream_interactor.get_module(ContentItemStore.IDENTITY).get_after(conversation, after_item, n); foreach (ContentItem item in items) { - ret.add(new ContentMetaItem(item, widget_factory)); + ret.add(create_content_meta_item(item)); } return ret; } public ContentMetaItem get_content_meta_item(ContentItem content_item) { - return new ContentMetaItem(content_item, widget_factory); + return create_content_meta_item(content_item); + } + + private ContentMetaItem create_content_meta_item(ContentItem content_item) { + if (content_item.type_ == MessageItem.TYPE) { + return new MessageMetaItem(content_item, stream_interactor); + } else if (content_item.type_ == FileItem.TYPE) { + return new FileMetaItem(content_item, stream_interactor); + } + return null; } } -public class ContentMetaItem : Plugins.MetaConversationItem { - public override Jid? jid { get; set; } - public override DateTime sort_time { get; set; } - public override DateTime? display_time { get; set; } - public override Encryption encryption { get; set; } +public abstract class ContentMetaItem : Plugins.MetaConversationItem { public ContentItem content_item; - private ContentItemWidgetFactory widget_factory; - public ContentMetaItem(ContentItem content_item, ContentItemWidgetFactory widget_factory) { + protected ContentMetaItem(ContentItem content_item) { this.jid = content_item.jid; this.sort_time = content_item.sort_time; this.seccondary_sort_indicator = (long) content_item.display_time.to_unix(); @@ -96,15 +98,6 @@ public class ContentMetaItem : Plugins.MetaConversationItem { this.requires_header = true; this.content_item = content_item; - this.widget_factory = widget_factory; - } - - public override bool can_merge { get; set; default=true; } - public override bool requires_avatar { get; set; default=true; } - public override bool requires_header { get; set; default=true; } - - public override Object? get_widget(Plugins.WidgetType type) { - return widget_factory.get_widget(content_item); } } diff --git a/main/src/ui/conversation_content_view/conversation_item_skeleton.vala b/main/src/ui/conversation_content_view/conversation_item_skeleton.vala index 8c59dde7..fe6c2dee 100644 --- a/main/src/ui/conversation_content_view/conversation_item_skeleton.vala +++ b/main/src/ui/conversation_content_view/conversation_item_skeleton.vala @@ -15,6 +15,8 @@ public class ConversationItemSkeleton : EventBox { public StreamInteractor stream_interactor; public Conversation conversation { get; set; } public Plugins.MetaConversationItem item; + public ContentMetaItem? content_meta_item = null; + public Widget? widget = null; private Box image_content_box = new Box(Orientation.HORIZONTAL, 8) { visible=true }; private Box header_content_box = new Box(Orientation.VERTICAL, 0) { visible=true }; @@ -25,9 +27,18 @@ public class ConversationItemSkeleton : EventBox { this.stream_interactor = stream_interactor; this.conversation = conversation; this.item = item; + this.content_meta_item = item as ContentMetaItem; this.get_style_context().add_class("message-box"); - Widget? widget = item.get_widget(Plugins.WidgetType.GTK) as Widget; + item.notify["in-edit-mode"].connect(() => { + if (item.in_edit_mode) { + this.get_style_context().add_class("edit-mode"); + } else { + this.get_style_context().remove_class("edit-mode"); + } + }); + + widget = item.get_widget(Plugins.WidgetType.GTK) as Widget; if (widget != null) { widget.valign = Align.END; header_content_box.add(widget); @@ -51,7 +62,12 @@ public class ConversationItemSkeleton : EventBox { update_margin(); } - public void update_margin() { + public void set_edit_mode() { + if (content_meta_item == null) return; + + } + + private void update_margin() { if (item.requires_header && show_skeleton && metadata_header == null) { metadata_header = new ItemMetaDataHeader(stream_interactor, conversation, item) { visible=true }; header_content_box.add(metadata_header); diff --git a/main/src/ui/conversation_content_view/conversation_view.vala b/main/src/ui/conversation_content_view/conversation_view.vala index ac6df1fc..808c6cad 100644 --- a/main/src/ui/conversation_content_view/conversation_view.vala +++ b/main/src/ui/conversation_content_view/conversation_view.vala @@ -15,6 +15,8 @@ public class ConversationView : Box, Plugins.ConversationItemCollection, Plugins [GtkChild] public ScrolledWindow scrolled; [GtkChild] private Revealer notification_revealer; [GtkChild] private Box message_menu_box; + [GtkChild] private Button button1; + [GtkChild] private Image button1_icon; [GtkChild] private Box notifications; [GtkChild] private Box main; [GtkChild] private EventBox main_event_box; @@ -29,7 +31,6 @@ public class ConversationView : Box, Plugins.ConversationItemCollection, Plugins private Gee.List<ConversationItemSkeleton> item_skeletons = new Gee.ArrayList<ConversationItemSkeleton>(); private ContentProvider content_populator; private SubscriptionNotitication subscription_notification; - private bool enable_menu_box = false; private double? was_value; private double? was_upper; @@ -40,8 +41,8 @@ public class ConversationView : Box, Plugins.ConversationItemCollection, Plugins private bool firstLoad = true; private bool at_current_content = true; private bool reload_messages = true; - Widget currently_highlighted = null; - ContentItem current_highlighted_item = null; + ConversationItemSkeleton currently_highlighted = null; + ContentMetaItem? current_meta_item = null; bool mouse_inside = false; int last_y_root = -1; @@ -67,6 +68,11 @@ public class ConversationView : Box, Plugins.ConversationItemCollection, Plugins main_event_box.events = EventMask.POINTER_MOTION_MASK; main_event_box.motion_notify_event.connect(on_motion_notify_event); + button1.clicked.connect(() => { + current_meta_item.get_item_actions(Plugins.WidgetType.GTK)[0].callback(button1, current_meta_item, currently_highlighted.widget); + update_message_menu(); + }); + return this; } @@ -95,7 +101,6 @@ public class ConversationView : Box, Plugins.ConversationItemCollection, Plugins } last_y_root = y_root; - message_menu_box.visible = enable_menu_box; // Get pointer location in main int geometry_x, geometry_y, geometry_width, geometry_height, dest_x, dest_y; @@ -106,21 +111,24 @@ public class ConversationView : Box, Plugins.ConversationItemCollection, Plugins // Get widget under pointer int h = 0; bool @break = false; - Widget? w = null; + ConversationItemSkeleton? w = null; main.@foreach((widget) => { if (break) return; h += widget.get_allocated_height(); - w = widget; + w = widget as ConversationItemSkeleton; if (h >= dest_y) { @break = true; return; } }); + if (currently_highlighted != null) currently_highlighted.unset_state_flags(StateFlags.PRELIGHT); + if (w == null) { - if (currently_highlighted != null) currently_highlighted.unset_state_flags(StateFlags.PRELIGHT); currently_highlighted = null; + current_meta_item = null; + update_message_menu(); return; } @@ -129,23 +137,36 @@ public class ConversationView : Box, Plugins.ConversationItemCollection, Plugins w.translate_coordinates(main, 0, 0, out widget_x, out widget_y); // Get MessageItem - var iter = widgets.map_iterator(); - while (iter.next()) { - if (iter.get_value() == w) { - Plugins.MetaConversationItem meta_item = iter.get_key(); - var meta_content_item = meta_item as ContentMetaItem; - if (meta_content_item == null) return; - current_highlighted_item = meta_content_item.content_item; + foreach (Plugins.MetaConversationItem item in item_item_skeletons.keys) { + if (item_item_skeletons[item] == w) { + current_meta_item = item as ContentMetaItem; } } - // Highlight widget - if (currently_highlighted != null) currently_highlighted.unset_state_flags(StateFlags.PRELIGHT); - w.set_state_flags(StateFlags.PRELIGHT, true); - currently_highlighted = w; + update_message_menu(); + + if (current_meta_item != null) { + // Highlight widget + w.set_state_flags(StateFlags.PRELIGHT, true); + currently_highlighted = w; + + // Move message menu + message_menu_box.margin_top = widget_y - 10; + } + } - // Move message menu - message_menu_box.margin_top = widget_y - 10; + private void update_message_menu() { + if (current_meta_item == null) { + message_menu_box.visible = false; + return; + } + + var actions = current_meta_item.get_item_actions(Plugins.WidgetType.GTK); + message_menu_box.visible = actions != null && actions.size > 0; + if (actions != null && actions.size == 1) { + button1.visible = true; + button1_icon.set_from_icon_name(actions[0].icon_name, IconSize.SMALL_TOOLBAR); + } } public void initialize_for_conversation(Conversation? conversation) { @@ -163,8 +184,6 @@ public class ConversationView : Box, Plugins.ConversationItemCollection, Plugins initialize_for_conversation_(conversation); display_latest(); stack.set_visible_child_name("main"); - - enable_menu_box = false; } public void initialize_around_message(Conversation conversation, ContentItem content_item) { diff --git a/main/src/ui/conversation_content_view/date_separator_populator.vala b/main/src/ui/conversation_content_view/date_separator_populator.vala index 3ddb0d9a..91485f25 100644 --- a/main/src/ui/conversation_content_view/date_separator_populator.vala +++ b/main/src/ui/conversation_content_view/date_separator_populator.vala @@ -54,10 +54,6 @@ class DateSeparatorPopulator : Plugins.ConversationItemPopulator, Plugins.Conver public class MetaDateItem : Plugins.MetaConversationItem { public override DateTime sort_time { get; set; } - public override bool can_merge { get; set; default=false; } - public override bool requires_avatar { get; set; default=false; } - public override bool requires_header { get; set; default=false; } - private DateTime date; public MetaDateItem(DateTime date) { @@ -76,6 +72,8 @@ public class MetaDateItem : Plugins.MetaConversationItem { return box; } + public override Gee.List<Plugins.MessageAction>? get_item_actions(Plugins.WidgetType type) { return null; } + private static string get_relative_time(DateTime time) { DateTime time_local = time.to_local(); DateTime now_local = new DateTime.now_local(); diff --git a/main/src/ui/conversation_content_view/file_widget.vala b/main/src/ui/conversation_content_view/file_widget.vala index f5ba08e3..ee14af7a 100644 --- a/main/src/ui/conversation_content_view/file_widget.vala +++ b/main/src/ui/conversation_content_view/file_widget.vala @@ -7,6 +7,24 @@ using Dino.Entities; namespace Dino.Ui.ConversationSummary { +public class FileMetaItem : ContentMetaItem { + + private StreamInteractor stream_interactor; + + public FileMetaItem(ContentItem content_item, StreamInteractor stream_interactor) { + base(content_item); + this.stream_interactor = stream_interactor; + } + + public override Object? get_widget(Plugins.WidgetType type) { + FileItem file_item = content_item as FileItem; + FileTransfer transfer = file_item.file_transfer; + return new FileWidget(stream_interactor, transfer) { visible=true }; + } + + public override Gee.List<Plugins.MessageAction>? get_item_actions(Plugins.WidgetType type) { return null; } +} + public class FileWidget : Box { enum State { diff --git a/main/src/ui/conversation_content_view/message_item.vala b/main/src/ui/conversation_content_view/message_item.vala deleted file mode 100644 index e69de29b..00000000 --- a/main/src/ui/conversation_content_view/message_item.vala +++ /dev/null diff --git a/main/src/ui/conversation_content_view/message_widget.vala b/main/src/ui/conversation_content_view/message_widget.vala new file mode 100644 index 00000000..71094c71 --- /dev/null +++ b/main/src/ui/conversation_content_view/message_widget.vala @@ -0,0 +1,211 @@ +using Gee; +using Gdk; +using Gtk; +using Pango; +using Xmpp; + +using Dino.Entities; + +namespace Dino.Ui.ConversationSummary { + +public class MessageMetaItem : ContentMetaItem { + + private StreamInteractor stream_interactor; + private MessageItemWidget message_item_widget; + private MessageItem message_item; + + public MessageMetaItem(ContentItem content_item, StreamInteractor stream_interactor) { + base(content_item); + message_item = content_item as MessageItem; + this.stream_interactor = stream_interactor; + } + + public override Object? get_widget(Plugins.WidgetType type) { + message_item_widget = new MessageItemWidget(stream_interactor, content_item) { visible=true }; + + message_item_widget.edit_cancelled.connect(() => { this.in_edit_mode = false; }); + message_item_widget.edit_sent.connect(on_edit_send); + + stream_interactor.get_module(MessageCorrection.IDENTITY).received_correction.connect(on_received_correction); + + return message_item_widget; + } + + public override Gee.List<Plugins.MessageAction>? get_item_actions(Plugins.WidgetType type) { + if (content_item as FileItem != null) return null; + + bool allowed = stream_interactor.get_module(MessageCorrection.IDENTITY).is_own_correction_allowed(message_item.conversation, message_item.message); + Gee.List<Plugins.MessageAction> actions = new ArrayList<Plugins.MessageAction>(); + if (allowed && !in_edit_mode) { + Plugins.MessageAction action1 = new Plugins.MessageAction(); + action1.icon_name = "document-edit-symbolic"; + action1.callback = (button, content_meta_item_activated, widget) => { + message_item_widget.set_edit_mode(); + this.in_edit_mode = true; + }; + actions.add(action1); + } + return actions; + } + + private void on_edit_send(string text) { + stream_interactor.get_module(MessageCorrection.IDENTITY).send_correction(message_item.conversation, message_item.message, text); + this.in_edit_mode = false; + } + + private void on_received_correction(ContentItem content_item) { + if (this.content_item.id == content_item.id) { + this.content_item = content_item; + message_item = content_item as MessageItem; + message_item_widget.content_item = content_item; + message_item_widget.update_label(); + } + } +} + +public class MessageItemWidget : SizeRequestBin { + + public signal void edit_cancelled(); + public signal void edit_sent(string text); + + StreamInteractor stream_interactor; + public ContentItem content_item; + + Label label = new Label("") { use_markup=true, xalign=0, selectable=true, wrap=true, wrap_mode=Pango.WrapMode.WORD_CHAR, vexpand=true, visible=true }; + MessageItemEditMode? edit_mode = null; + ChatTextViewController? controller = null; + + ulong realize_id = -1; + ulong style_updated_id = -1; + + construct { + this.add(label); + this.size_request_mode = SizeRequestMode.HEIGHT_FOR_WIDTH; + } + + public MessageItemWidget(StreamInteractor stream_interactor, ContentItem content_item) { + this.stream_interactor = stream_interactor; + this.content_item = content_item; + + update_label(); + } + + public void set_edit_mode() { + + MessageItem message_item = content_item as MessageItem; + Message message = message_item.message; + + if (edit_mode == null) { + edit_mode = new MessageItemEditMode(); + controller = new ChatTextViewController(edit_mode.chat_text_view, stream_interactor); + Conversation conversation = message_item.conversation; + controller.initialize_for_conversation(conversation); + + edit_mode.cancelled.connect(() => { + edit_cancelled(); + unset_edit_mode(); + }); + edit_mode.send.connect(() => { + edit_sent(edit_mode.chat_text_view.text_view.buffer.text); + unset_edit_mode(); + }); + } + + edit_mode.chat_text_view.text_view.buffer.text = message.body; + + this.remove(label); + this.add(edit_mode); + + edit_mode.chat_text_view.text_view.grab_focus(); + } + + public void unset_edit_mode() { + this.remove(edit_mode); + this.add(label); + } + + public void update_label() { + label.label = generate_markup_text(content_item); + } + + private string generate_markup_text(ContentItem item) { + MessageItem message_item = item as MessageItem; + Conversation conversation = message_item.conversation; + Message message = message_item.message; + + bool theme_dependent = false; + + string markup_text = message.body; + if (markup_text.length > 10000) { + markup_text = markup_text.substring(0, 10000) + " [" + _("Message too long") + "]"; + } + if (message.body.has_prefix("/me")) { + markup_text = markup_text.substring(3); + } + + if (conversation.type_ == Conversation.Type.GROUPCHAT) { + markup_text = Util.parse_add_markup(markup_text, conversation.nickname, true, true); + } else { + markup_text = Util.parse_add_markup(markup_text, null, true, true); + } + + if (message.body.has_prefix("/me")) { + string display_name = Util.get_participant_display_name(stream_interactor, conversation, message.from); + string color = Util.get_name_hex_color(stream_interactor, conversation.account, message.real_jid ?? message.from, Util.is_dark_theme(label)); + markup_text = @"<span color=\"#$(color)\">$(Markup.escape_text(display_name))</span>" + markup_text; + theme_dependent = true; + } + + int only_emoji_count = Util.get_only_emoji_count(markup_text); + if (only_emoji_count != -1) { + string size_str = only_emoji_count < 5 ? "xx-large" : "large"; + markup_text = @"<span size=\'$size_str\'>" + markup_text + "</span>"; + } + + if (message.edit_to != null) { + string color = Util.is_dark_theme(label) ? "#808080" : "#909090"; + markup_text += " <span size='small' color='%s'>(%s)</span>".printf(color, _("edited")); + theme_dependent = true; + } + + if (theme_dependent && realize_id == -1) { + realize_id = label.realize.connect(update_label); + style_updated_id = label.style_updated.connect(update_label); + } else if (!theme_dependent && realize_id != -1) { + label.disconnect(realize_id); + label.disconnect(style_updated_id); + } + return markup_text; + } +} + +[GtkTemplate (ui = "/im/dino/Dino/message_item_widget_edit_mode.ui")] +public class MessageItemEditMode : Box { + + public signal void cancelled(); + public signal void send(); + + [GtkChild] public MenuButton emoji_button; + [GtkChild] public ChatTextView chat_text_view; + [GtkChild] public Button cancel_button; + [GtkChild] public Button send_button; + [GtkChild] public Frame frame; + + construct { + Util.force_css(frame, "* { border-radius: 3px; }"); + + EmojiChooser chooser = new EmojiChooser(); + chooser.emoji_picked.connect((emoji) => { + chat_text_view.text_view.buffer.insert_at_cursor(emoji, emoji.data.length); + }); + emoji_button.set_popover(chooser); + + cancel_button.clicked.connect(() => cancelled()); + send_button.clicked.connect(() => send()); + chat_text_view.cancel_input.connect(() => cancelled()); + chat_text_view.send_text.connect(() => send()); + + } +} + +} |