From 0d29e05d7711f98bc26bd2fc4abd6a7b70f52329 Mon Sep 17 00:00:00 2001 From: John Hernandez <129467592+H3rnand3zzz@users.noreply.github.com> Date: Tue, 5 Dec 2023 12:35:48 +0100 Subject: [PATCH] Fix scrolling state at windows edge The problem: if user scrolled to the edge of the window, the state that edge is reached, transfers to other windows, rendering user unable to scroll further up/down in other windows as well. Make unique states for each window that show that edge of the DB is reached. Later it might be improved with MAM states as well to decrease load on program in cases when user keeps scrolling despite reaching the edge. Bug discovered by @atomicwatch, reported through the developers' MUC `SCROLL_INNER` naming suggestion by @jubalh --- src/ui/win_types.h | 7 +++++++ src/ui/window.c | 27 +++++++++++++++++---------- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/ui/win_types.h b/src/ui/win_types.h index b7cd3519..dc821c01 100644 --- a/src/ui/win_types.h +++ b/src/ui/win_types.h @@ -146,9 +146,16 @@ typedef enum { WIN_VCARD } win_type_t; +typedef enum { + WIN_SCROLL_INNER, + WIN_SCROLL_REACHED_TOP, + WIN_SCROLL_REACHED_BOTTOM +} win_scroll_state_t; + typedef struct prof_win_t { win_type_t type; + win_scroll_state_t scroll_state; ProfLayout* layout; Autocomplete urls_ac; Autocomplete quotes_ac; diff --git a/src/ui/window.c b/src/ui/window.c index e3dff377..b0452091 100644 --- a/src/ui/window.c +++ b/src/ui/window.c @@ -75,9 +75,6 @@ static void _win_print_internal(ProfWin* window, const char* show_char, int pad_ int flags, theme_item_t theme_item, const char* const from, const char* const message, DeliveryReceipt* receipt); static void _win_print_wrapped(WINDOW* win, const char* const message, size_t indent, int pad_indent); -static gboolean _reached_top_of_database = FALSE; -static gboolean _reached_bottom_of_database = FALSE; - int win_roster_cols(void) { @@ -136,6 +133,7 @@ win_create_console(void) { ProfConsoleWin* new_win = malloc(sizeof(ProfConsoleWin)); new_win->window.type = WIN_CONSOLE; + new_win->window.scroll_state = WIN_SCROLL_INNER; new_win->window.layout = _win_create_split_layout(); return &new_win->window; @@ -146,6 +144,7 @@ win_create_chat(const char* const barejid) { ProfChatWin* new_win = malloc(sizeof(ProfChatWin)); new_win->window.type = WIN_CHAT; + new_win->window.scroll_state = WIN_SCROLL_INNER; new_win->window.layout = _win_create_simple_layout(); new_win->barejid = strdup(barejid); @@ -177,6 +176,7 @@ win_create_muc(const char* const roomjid) int cols = getmaxx(stdscr); new_win->window.type = WIN_MUC; + new_win->window.scroll_state = WIN_SCROLL_INNER; ProfLayoutSplit* layout = malloc(sizeof(ProfLayoutSplit)); layout->base.type = LAYOUT_SPLIT; @@ -231,6 +231,7 @@ win_create_config(const char* const roomjid, DataForm* form, ProfConfWinCallback { ProfConfWin* new_win = malloc(sizeof(ProfConfWin)); new_win->window.type = WIN_CONFIG; + new_win->window.scroll_state = WIN_SCROLL_INNER; new_win->window.layout = _win_create_simple_layout(); new_win->roomjid = strdup(roomjid); new_win->form = form; @@ -248,6 +249,7 @@ win_create_private(const char* const fulljid) { ProfPrivateWin* new_win = malloc(sizeof(ProfPrivateWin)); new_win->window.type = WIN_PRIVATE; + new_win->window.scroll_state = WIN_SCROLL_INNER; new_win->window.layout = _win_create_simple_layout(); new_win->fulljid = strdup(fulljid); new_win->unread = 0; @@ -264,6 +266,7 @@ win_create_xmlconsole(void) { ProfXMLWin* new_win = malloc(sizeof(ProfXMLWin)); new_win->window.type = WIN_XML; + new_win->window.scroll_state = WIN_SCROLL_INNER; new_win->window.layout = _win_create_simple_layout(); new_win->memcheck = PROFXMLWIN_MEMCHECK; @@ -276,6 +279,7 @@ win_create_plugin(const char* const plugin_name, const char* const tag) { ProfPluginWin* new_win = malloc(sizeof(ProfPluginWin)); new_win->window.type = WIN_PLUGIN; + new_win->window.scroll_state = WIN_SCROLL_INNER; new_win->window.layout = _win_create_simple_layout(); new_win->tag = strdup(tag); @@ -291,6 +295,7 @@ win_create_vcard(vCard* vcard) { ProfVcardWin* new_win = malloc(sizeof(ProfVcardWin)); new_win->window.type = WIN_VCARD; + new_win->window.scroll_state = WIN_SCROLL_INNER; new_win->window.layout = _win_create_simple_layout(); new_win->vcard = vcard; @@ -625,7 +630,6 @@ win_free(ProfWin* window) void win_page_up(ProfWin* window, int scroll_size) { - _reached_bottom_of_database = FALSE; int rows = getmaxy(stdscr); int total_rows = getcury(window->layout->win); int page_space = rows - 4; @@ -633,6 +637,8 @@ win_page_up(ProfWin* window, int scroll_size) int page_start_initial = *page_start; if (scroll_size == 0) scroll_size = page_space; + win_scroll_state_t* scroll_state = &window->scroll_state; + *scroll_state = (*scroll_state == WIN_SCROLL_REACHED_BOTTOM) ? WIN_SCROLL_INNER : *scroll_state; *page_start -= scroll_size; @@ -642,11 +648,11 @@ win_page_up(ProfWin* window, int scroll_size) // Don't do anything if still fetching mam messages if (first_entry && !(first_entry->theme_item == THEME_ROOMINFO && g_strcmp0(first_entry->message, LOADING_MESSAGE) == 0)) { - if (!_reached_top_of_database) { - _reached_top_of_database = !chatwin_db_history(chatwin, NULL, NULL, TRUE); + if (*scroll_state != WIN_SCROLL_REACHED_TOP) { + *scroll_state = !chatwin_db_history(chatwin, NULL, NULL, TRUE) ? WIN_SCROLL_REACHED_TOP : WIN_SCROLL_INNER; } - if (_reached_top_of_database && prefs_get_boolean(PREF_MAM)) { + if (*scroll_state == WIN_SCROLL_REACHED_TOP && prefs_get_boolean(PREF_MAM)) { win_print_loading_history(window); iq_mam_request_older(chatwin); } @@ -672,7 +678,6 @@ win_page_up(ProfWin* window, int scroll_size) void win_page_down(ProfWin* window, int scroll_size) { - _reached_top_of_database = FALSE; int rows = getmaxy(stdscr); int* page_start = &(window->layout->y_pos); int total_rows = getcury(window->layout->win); @@ -680,6 +685,8 @@ win_page_down(ProfWin* window, int scroll_size) int page_start_initial = *page_start; if (scroll_size == 0) scroll_size = page_space; + win_scroll_state_t* scroll_state = &window->scroll_state; + *scroll_state = (*scroll_state == WIN_SCROLL_REACHED_TOP) ? WIN_SCROLL_INNER : *scroll_state; *page_start += scroll_size; @@ -691,8 +698,8 @@ win_page_down(ProfWin* window, int scroll_size) GDateTime* now = g_date_time_new_now_local(); gchar* end = g_date_time_format_iso8601(now); // end is free'd inside - if (!_reached_bottom_of_database && !chatwin_db_history((ProfChatWin*)window, start, end, FALSE)) { - _reached_bottom_of_database = TRUE; + if (*scroll_state != WIN_SCROLL_REACHED_BOTTOM && !chatwin_db_history((ProfChatWin*)window, start, end, FALSE)) { + *scroll_state = WIN_SCROLL_REACHED_BOTTOM; } g_date_time_unref(now);