From fb799e3ba8313ff2da53d9d5c34f8421f164cbf1 Mon Sep 17 00:00:00 2001 From: fiaxh Date: Mon, 27 Feb 2023 23:38:31 +0100 Subject: Fix some memory leaks --- .../conversation_item_skeleton.vala | 36 ++++++++- .../conversation_view.vala | 10 ++- .../ui/conversation_content_view/file_widget.vala | 11 +++ .../conversation_content_view/message_widget.vala | 88 +++++++++++++--------- main/src/ui/widgets/date_separator.vala | 10 ++- plugins/omemo/src/ui/bad_messages_populator.vala | 41 +++++++--- 6 files changed, 143 insertions(+), 53 deletions(-) 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 9e98cacb..b6c0f7c6 100644 --- a/main/src/ui/conversation_content_view/conversation_item_skeleton.vala +++ b/main/src/ui/conversation_content_view/conversation_item_skeleton.vala @@ -71,9 +71,7 @@ public class ConversationItemSkeleton : Plugins.ConversationItemWidgetInterface, ContentMetaItem? content_meta_item = item as ContentMetaItem; if (content_meta_item != null) { reactions_controller = new ReactionsController(conversation, content_meta_item.content_item, stream_interactor); - reactions_controller.box_activated.connect((widget) => { - set_widget(widget, Plugins.WidgetType.GTK4, 3); - }); + reactions_controller.box_activated.connect(on_reaction_box_activated); reactions_controller.init(); } @@ -170,6 +168,10 @@ public class ConversationItemSkeleton : Plugins.ConversationItemWidgetInterface, } } + private void on_reaction_box_activated(Widget widget) { + set_widget(widget, Plugins.WidgetType.GTK4, 3); + } + private void update_time() { time_label.label = get_relative_time(item.time.to_local()).to_string(); @@ -271,6 +273,34 @@ public class ConversationItemSkeleton : Plugins.ConversationItemWidgetInterface, stream_interactor.get_module(RosterManager.IDENTITY).disconnect(updated_roster_handler_id); updated_roster_handler_id = 0; } + reactions_controller = null; + + // Children won't be disposed automatically + if (name_label != null) { + name_label.unparent(); + name_label.dispose(); + name_label = null; + } + if (time_label != null) { + time_label.unparent(); + time_label.dispose(); + time_label = null; + } + if (avatar_image != null) { + avatar_image.unparent(); + avatar_image.dispose(); + avatar_image = null; + } + if (encryption_image != null) { + encryption_image.unparent(); + encryption_image.dispose(); + encryption_image = null; + } + if (received_image != null) { + received_image.unparent(); + received_image.dispose(); + received_image = null; + } base.dispose(); } } diff --git a/main/src/ui/conversation_content_view/conversation_view.vala b/main/src/ui/conversation_content_view/conversation_view.vala index ae7ed657..badc6c65 100644 --- a/main/src/ui/conversation_content_view/conversation_view.vala +++ b/main/src/ui/conversation_content_view/conversation_view.vala @@ -426,6 +426,7 @@ public class ConversationView : Widget, Plugins.ConversationItemCollection, Plug content_items.remove((ContentMetaItem)item); } meta_items.remove(item); + skeleton.dispose(); } removed_item(item); @@ -591,12 +592,19 @@ public class ConversationView : Widget, Plugins.ConversationItemCollection, Plug private void clear() { was_upper = null; was_page_size = null; + foreach (var item in content_items) { + item.dispose(); + } content_items.clear(); meta_items.clear(); widget_order.clear(); + foreach (var skeleton in item_item_skeletons.values) { + skeleton.dispose(); + } item_item_skeletons.clear(); foreach (Widget widget in widgets.values) { - main.remove(widget); + widget.unparent(); + widget.dispose(); } widgets.clear(); } diff --git a/main/src/ui/conversation_content_view/file_widget.vala b/main/src/ui/conversation_content_view/file_widget.vala index 543eb169..785acf7d 100644 --- a/main/src/ui/conversation_content_view/file_widget.vala +++ b/main/src/ui/conversation_content_view/file_widget.vala @@ -135,6 +135,17 @@ public class FileWidget : SizeRequestBox { } return false; } + + public override void dispose() { + if (default_widget_controller != null) default_widget_controller.dispose(); + default_widget_controller = null; + if (content != null) { + content.unparent(); + content.dispose(); + content = null; + } + base.dispose(); + } } public class FileWidgetController : Object { diff --git a/main/src/ui/conversation_content_view/message_widget.vala b/main/src/ui/conversation_content_view/message_widget.vala index d7733d5a..11b38286 100644 --- a/main/src/ui/conversation_content_view/message_widget.vala +++ b/main/src/ui/conversation_content_view/message_widget.vala @@ -19,6 +19,7 @@ public class MessageMetaItem : ContentMetaItem { private StreamInteractor stream_interactor; private MessageItem message_item; public Message.Marked marked { get; set; } + public Plugins.ConversationItemWidgetInterface outer = null; MessageItemEditMode? edit_mode = null; ChatTextViewController? controller = null; @@ -35,6 +36,8 @@ public class MessageMetaItem : ContentMetaItem { message_item = content_item as MessageItem; this.stream_interactor = stream_interactor; + stream_interactor.get_module(MessageCorrection.IDENTITY).received_correction.connect(on_received_correction); + label.activate_link.connect(on_label_activate_link); Message message = ((MessageItem) content_item).message; @@ -146,43 +149,9 @@ public class MessageMetaItem : ContentMetaItem { } public override Object? get_widget(Plugins.ConversationItemWidgetInterface outer, Plugins.WidgetType type) { + this.outer = outer; - stream_interactor.get_module(MessageCorrection.IDENTITY).received_correction.connect(on_received_correction); - - this.notify["in-edit-mode"].connect(() => { - if (in_edit_mode == false) return; - bool allowed = stream_interactor.get_module(MessageCorrection.IDENTITY).is_own_correction_allowed(message_item.conversation, message_item.message); - if (allowed) { - MessageItem message_item = content_item as MessageItem; - Message message = message_item.message; - - 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(() => { - in_edit_mode = false; - outer.set_widget(label, Plugins.WidgetType.GTK4, 2); - }); - edit_mode.send.connect(() => { - if (((MessageItem) content_item).message.body != edit_mode.chat_text_view.text_view.buffer.text) { - on_edit_send(edit_mode.chat_text_view.text_view.buffer.text); - } else { -// edit_cancelled(); - } - in_edit_mode = false; - outer.set_widget(label, Plugins.WidgetType.GTK4, 2); - }); - - edit_mode.chat_text_view.text_view.buffer.text = message.body; - - outer.set_widget(edit_mode, Plugins.WidgetType.GTK4, 2); - edit_mode.chat_text_view.text_view.grab_focus(); - } else { - this.in_edit_mode = false; - } - }); + this.notify["in-edit-mode"].connect(on_in_edit_mode_changed); outer.set_widget(label, Plugins.WidgetType.GTK4, 2); @@ -201,7 +170,6 @@ public class MessageMetaItem : ContentMetaItem { } public override Gee.List? get_item_actions(Plugins.WidgetType type) { - if (content_item as FileItem != null || this.in_edit_mode) return null; if (in_edit_mode) return null; Gee.List actions = new ArrayList(); @@ -224,6 +192,41 @@ public class MessageMetaItem : ContentMetaItem { return actions; } + private void on_in_edit_mode_changed() { + if (in_edit_mode == false) return; + bool allowed = stream_interactor.get_module(MessageCorrection.IDENTITY).is_own_correction_allowed(message_item.conversation, message_item.message); + if (allowed) { + MessageItem message_item = content_item as MessageItem; + Message message = message_item.message; + + 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(() => { + in_edit_mode = false; + outer.set_widget(label, Plugins.WidgetType.GTK4, 2); + }); + edit_mode.send.connect(() => { + if (((MessageItem) content_item).message.body != edit_mode.chat_text_view.text_view.buffer.text) { + on_edit_send(edit_mode.chat_text_view.text_view.buffer.text); + } else { +// edit_cancelled(); + } + in_edit_mode = false; + outer.set_widget(label, Plugins.WidgetType.GTK4, 2); + }); + + edit_mode.chat_text_view.text_view.buffer.text = message.body; + + outer.set_widget(edit_mode, Plugins.WidgetType.GTK4, 2); + edit_mode.chat_text_view.text_view.grab_focus(); + } else { + this.in_edit_mode = false; + } + } + 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; @@ -244,6 +247,17 @@ public class MessageMetaItem : ContentMetaItem { Dino.Application.get_default().open(new File[]{file}, ""); return true; } + + public override void dispose() { + stream_interactor.get_module(MessageCorrection.IDENTITY).received_correction.disconnect(on_received_correction); + this.notify["in-edit-mode"].disconnect(on_in_edit_mode_changed); + if (label != null) { + label.unparent(); + label.dispose(); + label = null; + } + base.dispose(); + } } [GtkTemplate (ui = "/im/dino/Dino/message_item_widget_edit_mode.ui")] diff --git a/main/src/ui/widgets/date_separator.vala b/main/src/ui/widgets/date_separator.vala index 95729bce..b5d84a5b 100644 --- a/main/src/ui/widgets/date_separator.vala +++ b/main/src/ui/widgets/date_separator.vala @@ -40,8 +40,14 @@ public class Dino.Ui.ViewModel.CompatDateSeparatorModel : DateSeparatorModel { private void update_time_label() { date_label = get_relative_time(date); - time_update_timeout = Timeout.add_seconds((int) get_next_time_change(), () => { - if (time_update_timeout != 0) update_time_label(); + time_update_timeout = set_update_time_label_timeout((int) get_next_time_change(), this); + } + + private static uint set_update_time_label_timeout(int interval, CompatDateSeparatorModel model_) { + WeakRef model_weak = WeakRef(model_); + return Timeout.add_seconds(interval, () => { + CompatDateSeparatorModel? model = (CompatDateSeparatorModel) model_weak.get(); + if (model != null && model.time_update_timeout != 0) model.update_time_label(); return false; }); } diff --git a/plugins/omemo/src/ui/bad_messages_populator.vala b/plugins/omemo/src/ui/bad_messages_populator.vala index 3cb3375b..8f087482 100644 --- a/plugins/omemo/src/ui/bad_messages_populator.vala +++ b/plugins/omemo/src/ui/bad_messages_populator.vala @@ -94,6 +94,7 @@ public class BadMessagesPopulator : Plugins.ConversationItemPopulator, Plugins.C foreach (BadMessageItem bad_item in bad_items) { item_collection.remove_item(bad_item); } + bad_items.clear(); } public void init(Conversation conversation, Plugins.ConversationItemCollection item_collection, Plugins.WidgetType type) { @@ -103,7 +104,9 @@ public class BadMessagesPopulator : Plugins.ConversationItemPopulator, Plugins.C init_state(); } - public void close(Conversation conversation) { } + public void close(Conversation conversation) { + clear_state(); + } public void populate_timespan(Conversation conversation, DateTime after, DateTime before) { } } @@ -131,9 +134,17 @@ public class BadMessageItem : Plugins.MetaConversationItem { } public class BadMessagesWidget : Box { + private Plugin plugin; + private Conversation conversation; + private Jid jid; + private Label label; + public BadMessagesWidget(Plugin plugin, Conversation conversation, Jid jid, BadnessType badness_type) { Object(orientation:Orientation.HORIZONTAL, spacing:5); + this.plugin = plugin; + this.conversation = conversation; + this.jid = jid; this.halign = Align.CENTER; this.visible = true; @@ -159,19 +170,29 @@ public class BadMessagesWidget : Box { } else { warning_text += _("%s does not trust this device. That means, you might be missing messages.").printf(who); } - Label label = new Label(warning_text) { margin_start=70, margin_end=70, justify=Justification.CENTER, use_markup=true, selectable=true, wrap=true, wrap_mode=Pango.WrapMode.WORD_CHAR, hexpand=true }; + label = new Label(warning_text) { margin_start=70, margin_end=70, justify=Justification.CENTER, use_markup=true, selectable=true, wrap=true, wrap_mode=Pango.WrapMode.WORD_CHAR, hexpand=true }; label.add_css_class("dim-label"); this.append(label); - label.activate_link.connect(() => { - if (badness_type == BadnessType.UNTRUSTED) { - ContactDetailsDialog dialog = new ContactDetailsDialog(plugin, conversation.account, jid); - dialog.set_transient_for((Window) get_root()); - dialog.present(); - } + if (badness_type == BadnessType.UNTRUSTED) { + label.activate_link.connect(on_label_activate_link); + } + } - return false; - }); + private bool on_label_activate_link() { + ContactDetailsDialog dialog = new ContactDetailsDialog(plugin, conversation.account, jid); + dialog.set_transient_for((Window) get_root()); + dialog.present(); + return false; + } + + public override void dispose() { + if (label != null) { + label.unparent(); + label.dispose(); + label = null; + } + base.dispose(); } } -- cgit v1.2.3-70-g09d2