From 1ed7f5bda3eb263857d1dee6841a654ef8787f69 Mon Sep 17 00:00:00 2001 From: James Magahern Date: Wed, 14 May 2025 17:37:23 -0700 Subject: [PATCH] Fix retain cycles --- src/service/repository.vala | 2 ++ src/transcript/message-list-model.vala | 39 ++++++++++++++------- src/transcript/transcript-drawing-area.vala | 4 +-- src/transcript/transcript-view.vala | 22 ++++++++---- 4 files changed, 46 insertions(+), 21 deletions(-) diff --git a/src/service/repository.vala b/src/service/repository.vala index 0793fa8..421ca94 100644 --- a/src/service/repository.vala +++ b/src/service/repository.vala @@ -24,6 +24,8 @@ public class Repository : DBusServiceProxy { } private void connect_to_repository() { + GLib.info("Connecting to repository"); + try { this.dbus_repository = Bus.get_proxy_sync(BusType.SESSION, DBUS_NAME, DBUS_PATH); this.dbus_repository.conversations_updated.connect(() => { diff --git a/src/transcript/message-list-model.vala b/src/transcript/message-list-model.vala index 037e1f2..25c58fb 100644 --- a/src/transcript/message-list-model.vala +++ b/src/transcript/message-list-model.vala @@ -5,8 +5,8 @@ public class MessageListModel : Object, ListModel { public signal void messages_changed(); - public SortedSet messages { - owned get { return _messages.read_only_view; } + public ArrayList messages { + get { return _messages; } } public bool is_group_chat { @@ -17,19 +17,34 @@ public class MessageListModel : Object, ListModel public string conversation_guid { get; private set; } - private SortedSet _messages; + private ArrayList _messages; private HashSet participants = new HashSet(); - - public MessageListModel(string conversation_guid) { - _messages = new TreeSet((a, b) => { - // Sort by date in descending order (newest first) - return a.date.compare(b.date); - }); + private ulong handler_id = 0; - Repository.get_instance().messages_updated.connect(got_messages_updated); + public MessageListModel(string conversation_guid) { + _messages = new ArrayList(); this.conversation_guid = conversation_guid; } - + + ~MessageListModel() { + // NOTE: this won't actually get destructed automatically because of a retain cycle with the signal handler. + // unwatch_updates() should be called explicitly when the model is no longer needed. + unwatch_updates(); + } + + public void watch_updates() { + if (this.handler_id == 0) { + this.handler_id = Repository.get_instance().messages_updated.connect(got_messages_updated); + } + } + + public void unwatch_updates() { + if (this.handler_id != 0) { + Repository.get_instance().disconnect(this.handler_id); + this.handler_id = 0; + } + } + public void load_messages() { try { Message[] messages = Repository.get_instance().get_messages(conversation_guid); @@ -82,6 +97,6 @@ public class MessageListModel : Object, ListModel } public Object? get_item(uint position) { - return _messages.to_array()[position]; + return _messages.get((int)position); } } \ No newline at end of file diff --git a/src/transcript/transcript-drawing-area.vala b/src/transcript/transcript-drawing-area.vala index 497cdb1..5aa393d 100644 --- a/src/transcript/transcript-drawing-area.vala +++ b/src/transcript/transcript-drawing-area.vala @@ -5,7 +5,7 @@ private class TranscriptDrawingArea : Widget { public bool show_sender = true; - private SortedSet _messages = new TreeSet(); + private ArrayList _messages = new ArrayList(); private ArrayList _chat_items = new ArrayList(); private const float bubble_margin = 18.0f; @@ -14,7 +14,7 @@ private class TranscriptDrawingArea : Widget add_css_class("transcript-drawing-area"); } - public void set_messages(SortedSet messages) { + public void set_messages(ArrayList messages) { _messages = messages; recompute_message_layouts(); } diff --git a/src/transcript/transcript-view.vala b/src/transcript/transcript-view.vala index 127231c..4078749 100644 --- a/src/transcript/transcript-view.vala +++ b/src/transcript/transcript-view.vala @@ -9,16 +9,25 @@ public class TranscriptView : Adw.Bin return _model; } set { + if (_model != null) { + _model.disconnect(messages_changed_handler_id); + _model.unwatch_updates(); + } + _model = value; - if (model != null) { + if (value != null) { // Reset scroll position scrolled_window.vadjustment = new Gtk.Adjustment(0, 0, 0, 0, 0, 0); - model.messages_changed.connect(reload_messages); - model.load_messages(); + weak TranscriptView self = this; + messages_changed_handler_id = value.messages_changed.connect(() => { + self.reload_messages(); + }); + + value.load_messages(); } else { - transcript_drawing_area.set_messages(new TreeSet()); + transcript_drawing_area.set_messages(new ArrayList()); } } } @@ -34,10 +43,9 @@ public class TranscriptView : Adw.Bin private TranscriptDrawingArea transcript_drawing_area = new TranscriptDrawingArea(); private ScrolledWindow scrolled_window = new ScrolledWindow(); + private ulong messages_changed_handler_id = 0; - public TranscriptView(MessageListModel? model = null) { - this.model = model; - + public TranscriptView() { container = new Adw.ToolbarView(); set_child(container);