Fetch MAM pages when scrolling in chats

This commit is contained in:
Konstantin Kuznetsov 2024-03-19 11:13:44 +03:00 committed by Maxim Logaev
parent c9241e220c
commit bcac03ef6a
5 changed files with 51 additions and 8 deletions

View file

@ -2,6 +2,8 @@ using Xmpp;
namespace Dino.Entities { namespace Dino.Entities {
const int HISTORY_SYNC_MAM_PAGES = 10;
public class Conversation : Object { public class Conversation : Object {
public signal void object_updated(Conversation conversation); public signal void object_updated(Conversation conversation);
@ -16,6 +18,10 @@ public class Conversation : Object {
} }
} }
public int syncSpeed() {
return HISTORY_SYNC_MAM_PAGES;
}
public int id { get; set; } public int id { get; set; }
public Type type_ { get; set; } public Type type_ { get; set; }
public Account account { get; private set; } public Account account { get; private set; }

View file

@ -6,8 +6,6 @@ using Xmpp;
namespace Dino { namespace Dino {
const int HISTORY_SYNC_MAM_PAGES = 10;
public class ContentItemStore : StreamInteractionModule, Object { public class ContentItemStore : StreamInteractionModule, Object {
public static ModuleIdentity<ContentItemStore> IDENTITY = new ModuleIdentity<ContentItemStore>("content_item_store"); public static ModuleIdentity<ContentItemStore> IDENTITY = new ModuleIdentity<ContentItemStore>("content_item_store");
public string id { get { return IDENTITY.id; } } public string id { get { return IDENTITY.id; } }
@ -260,8 +258,8 @@ public class ContentItemStore : StreamInteractionModule, Object {
if (items.size == 0 && request_from_server) { if (items.size == 0 && request_from_server) {
// Async request to get earlier messages from the server // Async request to get earlier messages from the server
var history_sync = stream_interactor.get_module(MessageProcessor.IDENTITY).history_sync; var history_sync = stream_interactor.get_module(MessageProcessor.IDENTITY).history_sync;
history_sync.fetch_data.begin(conversation.account, conversation.counterpart.bare_jid, item.time, HISTORY_SYNC_MAM_PAGES, (_, res) => { history_sync.fetch_conversation_data.begin(conversation, item.time, (_, res) => {
history_sync.fetch_data.end(res); history_sync.fetch_conversation_data.end(res);
debug("History loaded"); debug("History loaded");
history_loaded(conversation, item, count); history_loaded(conversation, item, count);
}); });

View file

@ -143,11 +143,30 @@ public class Dino.HistorySync {
return page_result; return page_result;
} }
public async void fetch_data(Account account, Jid target, DateTime latest, int pages) { public async void fetch_data(Account account, Jid target, DateTime latest) {
debug("Fetch history for %s", target.to_string()); debug("Fetch history for %s", target.to_string());
var query_params = new Xmpp.MessageArchiveManagement.V2.MamQueryParams.query_before(target, latest, null); var query_params = new Xmpp.MessageArchiveManagement.V2.MamQueryParams.query_before(target, latest, null);
yield fetch_pages(account, query_params, pages); yield fetch_pages(account, query_params, HISTORY_SYNC_MAM_PAGES);
}
public async void fetch_conversation_data(Conversation? conversation, DateTime latest) {
if (conversation == null) {
warning("Failed to fetch history, conversation is null");
return;
}
var target = conversation.counterpart.bare_jid;
var account = conversation.account;
debug("Fetch history for %s", target.to_string());
var query_params = new Xmpp.MessageArchiveManagement.V2.MamQueryParams.query_before(target, latest, null);
if (conversation.type_ == Conversation.Type.CHAT) {
query_params.mam_server = account.bare_jid;
query_params.with = target;
}
yield fetch_pages(account, query_params, conversation.syncSpeed());
} }
public async void fetch_history(Account account, Jid target, Cancellable? cancellable = null) { public async void fetch_history(Account account, Jid target, Cancellable? cancellable = null) {

View file

@ -107,7 +107,7 @@ public class MucManager : StreamInteractionModule, Object {
var history_sync = stream_interactor.get_module(MessageProcessor.IDENTITY).history_sync; var history_sync = stream_interactor.get_module(MessageProcessor.IDENTITY).history_sync;
if (conversation == null) { if (conversation == null) {
// We never joined the conversation before, fetch latest MAM pages // We never joined the conversation before, fetch latest MAM pages
yield history_sync.fetch_data(account, jid.bare_jid, new DateTime.now(), 10); yield history_sync.fetch_data(account, jid.bare_jid, new DateTime.now());
} else { } else {
// Fetch everything up to the last time the user actively joined // Fetch everything up to the last time the user actively joined
if (!mucs_sync_cancellables.has_key(account)) { if (!mucs_sync_cancellables.has_key(account)) {

View file

@ -564,11 +564,31 @@ public class ConversationView : Widget, Plugins.ConversationItemCollection, Plug
private void load_earlier_messages(bool request_from_server = true) { private void load_earlier_messages(bool request_from_server = true) {
was_value = scrolled.vadjustment.value; was_value = scrolled.vadjustment.value;
debug("loading earlier messages"); debug("loading earlier messages");
if (!reloading_mutex.trylock()) { if (!reloading_mutex.trylock()) {
return; return;
} }
if (content_items.size > 0) { if (content_items.size == 0) {
// List is empty, try load local data
Gee.List<ContentMetaItem> items = content_populator.populate_latest(conversation, 20);
debug("inserting new messages, size: %d", items.size);
foreach (ContentMetaItem item in items) {
do_insert_item(item);
}
if (request_from_server) {
// If the list is empty also try to load data from the server
var history_sync = stream_interactor.get_module(MessageProcessor.IDENTITY).history_sync;
history_sync.fetch_conversation_data.begin(conversation, new DateTime.now(), (_, res) => {
history_sync.fetch_conversation_data.end(res);
// Request finished, reload messages
load_earlier_messages(false);
});
}
} else if (content_items.size > 0) {
// List is not empty, fetch data before the latest available message
Gee.List<ContentMetaItem> items = content_populator.populate_before(conversation, ((ContentMetaItem) content_items.first()).content_item, 20, request_from_server); Gee.List<ContentMetaItem> items = content_populator.populate_before(conversation, ((ContentMetaItem) content_items.first()).content_item, 20, request_from_server);
debug("inserting new messages, size: %d", items.size); debug("inserting new messages, size: %d", items.size);
foreach (ContentMetaItem item in items) { foreach (ContentMetaItem item in items) {