Fix some memory leaks

This commit is contained in:
fiaxh 2023-02-27 23:38:31 +01:00
parent c526848098
commit fb799e3ba8
6 changed files with 143 additions and 53 deletions

View file

@ -71,9 +71,7 @@ public class ConversationItemSkeleton : Plugins.ConversationItemWidgetInterface,
ContentMetaItem? content_meta_item = item as ContentMetaItem; ContentMetaItem? content_meta_item = item as ContentMetaItem;
if (content_meta_item != null) { if (content_meta_item != null) {
reactions_controller = new ReactionsController(conversation, content_meta_item.content_item, stream_interactor); reactions_controller = new ReactionsController(conversation, content_meta_item.content_item, stream_interactor);
reactions_controller.box_activated.connect((widget) => { reactions_controller.box_activated.connect(on_reaction_box_activated);
set_widget(widget, Plugins.WidgetType.GTK4, 3);
});
reactions_controller.init(); 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() { private void update_time() {
time_label.label = get_relative_time(item.time.to_local()).to_string(); 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); stream_interactor.get_module(RosterManager.IDENTITY).disconnect(updated_roster_handler_id);
updated_roster_handler_id = 0; 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(); base.dispose();
} }
} }

View file

@ -426,6 +426,7 @@ public class ConversationView : Widget, Plugins.ConversationItemCollection, Plug
content_items.remove((ContentMetaItem)item); content_items.remove((ContentMetaItem)item);
} }
meta_items.remove(item); meta_items.remove(item);
skeleton.dispose();
} }
removed_item(item); removed_item(item);
@ -591,12 +592,19 @@ public class ConversationView : Widget, Plugins.ConversationItemCollection, Plug
private void clear() { private void clear() {
was_upper = null; was_upper = null;
was_page_size = null; was_page_size = null;
foreach (var item in content_items) {
item.dispose();
}
content_items.clear(); content_items.clear();
meta_items.clear(); meta_items.clear();
widget_order.clear(); widget_order.clear();
foreach (var skeleton in item_item_skeletons.values) {
skeleton.dispose();
}
item_item_skeletons.clear(); item_item_skeletons.clear();
foreach (Widget widget in widgets.values) { foreach (Widget widget in widgets.values) {
main.remove(widget); widget.unparent();
widget.dispose();
} }
widgets.clear(); widgets.clear();
} }

View file

@ -135,6 +135,17 @@ public class FileWidget : SizeRequestBox {
} }
return false; 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 { public class FileWidgetController : Object {

View file

@ -19,6 +19,7 @@ public class MessageMetaItem : ContentMetaItem {
private StreamInteractor stream_interactor; private StreamInteractor stream_interactor;
private MessageItem message_item; private MessageItem message_item;
public Message.Marked marked { get; set; } public Message.Marked marked { get; set; }
public Plugins.ConversationItemWidgetInterface outer = null;
MessageItemEditMode? edit_mode = null; MessageItemEditMode? edit_mode = null;
ChatTextViewController? controller = null; ChatTextViewController? controller = null;
@ -35,6 +36,8 @@ public class MessageMetaItem : ContentMetaItem {
message_item = content_item as MessageItem; message_item = content_item as MessageItem;
this.stream_interactor = stream_interactor; 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); label.activate_link.connect(on_label_activate_link);
Message message = ((MessageItem) content_item).message; 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) { 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(on_in_edit_mode_changed);
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;
}
});
outer.set_widget(label, Plugins.WidgetType.GTK4, 2); outer.set_widget(label, Plugins.WidgetType.GTK4, 2);
@ -201,7 +170,6 @@ public class MessageMetaItem : ContentMetaItem {
} }
public override Gee.List<Plugins.MessageAction>? get_item_actions(Plugins.WidgetType type) { public override Gee.List<Plugins.MessageAction>? get_item_actions(Plugins.WidgetType type) {
if (content_item as FileItem != null || this.in_edit_mode) return null;
if (in_edit_mode) return null; if (in_edit_mode) return null;
Gee.List<Plugins.MessageAction> actions = new ArrayList<Plugins.MessageAction>(); Gee.List<Plugins.MessageAction> actions = new ArrayList<Plugins.MessageAction>();
@ -224,6 +192,41 @@ public class MessageMetaItem : ContentMetaItem {
return actions; 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) { private void on_edit_send(string text) {
stream_interactor.get_module(MessageCorrection.IDENTITY).send_correction(message_item.conversation, message_item.message, text); stream_interactor.get_module(MessageCorrection.IDENTITY).send_correction(message_item.conversation, message_item.message, text);
this.in_edit_mode = false; this.in_edit_mode = false;
@ -244,6 +247,17 @@ public class MessageMetaItem : ContentMetaItem {
Dino.Application.get_default().open(new File[]{file}, ""); Dino.Application.get_default().open(new File[]{file}, "");
return true; 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")] [GtkTemplate (ui = "/im/dino/Dino/message_item_widget_edit_mode.ui")]

View file

@ -40,8 +40,14 @@ public class Dino.Ui.ViewModel.CompatDateSeparatorModel : DateSeparatorModel {
private void update_time_label() { private void update_time_label() {
date_label = get_relative_time(date); date_label = get_relative_time(date);
time_update_timeout = Timeout.add_seconds((int) get_next_time_change(), () => { time_update_timeout = set_update_time_label_timeout((int) get_next_time_change(), this);
if (time_update_timeout != 0) update_time_label(); }
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; return false;
}); });
} }

View file

@ -94,6 +94,7 @@ public class BadMessagesPopulator : Plugins.ConversationItemPopulator, Plugins.C
foreach (BadMessageItem bad_item in bad_items) { foreach (BadMessageItem bad_item in bad_items) {
item_collection.remove_item(bad_item); item_collection.remove_item(bad_item);
} }
bad_items.clear();
} }
public void init(Conversation conversation, Plugins.ConversationItemCollection item_collection, Plugins.WidgetType type) { 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(); init_state();
} }
public void close(Conversation conversation) { } public void close(Conversation conversation) {
clear_state();
}
public void populate_timespan(Conversation conversation, DateTime after, DateTime before) { } public void populate_timespan(Conversation conversation, DateTime after, DateTime before) { }
} }
@ -131,9 +134,17 @@ public class BadMessageItem : Plugins.MetaConversationItem {
} }
public class BadMessagesWidget : Box { 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) { public BadMessagesWidget(Plugin plugin, Conversation conversation, Jid jid, BadnessType badness_type) {
Object(orientation:Orientation.HORIZONTAL, spacing:5); Object(orientation:Orientation.HORIZONTAL, spacing:5);
this.plugin = plugin;
this.conversation = conversation;
this.jid = jid;
this.halign = Align.CENTER; this.halign = Align.CENTER;
this.visible = true; this.visible = true;
@ -159,19 +170,29 @@ public class BadMessagesWidget : Box {
} else { } else {
warning_text += _("%s does not trust this device. That means, you might be missing messages.").printf(who); 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"); label.add_css_class("dim-label");
this.append(label); this.append(label);
label.activate_link.connect(() => { if (badness_type == BadnessType.UNTRUSTED) {
if (badness_type == BadnessType.UNTRUSTED) { label.activate_link.connect(on_label_activate_link);
ContactDetailsDialog dialog = new ContactDetailsDialog(plugin, conversation.account, jid); }
dialog.set_transient_for((Window) get_root()); }
dialog.present();
}
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();
} }
} }