diff options
Diffstat (limited to 'client/src/ui/conversation_summary')
-rw-r--r-- | client/src/ui/conversation_summary/merged_message_item.vala | 170 | ||||
-rw-r--r-- | client/src/ui/conversation_summary/merged_status_item.vala | 30 | ||||
-rw-r--r-- | client/src/ui/conversation_summary/status_item.vala | 29 | ||||
-rw-r--r-- | client/src/ui/conversation_summary/view.vala | 222 |
4 files changed, 0 insertions, 451 deletions
diff --git a/client/src/ui/conversation_summary/merged_message_item.vala b/client/src/ui/conversation_summary/merged_message_item.vala deleted file mode 100644 index 3647d082..00000000 --- a/client/src/ui/conversation_summary/merged_message_item.vala +++ /dev/null @@ -1,170 +0,0 @@ -using Gee; -using Gdk; -using Gtk; -using Markup; - -using Dino.Entities; - -namespace Dino.Ui.ConversationSummary { - -[GtkTemplate (ui = "/org/dino-im/conversation_summary/message_item.ui")] -public class MergedMessageItem : Grid { - - public Conversation conversation { get; set; } - public Jid from { get; private set; } - public DateTime initial_time { get; private set; } - public ArrayList<Message> messages = new ArrayList<Message>(Message.equals_func); - - [GtkChild] - private Image image; - - [GtkChild] - private Label time_label; - - [GtkChild] - private Label name_label; - - [GtkChild] - private Image encryption_image; - - [GtkChild] - private Image received_image; - - [GtkChild] - private TextView message_text_view; - - public MergedMessageItem(StreamInteractor stream_interactor, Conversation conversation, Message message) { - this.conversation = conversation; - this.from = message.from; - this.initial_time = message.time; - setup_tags(); - add_message(message); - - time_label.label = get_relative_time(initial_time.to_local()); - string display_name = Util.get_message_display_name(stream_interactor, message, conversation.account); - name_label.set_markup(@"<span foreground=\"#$(Util.get_name_hex_color(display_name))\">$display_name</span>"); - Util.image_set_from_scaled_pixbuf(image, (new AvatarGenerator(30, 30, image.scale_factor)).draw_message(stream_interactor, message)); - if (message.encryption == Entities.Message.Encryption.PGP) { - encryption_image.visible = true; - encryption_image.set_from_icon_name("changes-prevent-symbolic", IconSize.SMALL_TOOLBAR); - } - } - - public void update() { - time_label.label = get_relative_time(initial_time.to_local()); - } - - public void add_message(Message message) { - TextIter end; - message_text_view.buffer.get_end_iter(out end); - if (messages.size > 0) { - message_text_view.buffer.insert(ref end, "\n", -1); - } - message_text_view.buffer.insert(ref end, message.body, -1); - format_suffix_urls(message.body); - messages.add(message); - message.notify["marked"].connect_after(update_received); // TODO other thread? not main? css error? gtk main? - update_received(); - } - - private void update_received() { - bool all_received = true; - bool all_read = true; - foreach (Message message in messages) { - if (message.marked == Message.Marked.WONTSEND) { - received_image.visible = true; - Gtk.IconTheme icon_theme = Gtk.IconTheme.get_default(); - Gtk.IconInfo? icon_info = icon_theme.lookup_icon("dialog-warning-symbolic", IconSize.SMALL_TOOLBAR, 0); - received_image.set_from_pixbuf(icon_info.load_symbolic({1,0,0,1})); - return; - } else if (message.marked != Message.Marked.READ) { - all_read = false; - if (message.marked != Message.Marked.RECEIVED) { - all_received = false; - } - } - } - if (all_read) { - received_image.visible = true; - received_image.set_from_resource("/org/dino-im/img/double_tick.svg"); - } else if (all_received) { - received_image.visible = true; - received_image.set_from_resource("/org/dino-im/img/tick.svg"); - } else if (received_image.visible) { - received_image.set_from_icon_name("image-loading-symbolic", IconSize.SMALL_TOOLBAR); - } - } - - private void format_suffix_urls(string text) { - int absolute_start = message_text_view.buffer.text.length - text.length; - - Regex url_regex = new Regex("""(?i)\b((?:[a-z][\w-]+:(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))"""); - MatchInfo match_info; - url_regex.match(text, 0, out match_info); - for (; match_info.matches(); match_info.next()) { - string? url = match_info.fetch(0); - int start; - int end; - match_info.fetch_pos(0, out start, out end); - TextIter start_iter; - TextIter end_iter; - message_text_view.buffer.get_iter_at_offset(out start_iter, absolute_start + start); - message_text_view.buffer.get_iter_at_offset(out end_iter, absolute_start + end); - message_text_view.buffer.apply_tag_by_name("url", start_iter, end_iter); - } - } - - private void setup_tags() { - message_text_view.buffer.create_tag("url", underline: Pango.Underline.SINGLE, foreground: "blue"); - message_text_view.button_release_event.connect(open_url); - message_text_view.motion_notify_event.connect(change_cursor_over_url); - } - - private bool open_url(EventButton event_button) { - int buffer_x, buffer_y; - message_text_view.window_to_buffer_coords(TextWindowType.TEXT, (int) event_button.x, (int) event_button.y, out buffer_x, out buffer_y); - TextIter iter; - message_text_view.get_iter_at_location(out iter, buffer_x, buffer_y); - TextIter start_iter = iter, end_iter = iter; - if (start_iter.backward_to_tag_toggle(null) && end_iter.forward_to_tag_toggle(null)) { - string url = start_iter.get_text(end_iter); - try{ - AppInfo.launch_default_for_uri(url, null); - } catch (Error err) { - print("Tryed to open " + url); - } - } - return false; - } - - private bool change_cursor_over_url(EventMotion event_motion) { - TextIter iter; - message_text_view.get_iter_at_location(out iter, (int) event_motion.x, (int) event_motion.y); - if (iter.has_tag(message_text_view.buffer.tag_table.lookup("url"))) { - event_motion.window.set_cursor(new Cursor.for_display(get_display(), CursorType.HAND2)); - } else { - event_motion.window.set_cursor(new Cursor.for_display(get_display(), CursorType.XTERM)); - } - return false; - } - - private static string get_relative_time(DateTime datetime) { - DateTime now = new DateTime.now_local(); - TimeSpan timespan = now.difference(datetime); - if (timespan > 365 * TimeSpan.DAY) { - return datetime.format("%d.%m.%Y %H:%M"); - } else if (timespan > 7 * TimeSpan.DAY) { - return datetime.format("%d.%m %H:%M"); - } else if (timespan > 1 * TimeSpan.DAY) { - return datetime.format("%a, %H:%M"); - } else if (timespan > 9 * TimeSpan.MINUTE) { - return datetime.format("%H:%M"); - } else if (timespan > TimeSpan.MINUTE) { - return (timespan / TimeSpan.MINUTE).to_string() + " min ago"; - } else { - return "Just now"; - } - } -} - -} diff --git a/client/src/ui/conversation_summary/merged_status_item.vala b/client/src/ui/conversation_summary/merged_status_item.vala deleted file mode 100644 index 78b156e9..00000000 --- a/client/src/ui/conversation_summary/merged_status_item.vala +++ /dev/null @@ -1,30 +0,0 @@ -using Gee; -using Gtk; - -using Dino.Entities; - -namespace Dino.Ui.ConversationSummary { - -private class MergedStatusItem : Expander { - - private StreamInteractor stream_interactor; - private Conversation conversation; - private ArrayList<Show> statuses = new ArrayList<Show>(); - - public MergedStatusItem(StreamInteractor stream_interactor, Conversation conversation, Show show) { - set_hexpand(true); - add_status(show); - } - - public void add_status(Show show) { - statuses.add(show); - StatusItem status_item = new StatusItem(stream_interactor, conversation, @"is $(show.as)"); - if (statuses.size == 1) { - label = show.as; - } else { - label = @"changed their status $(statuses.size) times"; - add(new Label(show.as)); - } - } -} -}
\ No newline at end of file diff --git a/client/src/ui/conversation_summary/status_item.vala b/client/src/ui/conversation_summary/status_item.vala deleted file mode 100644 index 5918d008..00000000 --- a/client/src/ui/conversation_summary/status_item.vala +++ /dev/null @@ -1,29 +0,0 @@ -using Gtk; -using Markup; - -using Dino.Entities; - -namespace Dino.Ui.ConversationSummary { - -private class StatusItem : Grid { - - private Image image = new Image(); - private Label label = new Label(""); - - private StreamInteractor stream_interactor; - private Conversation conversation; - - public StatusItem(StreamInteractor stream_interactor, Conversation conversation, string? text) { - Object(column_spacing : 7); - set_hexpand(true); - this.stream_interactor = stream_interactor; - this.conversation = conversation; - image.set_from_pixbuf((new AvatarGenerator(30, 30)).set_greyscale(true).draw_conversation(stream_interactor, conversation)); - attach(image, 0, 0, 1, 1); - attach(label, 1, 0, 1, 1); - string display_name = Util.get_display_name(stream_interactor, conversation.counterpart, conversation.account); - label.set_markup(@"<span foreground=\"#B1B1B1\"> $(escape_text(display_name)) $text </span>"); - show_all(); - } -} -}
\ No newline at end of file diff --git a/client/src/ui/conversation_summary/view.vala b/client/src/ui/conversation_summary/view.vala deleted file mode 100644 index 59cf88aa..00000000 --- a/client/src/ui/conversation_summary/view.vala +++ /dev/null @@ -1,222 +0,0 @@ -using Gee; -using Gtk; -using Pango; - -using Dino.Entities; -using Xmpp; - -namespace Dino.Ui.ConversationSummary { - -[GtkTemplate (ui = "/org/dino-im/conversation_summary/view.ui")] -public class View : Box { - - public Conversation? conversation { get; private set; } - public HashMap<Entities.Message, MergedMessageItem> message_items = new HashMap<Entities.Message, MergedMessageItem>(Entities.Message.hash_func, Entities.Message.equals_func); - - [GtkChild] - private ScrolledWindow scrolled; - - [GtkChild] - private Box main; - - private StreamInteractor stream_interactor; - private MergedMessageItem? last_message_item; - private StatusItem typing_status; - private Entities.Message? earliest_message; - double? was_value; - double? was_upper; - double? was_page_size; - Object reloading_lock = new Object(); - bool reloading = false; - - public View(StreamInteractor stream_interactor) { - Object(homogeneous : false, spacing : 0); - this.stream_interactor = stream_interactor; - scrolled.vadjustment.notify["upper"].connect_after(on_upper_notify); - scrolled.vadjustment.notify["value"].connect(on_value_notify); - - CounterpartInteractionManager.get_instance(stream_interactor).received_state.connect((account, jid, state) => { - Idle.add(() => { on_received_state(account, jid, state); return false; }); - }); - MessageManager.get_instance(stream_interactor).message_received.connect((message, conversation) => { - Idle.add(() => { show_message(message, conversation, true); return false; }); - }); - MessageManager.get_instance(stream_interactor).message_sent.connect((message, conversation) => { - Idle.add(() => { show_message(message, conversation, true); return false; }); - }); - PresenceManager.get_instance(stream_interactor).show_received.connect((show, jid, account) => { - Idle.add(() => { on_show_received(show, jid, account); return false; }); - }); - Timeout.add_seconds(60, () => { - foreach (MergedMessageItem message_item in message_items.values) { - message_item.update(); - } - return true; - }); - } - - public void initialize_for_conversation(Conversation? conversation) { - this.conversation = conversation; - clear(); - message_items.clear(); - was_upper = null; - was_page_size = null; - last_message_item = null; - - ArrayList<Object> objects = new ArrayList<Object>(); - Gee.List<Entities.Message>? messages = MessageManager.get_instance(stream_interactor).get_messages(conversation); - if (messages != null && messages.size > 0) { - earliest_message = messages[0]; - objects.add_all(messages); - } - HashMap<Jid, ArrayList<Show>>? shows = PresenceManager.get_instance(stream_interactor).get_shows(conversation.counterpart, conversation.account); - if (shows != null) { - foreach (Jid jid in shows.keys) objects.add_all(shows[jid]); - } - objects.sort((a, b) => { - DateTime? dt1 = null; - DateTime? dt2 = null; - Entities.Message m1 = a as Entities.Message; - if (m1 != null) dt1 = m1.time; - Show s1 = a as Show; - if (s1 != null) dt1 = s1.datetime; - Entities.Message m2 = b as Entities.Message; - if (m2 != null) dt2 = m2.time; - Show s2 = b as Show; - if (s2 != null) dt2 = s2.datetime; - return dt1.compare(dt2); - }); - foreach (Object o in objects) { - Entities.Message message = o as Entities.Message; - Show show = o as Show; - if (message != null) { - show_message(message, conversation); - } else if (show != null) { - on_show_received(show, conversation.counterpart, conversation.account); - } - } - update_chat_state(); - } - - private void on_received_state(Account account, Jid jid, string state) { - if (conversation != null && conversation.account.equals(account) && conversation.counterpart.equals_bare(jid)) { - update_chat_state(state); - } - } - - private void update_chat_state(string? state = null) { - string? state_ = state; - if (state_ == null) { - state_ = CounterpartInteractionManager.get_instance(stream_interactor).get_chat_state(conversation.account, conversation.counterpart); - } - if (typing_status != null) { - main.remove(typing_status); - } - if (state_ != null) { - if (state_ == Xep.ChatStateNotifications.STATE_COMPOSING || state_ == Xep.ChatStateNotifications.STATE_PAUSED) { - if (state_ == Xep.ChatStateNotifications.STATE_COMPOSING) { - typing_status = new StatusItem(stream_interactor, conversation, "is typing..."); - } else if (state_ == Xep.ChatStateNotifications.STATE_PAUSED) { - typing_status = new StatusItem(stream_interactor, conversation, "has stoped typing"); - } - main.add(typing_status); - } - } - } - - private void on_show_received(Show show, Jid jid, Account account) { - - } - - private void on_upper_notify() { - if (was_upper == null || scrolled.vadjustment.value > was_upper - was_page_size - 1 || - scrolled.vadjustment.value > was_upper - was_page_size - 1) { // scrolled down or content smaller than page size - scrolled.vadjustment.value = scrolled.vadjustment.upper - scrolled.vadjustment.page_size; // scroll down - } else if (scrolled.vadjustment.value < scrolled.vadjustment.upper - scrolled.vadjustment.page_size - 1){ - scrolled.vadjustment.value = scrolled.vadjustment.upper - was_upper + scrolled.vadjustment.value; // stay at same content - } - was_upper = scrolled.vadjustment.upper; - was_page_size = scrolled.vadjustment.page_size; - lock(reloading_lock) { - reloading = false; - } - } - - private void on_value_notify() { - if (scrolled.vadjustment.value < 200) { - load_earlier_messages(); - } - } - - private void load_earlier_messages() { - was_value = scrolled.vadjustment.value; - lock(reloading_lock) { - if(reloading) return; - reloading = true; - } - Gee.List<Entities.Message>? messages = MessageManager.get_instance(stream_interactor).get_messages_before(conversation, earliest_message); - if (messages != null && messages.size > 0) { - earliest_message = messages[0]; - MergedMessageItem? current_item = null; - int items_added = 0; - for (int i = 0; i < messages.size; i++) { - if (current_item != null && should_merge_message(current_item, messages[i])) { - current_item.add_message(messages[i]); - } else { - current_item = new MergedMessageItem(stream_interactor, conversation, messages[i]); - force_alloc_width(current_item, main.get_allocated_width()); - main.add(current_item); - message_items[messages[i]] = current_item; - main.reorder_child(current_item, items_added); - items_added++; - } - } - return; - } - reloading = false; - } - - private void show_message(Entities.Message message, Conversation conversation, bool animate = false) { - if (this.conversation != null && this.conversation.equals(conversation)) { - if (should_merge_message(last_message_item, message)) { - last_message_item.add_message(message); - } else { - MergedMessageItem message_item = new MergedMessageItem(stream_interactor, conversation, message); - if (animate) { - Revealer revealer = new Revealer() {transition_duration = 200, transition_type = RevealerTransitionType.SLIDE_UP, visible = true}; - revealer.add(message_item); - force_alloc_width(revealer, main.get_allocated_width()); - main.add(revealer); - revealer.set_reveal_child(true); - } else { - force_alloc_width(message_item, main.get_allocated_width()); - main.add(message_item); - } - last_message_item = message_item; - } - message_items[message] = last_message_item; - update_chat_state(); - } - } - - private bool should_merge_message(MergedMessageItem? message_item, Entities.Message message) { - return message_item != null && - message_item.from.equals(message.from) && - message_item.messages.get(0).encryption == message.encryption && - message.time.difference(message_item.initial_time) < TimeSpan.MINUTE && - (message_item.messages.get(0).marked == Entities.Message.Marked.WONTSEND) == (message.marked == Entities.Message.Marked.WONTSEND); - } - - private void force_alloc_width(Widget widget, int width) { - Allocation alloc = Allocation(); - widget.get_preferred_width(out alloc.width, null); - widget.get_preferred_height(out alloc.height, null); - alloc.width = width; - widget.size_allocate(alloc); - } - - private void clear() { - main.@foreach((widget) => { main.remove(widget); }); - } -} -} |