Use advertized/server/live time for sorting instead of arrival time
fixes #310
This commit is contained in:
parent
f31e96d6bb
commit
cc01374d3c
|
@ -93,10 +93,8 @@ public abstract interface NotificationPopulator : Object {
|
||||||
public abstract class MetaConversationItem : Object {
|
public abstract class MetaConversationItem : Object {
|
||||||
public virtual string populator_id { get; set; }
|
public virtual string populator_id { get; set; }
|
||||||
public virtual Jid? jid { get; set; default=null; }
|
public virtual Jid? jid { get; set; default=null; }
|
||||||
public virtual DateTime sort_time { get; set; default = new DateTime.now_utc(); }
|
public virtual DateTime time { get; set; default = new DateTime.now_utc(); }
|
||||||
public virtual long seccondary_sort_indicator { get; set; }
|
public virtual int secondary_sort_indicator { get; set; }
|
||||||
public virtual long tertiary_sort_indicator { get; set; }
|
|
||||||
public virtual DateTime? display_time { get; set; default = null; }
|
|
||||||
public virtual Encryption encryption { get; set; default = Encryption.NONE; }
|
public virtual Encryption encryption { get; set; default = Encryption.NONE; }
|
||||||
public virtual Entities.Message.Marked mark { get; set; default = Entities.Message.Marked.NONE; }
|
public virtual Entities.Message.Marked mark { get; set; default = Entities.Message.Marked.NONE; }
|
||||||
|
|
||||||
|
|
|
@ -37,11 +37,10 @@ public class ChatInteraction : StreamInteractionModule, Object {
|
||||||
if (read_up_to_item == null) return 0;
|
if (read_up_to_item == null) return 0;
|
||||||
|
|
||||||
Database db = Dino.Application.get_default().db;
|
Database db = Dino.Application.get_default().db;
|
||||||
string local_time = read_up_to_item.sort_time.to_unix().to_string();
|
string time = read_up_to_item.time.to_unix().to_string();
|
||||||
string time = read_up_to_item.display_time.to_unix().to_string();
|
|
||||||
string id = read_up_to_item.id.to_string();
|
string id = read_up_to_item.id.to_string();
|
||||||
return (int)db.content_item.select()
|
return (int)db.content_item.select()
|
||||||
.where(@"local_time > ? OR (local_time = ? AND time > ?) OR (local_time = ? AND time = ? AND id > ?)", { local_time, local_time, time, local_time, time, id })
|
.where(@"time > ? OR (time = ? AND id > ?)", { time, time, id })
|
||||||
.with(db.content_item.conversation_id, "=", conversation.id)
|
.with(db.content_item.conversation_id, "=", conversation.id)
|
||||||
.with(db.content_item.hide, "=", false)
|
.with(db.content_item.hide, "=", false)
|
||||||
.count();
|
.count();
|
||||||
|
|
|
@ -46,14 +46,12 @@ public class ContentItemStore : StreamInteractionModule, Object {
|
||||||
int provider = row[db.content_item.content_type];
|
int provider = row[db.content_item.content_type];
|
||||||
int foreign_id = row[db.content_item.foreign_id];
|
int foreign_id = row[db.content_item.foreign_id];
|
||||||
DateTime time = new DateTime.from_unix_utc(row[db.content_item.time]);
|
DateTime time = new DateTime.from_unix_utc(row[db.content_item.time]);
|
||||||
DateTime local_time = new DateTime.from_unix_utc(row[db.content_item.local_time]);
|
|
||||||
switch (provider) {
|
switch (provider) {
|
||||||
case 1:
|
case 1:
|
||||||
Message? message = stream_interactor.get_module(MessageStorage.IDENTITY).get_message_by_id(foreign_id, conversation);
|
Message? message = stream_interactor.get_module(MessageStorage.IDENTITY).get_message_by_id(foreign_id, conversation);
|
||||||
if (message != null) {
|
if (message != null) {
|
||||||
var message_item = new MessageItem(message, conversation, row[db.content_item.id]);
|
var message_item = new MessageItem(message, conversation, row[db.content_item.id]);
|
||||||
message_item.display_time = time;
|
message_item.time = time;
|
||||||
message_item.sort_time = local_time;
|
|
||||||
items.add(message_item);
|
items.add(message_item);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -122,36 +120,34 @@ public class ContentItemStore : StreamInteractionModule, Object {
|
||||||
QueryBuilder select = db.content_item.select()
|
QueryBuilder select = db.content_item.select()
|
||||||
.with(db.content_item.conversation_id, "=", conversation.id)
|
.with(db.content_item.conversation_id, "=", conversation.id)
|
||||||
.with(db.content_item.hide, "=", false)
|
.with(db.content_item.hide, "=", false)
|
||||||
.order_by(db.content_item.local_time, "DESC")
|
|
||||||
.order_by(db.content_item.time, "DESC")
|
.order_by(db.content_item.time, "DESC")
|
||||||
|
.order_by(db.content_item.id, "DESC")
|
||||||
.limit(count);
|
.limit(count);
|
||||||
|
|
||||||
return get_items_from_query(select, conversation);
|
return get_items_from_query(select, conversation);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Gee.List<ContentItem> get_before(Conversation conversation, ContentItem item, int count) {
|
public Gee.List<ContentItem> get_before(Conversation conversation, ContentItem item, int count) {
|
||||||
long local_time = (long) item.sort_time.to_unix();
|
long time = (long) item.time.to_unix();
|
||||||
long time = (long) item.display_time.to_unix();
|
|
||||||
QueryBuilder select = db.content_item.select()
|
QueryBuilder select = db.content_item.select()
|
||||||
.where(@"local_time < ? OR (local_time = ? AND time < ?) OR (local_time = ? AND time = ? AND id < ?)", { local_time.to_string(), local_time.to_string(), time.to_string(), local_time.to_string(), time.to_string(), item.id.to_string() })
|
.where(@"time < ? OR (time = ? AND id < ?)", { time.to_string(), time.to_string(), item.id.to_string() })
|
||||||
.with(db.content_item.conversation_id, "=", conversation.id)
|
.with(db.content_item.conversation_id, "=", conversation.id)
|
||||||
.with(db.content_item.hide, "=", false)
|
.with(db.content_item.hide, "=", false)
|
||||||
.order_by(db.content_item.local_time, "DESC")
|
|
||||||
.order_by(db.content_item.time, "DESC")
|
.order_by(db.content_item.time, "DESC")
|
||||||
|
.order_by(db.content_item.id, "DESC")
|
||||||
.limit(count);
|
.limit(count);
|
||||||
|
|
||||||
return get_items_from_query(select, conversation);
|
return get_items_from_query(select, conversation);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Gee.List<ContentItem> get_after(Conversation conversation, ContentItem item, int count) {
|
public Gee.List<ContentItem> get_after(Conversation conversation, ContentItem item, int count) {
|
||||||
long local_time = (long) item.sort_time.to_unix();
|
long time = (long) item.time.to_unix();
|
||||||
long time = (long) item.display_time.to_unix();
|
|
||||||
QueryBuilder select = db.content_item.select()
|
QueryBuilder select = db.content_item.select()
|
||||||
.where(@"local_time > ? OR (local_time = ? AND time > ?) OR (local_time = ? AND time = ? AND id > ?)", { local_time.to_string(), local_time.to_string(), time.to_string(), local_time.to_string(), time.to_string(), item.id.to_string() })
|
.where(@"time > ? OR (time = ? AND id > ?)", { time.to_string(), time.to_string(), item.id.to_string() })
|
||||||
.with(db.content_item.conversation_id, "=", conversation.id)
|
.with(db.content_item.conversation_id, "=", conversation.id)
|
||||||
.with(db.content_item.hide, "=", false)
|
.with(db.content_item.hide, "=", false)
|
||||||
.order_by(db.content_item.local_time, "ASC")
|
|
||||||
.order_by(db.content_item.time, "ASC")
|
.order_by(db.content_item.time, "ASC")
|
||||||
|
.order_by(db.content_item.id, "ASC")
|
||||||
.limit(count);
|
.limit(count);
|
||||||
|
|
||||||
return get_items_from_query(select, conversation);
|
return get_items_from_query(select, conversation);
|
||||||
|
@ -228,17 +224,15 @@ public abstract class ContentItem : Object {
|
||||||
public int id { get; set; }
|
public int id { get; set; }
|
||||||
public string type_ { get; set; }
|
public string type_ { get; set; }
|
||||||
public Jid jid { get; set; }
|
public Jid jid { get; set; }
|
||||||
public DateTime sort_time { get; set; }
|
public DateTime time { get; set; }
|
||||||
public DateTime display_time { get; set; }
|
|
||||||
public Encryption encryption { get; set; }
|
public Encryption encryption { get; set; }
|
||||||
public Entities.Message.Marked mark { get; set; }
|
public Entities.Message.Marked mark { get; set; }
|
||||||
|
|
||||||
ContentItem(int id, string ty, Jid jid, DateTime sort_time, DateTime display_time, Encryption encryption, Entities.Message.Marked mark) {
|
ContentItem(int id, string ty, Jid jid, DateTime time, Encryption encryption, Entities.Message.Marked mark) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.type_ = ty;
|
this.type_ = ty;
|
||||||
this.jid = jid;
|
this.jid = jid;
|
||||||
this.sort_time = sort_time;
|
this.time = time;
|
||||||
this.display_time = display_time;
|
|
||||||
this.encryption = encryption;
|
this.encryption = encryption;
|
||||||
this.mark = mark;
|
this.mark = mark;
|
||||||
}
|
}
|
||||||
|
@ -248,10 +242,7 @@ public abstract class ContentItem : Object {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int compare_func(ContentItem a, ContentItem b) {
|
public static int compare_func(ContentItem a, ContentItem b) {
|
||||||
int res = a.sort_time.compare(b.sort_time);
|
int res = a.time.compare(b.time);
|
||||||
if (res == 0) {
|
|
||||||
res = a.display_time.compare(b.display_time);
|
|
||||||
}
|
|
||||||
if (res == 0) {
|
if (res == 0) {
|
||||||
res = a.id - b.id > 0 ? 1 : -1;
|
res = a.id - b.id > 0 ? 1 : -1;
|
||||||
}
|
}
|
||||||
|
@ -266,7 +257,7 @@ public class MessageItem : ContentItem {
|
||||||
public Conversation conversation;
|
public Conversation conversation;
|
||||||
|
|
||||||
public MessageItem(Message message, Conversation conversation, int id) {
|
public MessageItem(Message message, Conversation conversation, int id) {
|
||||||
base(id, TYPE, message.from, message.local_time, message.time, message.encryption, message.marked);
|
base(id, TYPE, message.from, message.time, message.encryption, message.marked);
|
||||||
|
|
||||||
this.message = message;
|
this.message = message;
|
||||||
this.conversation = conversation;
|
this.conversation = conversation;
|
||||||
|
@ -287,7 +278,7 @@ public class FileItem : ContentItem {
|
||||||
} else if (file_transfer.direction == FileTransfer.DIRECTION_SENT) {
|
} else if (file_transfer.direction == FileTransfer.DIRECTION_SENT) {
|
||||||
mark = file_to_message_state(file_transfer.state);
|
mark = file_to_message_state(file_transfer.state);
|
||||||
}
|
}
|
||||||
base(id, TYPE, file_transfer.from, file_transfer.local_time, file_transfer.time, file_transfer.encryption, mark);
|
base(id, TYPE, file_transfer.from, file_transfer.time, file_transfer.encryption, mark);
|
||||||
|
|
||||||
this.file_transfer = file_transfer;
|
this.file_transfer = file_transfer;
|
||||||
this.conversation = conversation;
|
this.conversation = conversation;
|
||||||
|
|
|
@ -177,7 +177,7 @@ public class ConversationManager : StreamInteractionModule, Object {
|
||||||
|
|
||||||
if (stanza != null) {
|
if (stanza != null) {
|
||||||
bool is_mam_message = Xep.MessageArchiveManagement.MessageFlag.get_flag(stanza) != null;
|
bool is_mam_message = Xep.MessageArchiveManagement.MessageFlag.get_flag(stanza) != null;
|
||||||
bool is_recent = message.local_time.compare(new DateTime.now_utc().add_days(-3)) > 0;
|
bool is_recent = message.time.compare(new DateTime.now_utc().add_days(-3)) > 0;
|
||||||
if (is_mam_message && !is_recent) return false;
|
if (is_mam_message && !is_recent) return false;
|
||||||
}
|
}
|
||||||
stream_interactor.get_module(ConversationManager.IDENTITY).start_conversation(conversation);
|
stream_interactor.get_module(ConversationManager.IDENTITY).start_conversation(conversation);
|
||||||
|
@ -188,7 +188,7 @@ public class ConversationManager : StreamInteractionModule, Object {
|
||||||
private void handle_sent_message(Entities.Message message, Conversation conversation) {
|
private void handle_sent_message(Entities.Message message, Conversation conversation) {
|
||||||
conversation.last_active = message.time;
|
conversation.last_active = message.time;
|
||||||
|
|
||||||
bool is_recent = message.local_time.compare(new DateTime.now_utc().add_hours(-24)) > 0;
|
bool is_recent = message.time.compare(new DateTime.now_utc().add_hours(-24)) > 0;
|
||||||
if (is_recent) {
|
if (is_recent) {
|
||||||
start_conversation(conversation);
|
start_conversation(conversation);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ using Dino.Entities;
|
||||||
namespace Dino {
|
namespace Dino {
|
||||||
|
|
||||||
public class Database : Qlite.Database {
|
public class Database : Qlite.Database {
|
||||||
private const int VERSION = 17;
|
private const int VERSION = 18;
|
||||||
|
|
||||||
public class AccountTable : Table {
|
public class AccountTable : Table {
|
||||||
public Column<int> id = new Column.Integer("id") { primary_key = true, auto_increment = true };
|
public Column<int> id = new Column.Integer("id") { primary_key = true, auto_increment = true };
|
||||||
|
@ -62,7 +62,7 @@ public class Database : Qlite.Database {
|
||||||
internal ContentItemTable(Database db) {
|
internal ContentItemTable(Database db) {
|
||||||
base(db, "content_item");
|
base(db, "content_item");
|
||||||
init({id, conversation_id, time, local_time, content_type, foreign_id, hide});
|
init({id, conversation_id, time, local_time, content_type, foreign_id, hide});
|
||||||
index("contentitem_conversation_hide_localtime_time_idx", {conversation_id, hide, local_time, time});
|
index("contentitem_conversation_hide_time_idx", {conversation_id, hide, time});
|
||||||
unique({content_type, foreign_id}, "IGNORE");
|
unique({content_type, foreign_id}, "IGNORE");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,7 @@ public class Database : Qlite.Database {
|
||||||
type_, time, local_time, body, encryption, marked});
|
type_, time, local_time, body, encryption, marked});
|
||||||
|
|
||||||
// get latest messages
|
// get latest messages
|
||||||
index("message_account_counterpart_localtime_idx", {account_id, counterpart_id, local_time});
|
index("message_account_counterpart_time_idx", {account_id, counterpart_id, time});
|
||||||
|
|
||||||
// deduplication
|
// deduplication
|
||||||
index("message_account_counterpart_stanzaid_idx", {account_id, counterpart_id, stanza_id});
|
index("message_account_counterpart_stanzaid_idx", {account_id, counterpart_id, stanza_id});
|
||||||
|
@ -152,7 +152,6 @@ public class Database : Qlite.Database {
|
||||||
base(db, "file_transfer");
|
base(db, "file_transfer");
|
||||||
init({id, account_id, counterpart_id, counterpart_resource, our_resource, direction, time, local_time,
|
init({id, account_id, counterpart_id, counterpart_resource, our_resource, direction, time, local_time,
|
||||||
encryption, file_name, path, mime_type, size, state, provider, info});
|
encryption, file_name, path, mime_type, size, state, provider, info});
|
||||||
index("filetransfer_localtime_counterpart_idx", {local_time, counterpart_id});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -398,6 +397,19 @@ public class Database : Qlite.Database {
|
||||||
error("Failed to upgrade to database version 17: %s", e.message);
|
error("Failed to upgrade to database version 17: %s", e.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (oldVersion < 18) {
|
||||||
|
try {
|
||||||
|
exec("DROP INDEX contentitem_conversation_hide_localtime_time_idx");
|
||||||
|
exec("CREATE INDEX contentitem_conversation_hide_time_idx ON content_item (conversation_id, hide, time)");
|
||||||
|
|
||||||
|
exec("DROP INDEX message_account_counterpart_localtime_idx");
|
||||||
|
exec("CREATE INDEX message_account_counterpart_time_idx ON message (account_id, counterpart_id, time)");
|
||||||
|
|
||||||
|
exec("DROP INDEX filetransfer_localtime_counterpart_idx");
|
||||||
|
} catch (Error e) {
|
||||||
|
error("Failed to upgrade to database version 18: %s", e.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArrayList<Account> get_accounts() {
|
public ArrayList<Account> get_accounts() {
|
||||||
|
@ -448,22 +460,22 @@ public class Database : Qlite.Database {
|
||||||
|
|
||||||
if (before != null) {
|
if (before != null) {
|
||||||
if (id > 0) {
|
if (id > 0) {
|
||||||
select.where(@"local_time < ? OR (local_time = ? AND message.id < ?)", { before.to_unix().to_string(), before.to_unix().to_string(), id.to_string() });
|
select.where(@"time < ? OR (time = ? AND message.id < ?)", { before.to_unix().to_string(), before.to_unix().to_string(), id.to_string() });
|
||||||
} else {
|
} else {
|
||||||
select.with(message.id, "<", id);
|
select.with(message.id, "<", id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (after != null) {
|
if (after != null) {
|
||||||
if (id > 0) {
|
if (id > 0) {
|
||||||
select.where(@"local_time > ? OR (local_time = ? AND message.id > ?)", { after.to_unix().to_string(), after.to_unix().to_string(), id.to_string() });
|
select.where(@"time > ? OR (time = ? AND message.id > ?)", { after.to_unix().to_string(), after.to_unix().to_string(), id.to_string() });
|
||||||
} else {
|
} else {
|
||||||
select.with(message.local_time, ">", (long) after.to_unix());
|
select.with(message.time, ">", (long) after.to_unix());
|
||||||
}
|
}
|
||||||
if (id > 0) {
|
if (id > 0) {
|
||||||
select.with(message.id, ">", id);
|
select.with(message.id, ">", id);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
select.order_by(message.local_time, "DESC");
|
select.order_by(message.time, "DESC");
|
||||||
}
|
}
|
||||||
|
|
||||||
select.with(message.counterpart_id, "=", get_jid_id(jid))
|
select.with(message.counterpart_id, "=", get_jid_id(jid))
|
||||||
|
|
|
@ -149,47 +149,6 @@ public class FileManager : StreamInteractionModule, Object {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Gee.List<FileTransfer> get_latest_transfers(Account account, Jid counterpart, int n) {
|
|
||||||
Qlite.QueryBuilder select = db.file_transfer.select()
|
|
||||||
.with(db.file_transfer.counterpart_id, "=", db.get_jid_id(counterpart))
|
|
||||||
.with(db.file_transfer.account_id, "=", account.id)
|
|
||||||
.order_by(db.file_transfer.local_time, "DESC")
|
|
||||||
.limit(n);
|
|
||||||
return get_transfers_from_qry(select);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Gee.List<FileTransfer> get_transfers_before(Account account, Jid counterpart, DateTime before, int n) {
|
|
||||||
Qlite.QueryBuilder select = db.file_transfer.select()
|
|
||||||
.with(db.file_transfer.counterpart_id, "=", db.get_jid_id(counterpart))
|
|
||||||
.with(db.file_transfer.account_id, "=", account.id)
|
|
||||||
.with(db.file_transfer.local_time, "<", (long)before.to_unix())
|
|
||||||
.order_by(db.file_transfer.local_time, "DESC")
|
|
||||||
.limit(n);
|
|
||||||
return get_transfers_from_qry(select);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Gee.List<FileTransfer> get_transfers_after(Account account, Jid counterpart, DateTime after, int n) {
|
|
||||||
Qlite.QueryBuilder select = db.file_transfer.select()
|
|
||||||
.with(db.file_transfer.counterpart_id, "=", db.get_jid_id(counterpart))
|
|
||||||
.with(db.file_transfer.account_id, "=", account.id)
|
|
||||||
.with(db.file_transfer.local_time, ">", (long)after.to_unix())
|
|
||||||
.limit(n);
|
|
||||||
return get_transfers_from_qry(select);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Gee.List<FileTransfer> get_transfers_from_qry(Qlite.QueryBuilder select) {
|
|
||||||
Gee.List<FileTransfer> ret = new ArrayList<FileTransfer>();
|
|
||||||
foreach (Qlite.Row row in select) {
|
|
||||||
try {
|
|
||||||
FileTransfer file_transfer = new FileTransfer.from_row(db, row, get_storage_dir());
|
|
||||||
ret.insert(0, file_transfer);
|
|
||||||
} catch (InvalidJidError e) {
|
|
||||||
warning("Ignoring file transfer with invalid Jid: %s", e.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void add_provider(FileProvider file_provider) {
|
public void add_provider(FileProvider file_provider) {
|
||||||
file_providers.add(file_provider);
|
file_providers.add(file_provider);
|
||||||
file_provider.file_incoming.connect((info, from, time, local_time, conversation, receive_data, file_meta) => {
|
file_provider.file_incoming.connect((info, from, time, local_time, conversation, receive_data, file_meta) => {
|
||||||
|
|
|
@ -40,7 +40,6 @@ public class MessageStorage : StreamInteractionModule, Object {
|
||||||
.with(db.message.account_id, "=", conversation.account.id)
|
.with(db.message.account_id, "=", conversation.account.id)
|
||||||
.with(db.message.counterpart_id, "=", db.get_jid_id(conversation.counterpart))
|
.with(db.message.counterpart_id, "=", db.get_jid_id(conversation.counterpart))
|
||||||
.with(db.message.type_, "=", (int) Util.get_message_type_for_conversation(conversation))
|
.with(db.message.type_, "=", (int) Util.get_message_type_for_conversation(conversation))
|
||||||
.order_by(db.message.local_time, "DESC")
|
|
||||||
.order_by(db.message.time, "DESC")
|
.order_by(db.message.time, "DESC")
|
||||||
.outer_join_with(db.message_correction, db.message_correction.message_id, db.message.id)
|
.outer_join_with(db.message_correction, db.message_correction.message_id, db.message.id)
|
||||||
.limit(count);
|
.limit(count);
|
||||||
|
@ -111,7 +110,6 @@ public class MessageStorage : StreamInteractionModule, Object {
|
||||||
.with(db.message.counterpart_id, "=", db.get_jid_id(conversation.counterpart))
|
.with(db.message.counterpart_id, "=", db.get_jid_id(conversation.counterpart))
|
||||||
.with(db.message.type_, "=", (int) Util.get_message_type_for_conversation(conversation))
|
.with(db.message.type_, "=", (int) Util.get_message_type_for_conversation(conversation))
|
||||||
.with(db.message.stanza_id, "=", stanza_id)
|
.with(db.message.stanza_id, "=", stanza_id)
|
||||||
.order_by(db.message.local_time, "DESC")
|
|
||||||
.order_by(db.message.time, "DESC")
|
.order_by(db.message.time, "DESC")
|
||||||
.outer_join_with(db.message_correction, db.message_correction.message_id, db.message.id);
|
.outer_join_with(db.message_correction, db.message_correction.message_id, db.message.id);
|
||||||
|
|
||||||
|
@ -139,7 +137,6 @@ public class MessageStorage : StreamInteractionModule, Object {
|
||||||
.with(db.message.counterpart_id, "=", db.get_jid_id(conversation.counterpart))
|
.with(db.message.counterpart_id, "=", db.get_jid_id(conversation.counterpart))
|
||||||
.with(db.message.type_, "=", (int) Util.get_message_type_for_conversation(conversation))
|
.with(db.message.type_, "=", (int) Util.get_message_type_for_conversation(conversation))
|
||||||
.with(db.message.server_id, "=", server_id)
|
.with(db.message.server_id, "=", server_id)
|
||||||
.order_by(db.message.local_time, "DESC")
|
|
||||||
.order_by(db.message.time, "DESC")
|
.order_by(db.message.time, "DESC")
|
||||||
.outer_join_with(db.message_correction, db.message_correction.message_id, db.message.id);
|
.outer_join_with(db.message_correction, db.message_correction.message_id, db.message.id);
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,7 @@ class ChatStatePopulator : Plugins.ConversationItemPopulator, Plugins.Conversati
|
||||||
}
|
}
|
||||||
|
|
||||||
private class MetaChatStateItem : Plugins.MetaConversationItem {
|
private class MetaChatStateItem : Plugins.MetaConversationItem {
|
||||||
public override DateTime sort_time { get; set; default=new DateTime.now_utc().add_years(10); }
|
public override DateTime time { get; set; default=new DateTime.now_utc().add_years(10); }
|
||||||
|
|
||||||
private StreamInteractor stream_interactor;
|
private StreamInteractor stream_interactor;
|
||||||
private Conversation conversation;
|
private Conversation conversation;
|
||||||
|
|
|
@ -79,10 +79,8 @@ public abstract class ContentMetaItem : Plugins.MetaConversationItem {
|
||||||
|
|
||||||
protected ContentMetaItem(ContentItem content_item) {
|
protected ContentMetaItem(ContentItem content_item) {
|
||||||
this.jid = content_item.jid;
|
this.jid = content_item.jid;
|
||||||
this.sort_time = content_item.sort_time;
|
this.time = content_item.time;
|
||||||
this.seccondary_sort_indicator = (long) content_item.display_time.to_unix();
|
this.secondary_sort_indicator = content_item.id;
|
||||||
this.tertiary_sort_indicator = content_item.id;
|
|
||||||
this.display_time = content_item.display_time;
|
|
||||||
this.encryption = content_item.encryption;
|
this.encryption = content_item.encryption;
|
||||||
this.mark = content_item.mark;
|
this.mark = content_item.mark;
|
||||||
|
|
||||||
|
|
|
@ -146,7 +146,7 @@ public class ItemMetaDataHeader : Box {
|
||||||
|
|
||||||
this.add(received_image);
|
this.add(received_image);
|
||||||
|
|
||||||
if (item.display_time != null) {
|
if (item.time != null) {
|
||||||
update_time();
|
update_time();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,7 +170,7 @@ public class ItemMetaDataHeader : Box {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void update_time() {
|
private void update_time() {
|
||||||
time_label.label = get_relative_time(item.display_time.to_local()).to_string();
|
time_label.label = get_relative_time(item.time.to_local()).to_string();
|
||||||
|
|
||||||
time_update_timeout = Timeout.add_seconds((int) get_next_time_change(), () => {
|
time_update_timeout = Timeout.add_seconds((int) get_next_time_change(), () => {
|
||||||
if (this.parent == null) return false;
|
if (this.parent == null) return false;
|
||||||
|
@ -226,7 +226,7 @@ public class ItemMetaDataHeader : Box {
|
||||||
|
|
||||||
private int get_next_time_change() {
|
private int get_next_time_change() {
|
||||||
DateTime now = new DateTime.now_local();
|
DateTime now = new DateTime.now_local();
|
||||||
DateTime item_time = item.display_time;
|
DateTime item_time = item.time;
|
||||||
TimeSpan timespan = now.difference(item_time);
|
TimeSpan timespan = now.difference(item_time);
|
||||||
|
|
||||||
if (timespan < 10 * TimeSpan.MINUTE) {
|
if (timespan < 10 * TimeSpan.MINUTE) {
|
||||||
|
|
|
@ -293,8 +293,8 @@ public class ConversationView : Box, Plugins.ConversationItemCollection, Plugins
|
||||||
|
|
||||||
public void insert_item(Plugins.MetaConversationItem item) {
|
public void insert_item(Plugins.MetaConversationItem item) {
|
||||||
if (meta_items.size > 0) {
|
if (meta_items.size > 0) {
|
||||||
bool after_last = meta_items.last().sort_time.compare(item.sort_time) <= 0;
|
bool after_last = meta_items.last().time.compare(item.time) <= 0;
|
||||||
bool within_range = meta_items.last().sort_time.compare(item.sort_time) > 0 && meta_items.first().sort_time.compare(item.sort_time) < 0;
|
bool within_range = meta_items.last().time.compare(item.time) > 0 && meta_items.first().time.compare(item.time) < 0;
|
||||||
bool accept = within_range || (at_current_content && after_last);
|
bool accept = within_range || (at_current_content && after_last);
|
||||||
if (!accept) {
|
if (!accept) {
|
||||||
return;
|
return;
|
||||||
|
@ -398,11 +398,11 @@ public class ConversationView : Box, Plugins.ConversationItemCollection, Plugins
|
||||||
Dino.Application app = Dino.Application.get_default();
|
Dino.Application app = Dino.Application.get_default();
|
||||||
if (item_skeletons.size == 1) {
|
if (item_skeletons.size == 1) {
|
||||||
foreach (Plugins.ConversationAdditionPopulator populator in app.plugin_registry.conversation_addition_populators) {
|
foreach (Plugins.ConversationAdditionPopulator populator in app.plugin_registry.conversation_addition_populators) {
|
||||||
populator.populate_timespan(conversation, item.sort_time, new DateTime.now_utc());
|
populator.populate_timespan(conversation, item.time, new DateTime.now_utc());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
foreach (Plugins.ConversationAdditionPopulator populator in app.plugin_registry.conversation_addition_populators) {
|
foreach (Plugins.ConversationAdditionPopulator populator in app.plugin_registry.conversation_addition_populators) {
|
||||||
populator.populate_timespan(conversation, item.sort_time, meta_items.higher(item).sort_time);
|
populator.populate_timespan(conversation, item.time, meta_items.higher(item).time);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -410,8 +410,8 @@ public class ConversationView : Box, Plugins.ConversationItemCollection, Plugins
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool can_merge(Plugins.MetaConversationItem upper_item /*more recent, displayed below*/, Plugins.MetaConversationItem lower_item /*less recent, displayed above*/) {
|
private bool can_merge(Plugins.MetaConversationItem upper_item /*more recent, displayed below*/, Plugins.MetaConversationItem lower_item /*less recent, displayed above*/) {
|
||||||
return upper_item.display_time != null && lower_item.display_time != null &&
|
return upper_item.time != null && lower_item.time != null &&
|
||||||
upper_item.display_time.difference(lower_item.display_time) < TimeSpan.MINUTE &&
|
upper_item.time.difference(lower_item.time) < TimeSpan.MINUTE &&
|
||||||
upper_item.jid != null && lower_item.jid != null &&
|
upper_item.jid != null && lower_item.jid != null &&
|
||||||
upper_item.jid.equals(lower_item.jid) &&
|
upper_item.jid.equals(lower_item.jid) &&
|
||||||
upper_item.encryption == lower_item.encryption &&
|
upper_item.encryption == lower_item.encryption &&
|
||||||
|
@ -470,15 +470,10 @@ public class ConversationView : Box, Plugins.ConversationItemCollection, Plugins
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int compare_meta_items(Plugins.MetaConversationItem a, Plugins.MetaConversationItem b) {
|
private static int compare_meta_items(Plugins.MetaConversationItem a, Plugins.MetaConversationItem b) {
|
||||||
int cmp1 = a.sort_time.compare(b.sort_time);
|
int cmp1 = a.time.compare(b.time);
|
||||||
if (cmp1 == 0) {
|
if (cmp1 != 0) return cmp1;
|
||||||
double cmp2 = a.seccondary_sort_indicator - b.seccondary_sort_indicator;
|
|
||||||
if (cmp2 == 0) {
|
return a.secondary_sort_indicator - b.secondary_sort_indicator;
|
||||||
return (int) (a.tertiary_sort_indicator - b.tertiary_sort_indicator);
|
|
||||||
}
|
|
||||||
return (int) cmp2;
|
|
||||||
}
|
|
||||||
return cmp1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void clear() {
|
private void clear() {
|
||||||
|
|
|
@ -38,7 +38,7 @@ class DateSeparatorPopulator : Plugins.ConversationItemPopulator, Plugins.Conver
|
||||||
private void on_inserted_item(Plugins.MetaConversationItem item) {
|
private void on_inserted_item(Plugins.MetaConversationItem item) {
|
||||||
if (!(item is ContentMetaItem)) return;
|
if (!(item is ContentMetaItem)) return;
|
||||||
|
|
||||||
DateTime time = item.sort_time.to_local();
|
DateTime time = item.time.to_local();
|
||||||
DateTime msg_date = new DateTime.local(time.get_year(), time.get_month(), time.get_day_of_month(), 0, 0, 0);
|
DateTime msg_date = new DateTime.local(time.get_year(), time.get_month(), time.get_day_of_month(), 0, 0, 0);
|
||||||
if (!insert_times.contains(msg_date)) {
|
if (!insert_times.contains(msg_date)) {
|
||||||
if (insert_times.lower(msg_date) != null) {
|
if (insert_times.lower(msg_date) != null) {
|
||||||
|
@ -52,13 +52,13 @@ class DateSeparatorPopulator : Plugins.ConversationItemPopulator, Plugins.Conver
|
||||||
}
|
}
|
||||||
|
|
||||||
public class MetaDateItem : Plugins.MetaConversationItem {
|
public class MetaDateItem : Plugins.MetaConversationItem {
|
||||||
public override DateTime sort_time { get; set; }
|
public override DateTime time { get; set; }
|
||||||
|
|
||||||
private DateTime date;
|
private DateTime date;
|
||||||
|
|
||||||
public MetaDateItem(DateTime date) {
|
public MetaDateItem(DateTime date) {
|
||||||
this.date = date;
|
this.date = date;
|
||||||
this.sort_time = date;
|
this.time = date;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Object? get_widget(Plugins.WidgetType widget_type) {
|
public override Object? get_widget(Plugins.WidgetType widget_type) {
|
||||||
|
|
|
@ -190,7 +190,7 @@ public class MessageItemWidget : SizeRequestBin {
|
||||||
|
|
||||||
// Append "pending..." iff message has not been sent yet
|
// Append "pending..." iff message has not been sent yet
|
||||||
if (message.direction == Message.DIRECTION_SENT && (message.marked == Message.Marked.SENDING || message.marked == Message.Marked.UNSENT)) {
|
if (message.direction == Message.DIRECTION_SENT && (message.marked == Message.Marked.SENDING || message.marked == Message.Marked.UNSENT)) {
|
||||||
if (message.local_time.compare(new DateTime.now_utc().add_seconds(-10)) < 0) {
|
if (message.time.compare(new DateTime.now_utc().add_seconds(-10)) < 0) {
|
||||||
markup_text += " <span size='small' color='%s'>%s</span>".printf(gray_color, "pending…");
|
markup_text += " <span size='small' color='%s'>%s</span>".printf(gray_color, "pending…");
|
||||||
|
|
||||||
// Update the label as soon as the sent state changes
|
// Update the label as soon as the sent state changes
|
||||||
|
@ -201,7 +201,7 @@ public class MessageItemWidget : SizeRequestBin {
|
||||||
update_label();
|
update_label();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
int time_diff = (- (int) message.local_time.difference(new DateTime.now_utc()) / 1000);
|
int time_diff = (- (int) message.time.difference(new DateTime.now_utc()) / 1000);
|
||||||
Timeout.add(10000 - time_diff, () => {
|
Timeout.add(10000 - time_diff, () => {
|
||||||
update_label();
|
update_label();
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -138,7 +138,7 @@ public class ConversationSelectorRow : ListBoxRow {
|
||||||
protected void update_time_label(DateTime? new_time = null) {
|
protected void update_time_label(DateTime? new_time = null) {
|
||||||
if (last_content_item != null) {
|
if (last_content_item != null) {
|
||||||
time_label.visible = true;
|
time_label.visible = true;
|
||||||
time_label.label = get_relative_time(last_content_item.display_time.to_local());
|
time_label.label = get_relative_time(last_content_item.time.to_local());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -146,8 +146,8 @@ public class GlobalSearch : Overlay {
|
||||||
|
|
||||||
private void append_messages(Gee.List<MessageItem> messages) {
|
private void append_messages(Gee.List<MessageItem> messages) {
|
||||||
foreach (MessageItem item in messages) {
|
foreach (MessageItem item in messages) {
|
||||||
Gee.List<MessageItem> before_message = stream_interactor.get_module(MessageStorage.IDENTITY).get_messages_before_message(item.conversation, item.message.local_time, item.message.id, 1);
|
Gee.List<MessageItem> before_message = stream_interactor.get_module(MessageStorage.IDENTITY).get_messages_before_message(item.conversation, item.message.time, item.message.id, 1);
|
||||||
Gee.List<MessageItem> after_message = stream_interactor.get_module(MessageStorage.IDENTITY).get_messages_after_message(item.conversation, item.message.local_time, item.message.id, 1);
|
Gee.List<MessageItem> after_message = stream_interactor.get_module(MessageStorage.IDENTITY).get_messages_after_message(item.conversation, item.message.time, item.message.id, 1);
|
||||||
|
|
||||||
Box context_box = new Box(Orientation.VERTICAL, 5) { visible=true };
|
Box context_box = new Box(Orientation.VERTICAL, 5) { visible=true };
|
||||||
if (before_message != null && before_message.size > 0) {
|
if (before_message != null && before_message.size > 0) {
|
||||||
|
@ -161,7 +161,7 @@ public class GlobalSearch : Overlay {
|
||||||
context_box.add(get_context_message_widget(after_message.first()));
|
context_box.add(get_context_message_widget(after_message.first()));
|
||||||
}
|
}
|
||||||
|
|
||||||
Label date_label = new Label(ConversationSummary.ItemMetaDataHeader.get_relative_time(item.display_time.to_local())) { xalign=0, visible=true };
|
Label date_label = new Label(ConversationSummary.ItemMetaDataHeader.get_relative_time(item.time.to_local())) { xalign=0, visible=true };
|
||||||
date_label.get_style_context().add_class("dim-label");
|
date_label.get_style_context().add_class("dim-label");
|
||||||
|
|
||||||
string display_name = Util.get_conversation_display_name(stream_interactor, item.conversation);
|
string display_name = Util.get_conversation_display_name(stream_interactor, item.conversation);
|
||||||
|
|
|
@ -110,7 +110,6 @@ public class BadMessageItem : Plugins.MetaConversationItem {
|
||||||
|
|
||||||
private Plugin plugin;
|
private Plugin plugin;
|
||||||
private Conversation conversation;
|
private Conversation conversation;
|
||||||
private DateTime date;
|
|
||||||
private Jid problem_jid;
|
private Jid problem_jid;
|
||||||
private BadnessType badness_type;
|
private BadnessType badness_type;
|
||||||
|
|
||||||
|
@ -118,8 +117,7 @@ public class BadMessageItem : Plugins.MetaConversationItem {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.conversation = conversation;
|
this.conversation = conversation;
|
||||||
this.problem_jid = jid;
|
this.problem_jid = jid;
|
||||||
this.date = date;
|
this.time = date;
|
||||||
this.sort_time = date;
|
|
||||||
this.badness_type = badness_type;
|
this.badness_type = badness_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue