fix(ui): preserve WIN_CHAT messages when DB cannot replay them
All checks were successful
CI Code / Check spelling (pull_request) Successful in 16s
CI Code / Check coding style (pull_request) Successful in 32s
CI Code / Code Coverage (pull_request) Successful in 2m45s
CI Code / Linux (debian) (pull_request) Successful in 4m39s
CI Code / Linux (ubuntu) (pull_request) Successful in 4m56s
CI Code / Linux (arch) (pull_request) Successful in 5m45s

_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.
This commit is contained in:
2026-05-16 17:06:31 +03:00
parent 506794474a
commit 0f24910685
3 changed files with 28 additions and 6 deletions

View File

@@ -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)
{

View File

@@ -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);

View File

@@ -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;
}
}