ConversationView: Split merged messages when an in-between one is added
This commit is contained in:
parent
ebf8d7ab01
commit
f3063f56b7
|
@ -64,7 +64,16 @@ public class MessageStorage : StreamInteractionModule, Object {
|
||||||
|
|
||||||
private void init_conversation(Conversation conversation) {
|
private void init_conversation(Conversation conversation) {
|
||||||
if (!messages.has_key(conversation)) {
|
if (!messages.has_key(conversation)) {
|
||||||
messages[conversation] = new Gee.TreeSet<Message>((a, b) => { return a.local_time.compare(b.local_time); });
|
messages[conversation] = new Gee.TreeSet<Message>((a, b) => {
|
||||||
|
int res = a.local_time.compare(b.local_time);
|
||||||
|
if (res == 0) {
|
||||||
|
res = a.time.compare(b.time);
|
||||||
|
}
|
||||||
|
if (res == 0) {
|
||||||
|
res = a.id - b.id > 0 ? 1 : -1;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
});
|
||||||
Gee.List<Message> db_messages = db.get_messages(conversation.counterpart, conversation.account, Util.get_message_type_for_conversation(conversation), 50, null);
|
Gee.List<Message> db_messages = db.get_messages(conversation.counterpart, conversation.account, Util.get_message_type_for_conversation(conversation), 50, null);
|
||||||
messages[conversation].add_all(db_messages);
|
messages[conversation].add_all(db_messages);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,9 +17,10 @@ public class ConversationItemSkeleton : Grid {
|
||||||
|
|
||||||
public StreamInteractor stream_interactor;
|
public StreamInteractor stream_interactor;
|
||||||
public Conversation conversation { get; set; }
|
public Conversation conversation { get; set; }
|
||||||
public Gee.List<Plugins.MetaConversationItem> items = new ArrayList<Plugins.MetaConversationItem>();
|
public ArrayList<Plugins.MetaConversationItem> items = new ArrayList<Plugins.MetaConversationItem>();
|
||||||
|
|
||||||
private Box box = new Box(Orientation.VERTICAL, 2) { visible=true };
|
private Box box = new Box(Orientation.VERTICAL, 2) { visible=true };
|
||||||
|
private HashMap<Plugins.MetaConversationItem, Widget> item_widgets = new HashMap<Plugins.MetaConversationItem, Widget>();
|
||||||
|
|
||||||
public ConversationItemSkeleton(StreamInteractor stream_interactor, Conversation conversation) {
|
public ConversationItemSkeleton(StreamInteractor stream_interactor, Conversation conversation) {
|
||||||
this.conversation = conversation;
|
this.conversation = conversation;
|
||||||
|
@ -36,11 +37,17 @@ public class ConversationItemSkeleton : Grid {
|
||||||
Widget widget = (Widget) item.get_widget(Plugins.WidgetType.GTK);
|
Widget widget = (Widget) item.get_widget(Plugins.WidgetType.GTK);
|
||||||
if (item.requires_header) {
|
if (item.requires_header) {
|
||||||
box.add(widget);
|
box.add(widget);
|
||||||
|
item_widgets[item] = widget;
|
||||||
} else {
|
} else {
|
||||||
set_title_widget(widget);
|
set_title_widget(widget);
|
||||||
}
|
}
|
||||||
item.notify["mark"].connect_after(update_received);
|
item.notify["mark"].connect_after(update_received_mark);
|
||||||
update_received();
|
update_received_mark();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove_meta_item(Plugins.MetaConversationItem item) {
|
||||||
|
box.remove(item_widgets[item]);
|
||||||
|
items.remove(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void set_title_widget(Widget w) {
|
public void set_title_widget(Widget w) {
|
||||||
|
@ -81,7 +88,7 @@ public class ConversationItemSkeleton : Grid {
|
||||||
set_title_widget(name_label);
|
set_title_widget(name_label);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void update_received() {
|
private void update_received_mark() {
|
||||||
bool all_received = true;
|
bool all_received = true;
|
||||||
bool all_read = true;
|
bool all_read = true;
|
||||||
bool all_sent = true;
|
bool all_sent = true;
|
||||||
|
|
|
@ -72,7 +72,6 @@ public class ConversationView : Box, Plugins.ConversationItemCollection {
|
||||||
|
|
||||||
public void insert_item(Plugins.MetaConversationItem item) {
|
public void insert_item(Plugins.MetaConversationItem item) {
|
||||||
lock (meta_items) {
|
lock (meta_items) {
|
||||||
meta_items.add(item);
|
|
||||||
if (!item.can_merge || !merge_back(item)) {
|
if (!item.can_merge || !merge_back(item)) {
|
||||||
insert_new(item);
|
insert_new(item);
|
||||||
}
|
}
|
||||||
|
@ -81,12 +80,17 @@ public class ConversationView : Box, Plugins.ConversationItemCollection {
|
||||||
|
|
||||||
public void remove_item(Plugins.MetaConversationItem item) {
|
public void remove_item(Plugins.MetaConversationItem item) {
|
||||||
lock (meta_items) {
|
lock (meta_items) {
|
||||||
|
ConversationItemSkeleton? skeleton = item_item_skeletons[item];
|
||||||
|
if (skeleton.items.size > 1) {
|
||||||
|
skeleton.remove_meta_item(item);
|
||||||
|
} else {
|
||||||
main.remove(widgets[item]);
|
main.remove(widgets[item]);
|
||||||
widgets.unset(item);
|
widgets.unset(item);
|
||||||
meta_items.remove(item);
|
|
||||||
item_skeletons.remove(item_item_skeletons[item]);
|
item_skeletons.remove(item_item_skeletons[item]);
|
||||||
item_item_skeletons.unset(item);
|
item_item_skeletons.unset(item);
|
||||||
}
|
}
|
||||||
|
meta_items.remove(item);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool merge_back(Plugins.MetaConversationItem item) {
|
private bool merge_back(Plugins.MetaConversationItem item) {
|
||||||
|
@ -101,7 +105,10 @@ public class ConversationView : Box, Plugins.ConversationItemCollection {
|
||||||
(item.mark == Message.Marked.WONTSEND) == (lower_start_item.mark == Message.Marked.WONTSEND)) {
|
(item.mark == Message.Marked.WONTSEND) == (lower_start_item.mark == Message.Marked.WONTSEND)) {
|
||||||
lower_skeleton.add_meta_item(item);
|
lower_skeleton.add_meta_item(item);
|
||||||
force_alloc_width(lower_skeleton, main.get_allocated_width());
|
force_alloc_width(lower_skeleton, main.get_allocated_width());
|
||||||
|
|
||||||
item_item_skeletons[item] = lower_skeleton;
|
item_item_skeletons[item] = lower_skeleton;
|
||||||
|
meta_items.add(item);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -109,13 +116,28 @@ public class ConversationView : Box, Plugins.ConversationItemCollection {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void insert_new(Plugins.MetaConversationItem item) {
|
private void insert_new(Plugins.MetaConversationItem item) {
|
||||||
|
Plugins.MetaConversationItem? lower_item = meta_items.lower(item);
|
||||||
|
|
||||||
|
// Does another skeleton need to be split?
|
||||||
|
if (lower_item != null) {
|
||||||
|
ConversationItemSkeleton lower_skeleton = item_item_skeletons[lower_item];
|
||||||
|
if (lower_skeleton.items.size > 1) {
|
||||||
|
Plugins.MetaConversationItem lower_end_item = lower_skeleton.items[lower_skeleton.items.size - 1];
|
||||||
|
if (item.sort_time.compare(lower_end_item.sort_time) < 0) {
|
||||||
|
split_at_time(lower_skeleton, item.sort_time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill datastructure
|
||||||
ConversationItemSkeleton item_skeleton = new ConversationItemSkeleton(stream_interactor, conversation);
|
ConversationItemSkeleton item_skeleton = new ConversationItemSkeleton(stream_interactor, conversation);
|
||||||
item_skeleton.add_meta_item(item);
|
item_skeleton.add_meta_item(item);
|
||||||
item_item_skeletons[item] = item_skeleton;
|
item_item_skeletons[item] = item_skeleton;
|
||||||
Plugins.MetaConversationItem? lower_item = meta_items.lower(item);
|
|
||||||
int index = lower_item != null ? item_skeletons.index_of(item_item_skeletons[lower_item]) + 1 : 0;
|
int index = lower_item != null ? item_skeletons.index_of(item_item_skeletons[lower_item]) + 1 : 0;
|
||||||
item_skeletons.insert(index, item_skeleton);
|
item_skeletons.insert(index, item_skeleton);
|
||||||
|
meta_items.add(item);
|
||||||
|
|
||||||
|
// Insert widget
|
||||||
Widget insert = item_skeleton;
|
Widget insert = item_skeleton;
|
||||||
if (animate) {
|
if (animate) {
|
||||||
Revealer revealer = new Revealer() {transition_duration = 200, transition_type = RevealerTransitionType.SLIDE_UP, visible = true};
|
Revealer revealer = new Revealer() {transition_duration = 200, transition_type = RevealerTransitionType.SLIDE_UP, visible = true};
|
||||||
|
@ -130,6 +152,7 @@ public class ConversationView : Box, Plugins.ConversationItemCollection {
|
||||||
force_alloc_width(insert, main.get_allocated_width());
|
force_alloc_width(insert, main.get_allocated_width());
|
||||||
main.reorder_child(insert, index);
|
main.reorder_child(insert, index);
|
||||||
|
|
||||||
|
// If an item from the past was added, add everything between that item and the (post-)first present item
|
||||||
if (index == 0) {
|
if (index == 0) {
|
||||||
Dino.Application app = Dino.Application.get_default();
|
Dino.Application app = Dino.Application.get_default();
|
||||||
if (item_skeletons.size == 1) {
|
if (item_skeletons.size == 1) {
|
||||||
|
@ -144,6 +167,24 @@ public class ConversationView : Box, Plugins.ConversationItemCollection {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void split_at_time(ConversationItemSkeleton split_skeleton, DateTime time) {
|
||||||
|
bool already_divided = false;
|
||||||
|
int i = 0;
|
||||||
|
while(i < split_skeleton.items.size) {
|
||||||
|
Plugins.MetaConversationItem meta_item = split_skeleton.items[i];
|
||||||
|
if (time.compare(meta_item.display_time) < 0) {
|
||||||
|
remove_item(meta_item);
|
||||||
|
if (!already_divided) {
|
||||||
|
insert_new(meta_item);
|
||||||
|
already_divided = true;
|
||||||
|
} else {
|
||||||
|
insert_item(meta_item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void on_upper_notify() {
|
private void on_upper_notify() {
|
||||||
if (was_upper == null || scrolled.vadjustment.value > was_upper - was_page_size - 1 ||
|
if (was_upper == null || scrolled.vadjustment.value > was_upper - was_page_size - 1 ||
|
||||||
scrolled.vadjustment.value > was_upper - was_page_size - 1) { // scrolled down or content smaller than page size
|
scrolled.vadjustment.value > was_upper - was_page_size - 1) { // scrolled down or content smaller than page size
|
||||||
|
|
Loading…
Reference in a new issue