Private
Public Access
1
0
Files
Kordophone/src/conversation-list/conversation-list-model.vala

126 lines
4.7 KiB
Vala

using GLib;
using Gee;
public class ConversationListModel : Object, ListModel
{
public SortedSet<Conversation> conversations {
owned get { return _conversations.read_only_view; }
}
private SortedSet<Conversation> _conversations;
public ConversationListModel() {
_conversations = new TreeSet<Conversation>((a, b) => {
// Sort by date in descending order (newest first)
return (int)(b.date - a.date);
});
Repository.get_instance().conversations_updated.connect(load_conversations);
Repository.get_instance().messages_updated.connect(load_conversations);
}
public void load_conversations() {
try {
Conversation[] new_conversations = Repository.get_instance().get_conversations();
// Create a map of old conversations for quick lookup
var old_conversations_map = new HashMap<string, Conversation>();
foreach (var conv in _conversations) {
old_conversations_map[conv.guid] = conv;
}
// Create a map of new conversations for quick lookup
var new_conversations_map = new HashMap<string, Conversation>();
foreach (var conv in new_conversations) {
new_conversations_map[conv.guid] = conv;
}
// Find removed conversations
var removed_positions = new ArrayList<uint>();
var current_position = 0;
foreach (var old_conv in _conversations) {
if (!new_conversations_map.has_key(old_conv.guid)) {
removed_positions.add(current_position);
}
current_position++;
}
// Remove conversations in reverse order to maintain correct positions
for (int i = removed_positions.size - 1; i >= 0; i--) {
var pos = removed_positions[i];
_conversations.remove(_conversations.to_array()[pos]);
items_changed(pos, 1, 0);
}
// Find added conversations and changed conversations
var added_conversations = new ArrayList<Conversation>();
var changed_conversations = new ArrayList<Conversation>();
foreach (var new_conv in new_conversations) {
if (!old_conversations_map.has_key(new_conv.guid)) {
added_conversations.add(new_conv);
} else {
var old_conv = old_conversations_map[new_conv.guid];
if (!old_conv.equals(new_conv)) {
changed_conversations.add(new_conv);
}
}
}
// Add new conversations
foreach (var conv in added_conversations) {
_conversations.add(conv);
// Find the position by counting how many items are before this one
uint pos = 0;
foreach (var existing_conv in _conversations) {
if (existing_conv.guid == conv.guid) break;
pos++;
}
items_changed(pos, 0, 1);
}
// Update changed conversations
GLib.message("Changed conversations: %d", changed_conversations.size);
foreach (var conv in changed_conversations) {
// Find position of old conversation
uint old_pos = 0;
var old_conv = old_conversations_map[conv.guid];
foreach (var existing_conv in _conversations) {
if (existing_conv.guid == old_conv.guid) break;
old_pos++;
}
// Remove the old one
_conversations.remove(old_conv);
// Add the new one
_conversations.add(conv);
// Find the new (sorted) position
uint new_pos = 0;
foreach (var existing_conv in _conversations) {
if (existing_conv.guid == conv.guid) break;
new_pos++;
}
// Notify of the change
items_changed(old_pos, 1, 0);
items_changed(new_pos, 0, 1);
}
} catch (Error e) {
warning("Failed to load conversations: %s", e.message);
}
}
// ListModel implementation
public Type get_item_type() {
return typeof(Conversation);
}
public uint get_n_items() {
return _conversations.size;
}
public Object? get_item(uint position) {
return _conversations.to_array()[position];
}
}