From 0f24910685164800fbdc60398db1c05f853fa979 Mon Sep 17 00:00:00 2001 From: "jabber.developer2" Date: Sat, 16 May 2026 17:06:31 +0300 Subject: [PATCH] fix(ui): preserve WIN_CHAT messages when DB cannot replay them MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit _win_printf skipped buffer/pad append for WIN_CHAT while the user was scrolled, relying on chatwin_db_history() to replay missed messages on scroll-down. That replay is unavailable when PREF_DBLOG is "off" (no write) or "redact" ([REDACTED] body), or when the backend failed to initialize — in those cases the message was lost. Introduce log_database_can_recover_messages() and gate the WIN_CHAT early return on it: when recovery is impossible, fall through and append to the buffer just like non-chat windows do. Also treat DB_RESPONSE_ERROR in win_page_down the same as DB_RESPONSE_EMPTY so the [SCROLLED] indicator doesn't hang when the backend is dead. --- src/database.c | 16 ++++++++++++++++ src/database.h | 3 +++ src/ui/window.c | 15 +++++++++------ 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/database.c b/src/database.c index b97e8539..0f3c8dc7 100644 --- a/src/database.c +++ b/src/database.c @@ -61,6 +61,22 @@ integrity_issue_free(integrity_issue_t* issue) } } +gboolean +log_database_can_recover_messages(void) +{ + if (!active_db_backend) { + return FALSE; + } + auto_gchar gchar* pref_dblog = prefs_get_string(PREF_DBLOG); + if (g_strcmp0(pref_dblog, "off") == 0) { + return FALSE; + } + if (g_strcmp0(pref_dblog, "redact") == 0) { + return FALSE; + } + return TRUE; +} + gboolean log_database_init(ProfAccount* account) { diff --git a/src/database.h b/src/database.h index c897230f..2204c0b0 100644 --- a/src/database.h +++ b/src/database.h @@ -109,6 +109,9 @@ ProfMessage* log_database_get_limits_info(const gchar* const contact_barejid, gb void log_database_close(void); GSList* log_database_verify_integrity(const gchar* const contact_barejid); +// FALSE if no backend, or PREF_DBLOG is "off" / "redact". +gboolean log_database_can_recover_messages(void); + // Cross-backend export/import (requires HAVE_SQLITE) #ifdef HAVE_SQLITE int log_database_export_to_flatfile(const gchar* const contact_jid); diff --git a/src/ui/window.c b/src/ui/window.c index 3ee21b43..bf84294f 100644 --- a/src/ui/window.c +++ b/src/ui/window.c @@ -813,7 +813,9 @@ win_page_down(ProfWin* window, int scroll_size) auto_gchar gchar* start = g_date_time_format_iso8601(last_entry->time); auto_gchar gchar* end_date = g_date_time_format_iso8601(now); db_history_result_t db_response = chatwin_db_history((ProfChatWin*)window, start, end_date, FALSE); - if (db_response == DB_RESPONSE_EMPTY) + // Treat transient DB error (e.g. no active backend) the same + // as EMPTY: no rows can be fetched, so stop indicating [SCROLLED]. + if (db_response == DB_RESPONSE_EMPTY || db_response == DB_RESPONSE_ERROR) *scroll_state = WIN_SCROLL_REACHED_BOTTOM; // similar to page_up (see explanation there) @@ -1809,13 +1811,14 @@ static void _win_printf(ProfWin* window, const char* show_char, int pad_indent, GDateTime* timestamp, int flags, theme_item_t theme_item, const char* const display_from, const char* const from_jid, const char* const message_id, const char* const message, ...) { - /* While the user is scrolled, bump the unread indicator. Only WIN_CHAT - * skips the buffer/render entirely — it can recover the message via - * chatwin_db_history on scroll-down. Other window types have no DB - * fallback, so the message must still be appended to the buffer and pad. */ + /* While the user is scrolled, bump the unread indicator. WIN_CHAT + * skips the buffer/render only when the DB will preserve the message + * verbatim — chatwin_db_history on scroll-down will replay it. When + * the DB is off/redact/dead we cannot recover, so fall through and + * append to the buffer just like non-chat windows. */ if (window->layout->paged && wins_is_current(window)) { window->layout->unread_msg++; - if (window->type == WIN_CHAT) { + if (window->type == WIN_CHAT && log_database_can_recover_messages()) { return; } }