Private
Public Access
1
0

Fix retain cycles

This commit is contained in:
2025-05-14 17:37:23 -07:00
parent f377bbb7f9
commit 1ed7f5bda3
4 changed files with 46 additions and 21 deletions

View File

@@ -24,6 +24,8 @@ public class Repository : DBusServiceProxy {
} }
private void connect_to_repository() { private void connect_to_repository() {
GLib.info("Connecting to repository");
try { try {
this.dbus_repository = Bus.get_proxy_sync<DBusService.Repository>(BusType.SESSION, DBUS_NAME, DBUS_PATH); this.dbus_repository = Bus.get_proxy_sync<DBusService.Repository>(BusType.SESSION, DBUS_NAME, DBUS_PATH);
this.dbus_repository.conversations_updated.connect(() => { this.dbus_repository.conversations_updated.connect(() => {

View File

@@ -5,8 +5,8 @@ public class MessageListModel : Object, ListModel
{ {
public signal void messages_changed(); public signal void messages_changed();
public SortedSet<Message> messages { public ArrayList<Message> messages {
owned get { return _messages.read_only_view; } get { return _messages; }
} }
public bool is_group_chat { public bool is_group_chat {
@@ -17,19 +17,34 @@ public class MessageListModel : Object, ListModel
public string conversation_guid { get; private set; } public string conversation_guid { get; private set; }
private SortedSet<Message> _messages; private ArrayList<Message> _messages;
private HashSet<string> participants = new HashSet<string>(); private HashSet<string> participants = new HashSet<string>();
private ulong handler_id = 0;
public MessageListModel(string conversation_guid) {
_messages = new TreeSet<Message>((a, b) => {
// Sort by date in descending order (newest first)
return a.date.compare(b.date);
});
Repository.get_instance().messages_updated.connect(got_messages_updated); public MessageListModel(string conversation_guid) {
_messages = new ArrayList<Message>();
this.conversation_guid = conversation_guid; 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() { public void load_messages() {
try { try {
Message[] messages = Repository.get_instance().get_messages(conversation_guid); Message[] messages = Repository.get_instance().get_messages(conversation_guid);
@@ -82,6 +97,6 @@ public class MessageListModel : Object, ListModel
} }
public Object? get_item(uint position) { public Object? get_item(uint position) {
return _messages.to_array()[position]; return _messages.get((int)position);
} }
} }

View File

@@ -5,7 +5,7 @@ private class TranscriptDrawingArea : Widget
{ {
public bool show_sender = true; public bool show_sender = true;
private SortedSet<Message> _messages = new TreeSet<Message>(); private ArrayList<Message> _messages = new ArrayList<Message>();
private ArrayList<ChatItemLayout> _chat_items = new ArrayList<ChatItemLayout>(); private ArrayList<ChatItemLayout> _chat_items = new ArrayList<ChatItemLayout>();
private const float bubble_margin = 18.0f; private const float bubble_margin = 18.0f;
@@ -14,7 +14,7 @@ private class TranscriptDrawingArea : Widget
add_css_class("transcript-drawing-area"); add_css_class("transcript-drawing-area");
} }
public void set_messages(SortedSet<Message> messages) { public void set_messages(ArrayList<Message> messages) {
_messages = messages; _messages = messages;
recompute_message_layouts(); recompute_message_layouts();
} }

View File

@@ -9,16 +9,25 @@ public class TranscriptView : Adw.Bin
return _model; return _model;
} }
set { set {
if (_model != null) {
_model.disconnect(messages_changed_handler_id);
_model.unwatch_updates();
}
_model = value; _model = value;
if (model != null) { if (value != null) {
// Reset scroll position // Reset scroll position
scrolled_window.vadjustment = new Gtk.Adjustment(0, 0, 0, 0, 0, 0); scrolled_window.vadjustment = new Gtk.Adjustment(0, 0, 0, 0, 0, 0);
model.messages_changed.connect(reload_messages); weak TranscriptView self = this;
model.load_messages(); messages_changed_handler_id = value.messages_changed.connect(() => {
self.reload_messages();
});
value.load_messages();
} else { } else {
transcript_drawing_area.set_messages(new TreeSet<Message>()); transcript_drawing_area.set_messages(new ArrayList<Message>());
} }
} }
} }
@@ -34,10 +43,9 @@ public class TranscriptView : Adw.Bin
private TranscriptDrawingArea transcript_drawing_area = new TranscriptDrawingArea(); private TranscriptDrawingArea transcript_drawing_area = new TranscriptDrawingArea();
private ScrolledWindow scrolled_window = new ScrolledWindow(); private ScrolledWindow scrolled_window = new ScrolledWindow();
private ulong messages_changed_handler_id = 0;
public TranscriptView(MessageListModel? model = null) { public TranscriptView() {
this.model = model;
container = new Adw.ToolbarView(); container = new Adw.ToolbarView();
set_child(container); set_child(container);