~buzzert/Kordophone#9: gtk v2: Conversation selected state lost when reloading
This commit is contained in:
@@ -21,29 +21,90 @@ public class ConversationListModel : Object, ListModel
|
|||||||
|
|
||||||
public void load_conversations() {
|
public void load_conversations() {
|
||||||
try {
|
try {
|
||||||
Conversation[] conversations = Repository.get_instance().get_conversations();
|
Conversation[] new_conversations = Repository.get_instance().get_conversations();
|
||||||
|
|
||||||
// Clear existing set
|
// Create a map of old conversations for quick lookup
|
||||||
uint old_count = _conversations.size;
|
var old_conversations_map = new HashMap<string, Conversation>();
|
||||||
_conversations.clear();
|
foreach (var conv in _conversations) {
|
||||||
|
old_conversations_map[conv.guid] = conv;
|
||||||
// Notify of removal
|
|
||||||
if (old_count > 0) {
|
|
||||||
items_changed(0, old_count, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process each conversation
|
// Create a map of new conversations for quick lookup
|
||||||
uint position = 0;
|
var new_conversations_map = new HashMap<string, Conversation>();
|
||||||
|
foreach (var conv in new_conversations) {
|
||||||
for (int i = 0; i < conversations.length; i++) {
|
new_conversations_map[conv.guid] = conv;
|
||||||
var conversation = conversations[i];
|
|
||||||
_conversations.add(conversation);
|
|
||||||
position++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify of additions
|
// Find removed conversations
|
||||||
if (position > 0) {
|
var removed_positions = new ArrayList<uint>();
|
||||||
items_changed(0, 0, position);
|
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) {
|
} catch (Error e) {
|
||||||
warning("Failed to load conversations: %s", e.message);
|
warning("Failed to load conversations: %s", e.message);
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ public class ConversationListView : Adw.Bin
|
|||||||
private Adw.HeaderBar header_bar;
|
private Adw.HeaderBar header_bar;
|
||||||
private ConversationListModel conversation_model;
|
private ConversationListModel conversation_model;
|
||||||
|
|
||||||
|
private string? selected_conversation_guid = null;
|
||||||
|
private bool selection_update_queued = false;
|
||||||
|
|
||||||
public ConversationListView () {
|
public ConversationListView () {
|
||||||
container = new Adw.ToolbarView ();
|
container = new Adw.ToolbarView ();
|
||||||
set_child (container);
|
set_child (container);
|
||||||
@@ -25,7 +28,10 @@ public class ConversationListView : Adw.Bin
|
|||||||
|
|
||||||
list_box.row_selected.connect ((row) => {
|
list_box.row_selected.connect ((row) => {
|
||||||
var conversation_row = (ConversationRow?) row;
|
var conversation_row = (ConversationRow?) row;
|
||||||
conversation_selected(conversation_row != null ? conversation_row.conversation.guid : null);
|
if (conversation_row != null) {
|
||||||
|
selected_conversation_guid = conversation_row.conversation.guid;
|
||||||
|
conversation_selected(selected_conversation_guid);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
header_bar = new Adw.HeaderBar ();
|
header_bar = new Adw.HeaderBar ();
|
||||||
@@ -44,9 +50,43 @@ public class ConversationListView : Adw.Bin
|
|||||||
|
|
||||||
// Set up model and bind to list
|
// Set up model and bind to list
|
||||||
conversation_model = new ConversationListModel ();
|
conversation_model = new ConversationListModel ();
|
||||||
|
conversation_model.items_changed.connect (on_items_changed);
|
||||||
list_box.bind_model (conversation_model, create_conversation_row);
|
list_box.bind_model (conversation_model, create_conversation_row);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void on_items_changed (uint position, uint removed, uint added) {
|
||||||
|
enqueue_selection_update();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void enqueue_selection_update() {
|
||||||
|
if (selection_update_queued) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
selection_update_queued = true;
|
||||||
|
GLib.Idle.add(() => {
|
||||||
|
update_selection();
|
||||||
|
selection_update_queued = false;
|
||||||
|
return false;
|
||||||
|
}, GLib.Priority.HIGH);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void update_selection() {
|
||||||
|
// Re-select selected_conversation_guid, if it has changed.
|
||||||
|
if (selected_conversation_guid != null) {
|
||||||
|
for (uint i = 0; i < conversation_model.get_n_items(); i++) {
|
||||||
|
var conversation = (Conversation) conversation_model.get_item(i);
|
||||||
|
if (conversation.guid == selected_conversation_guid) {
|
||||||
|
var row = list_box.get_row_at_index((int)i);
|
||||||
|
if (row != null) {
|
||||||
|
list_box.select_row(row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private Widget create_conversation_row (Object item) {
|
private Widget create_conversation_row (Object item) {
|
||||||
Conversation conversation = (Conversation) item;
|
Conversation conversation = (Conversation) item;
|
||||||
return new ConversationRow (conversation);
|
return new ConversationRow (conversation);
|
||||||
|
|||||||
@@ -52,4 +52,21 @@ public class Conversation : Object {
|
|||||||
_display_name = conversation_data["display_name"].get_string();
|
_display_name = conversation_data["display_name"].get_string();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool equals(Conversation other) {
|
||||||
|
if (other == null) return false;
|
||||||
|
if (guid != other.guid) return false;
|
||||||
|
if (date != other.date) return false;
|
||||||
|
if (unread_count != other.unread_count) return false;
|
||||||
|
if (last_message_preview != other.last_message_preview) return false;
|
||||||
|
if (_display_name != other._display_name) return false;
|
||||||
|
|
||||||
|
// Compare participants arrays
|
||||||
|
if (participants.length != other.participants.length) return false;
|
||||||
|
for (int i = 0; i < participants.length; i++) {
|
||||||
|
if (participants[i] != other.participants[i]) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user