From a86941decfd3323673cb1fcbe9f3f835c5d69777 Mon Sep 17 00:00:00 2001 From: pax Date: Thu, 9 Apr 2026 20:05:38 -0500 Subject: [PATCH] info_panel: suppress flat-tag flash when category fetch is pending MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a category fetch is about to fire (Rule34/Safebooru.org/ Moebooru on first click), the info panel was rendering the full flat tag list, then ~200ms later re-rendering with categorized tags. The re-layout from flat→categorized looked like a visual hitch. Fix: new _categories_pending flag on InfoPanel. When True, the flat-tag fallback branch is skipped — the tags area stays empty until categories arrive and render in one clean pass. _ensure_post_categories_async sets _categories_pending = True before scheduling the fetch (or False if no fetcher = Danbooru) _on_categories_updated clears _categories_pending = False Visual result: Danbooru/e621: instant (inline, no flag) Gelbooru with auth: instant (background prefetch beat the click) Rule34/SB.org/Moebooru: empty ~200ms → categories appear cleanly (no flat→categorized re-layout) --- booru_viewer/gui/info_panel.py | 8 ++++++-- booru_viewer/gui/main_window.py | 10 ++++++---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/booru_viewer/gui/info_panel.py b/booru_viewer/gui/info_panel.py index c47e43d..7ad0d5e 100644 --- a/booru_viewer/gui/info_panel.py +++ b/booru_viewer/gui/info_panel.py @@ -79,6 +79,7 @@ class InfoPanel(QWidget): def __init__(self, parent: QWidget | None = None) -> None: super().__init__(parent) + self._categories_pending = False layout = QVBoxLayout(self) layout.setContentsMargins(6, 6, 6, 6) @@ -164,8 +165,11 @@ class InfoPanel(QWidget): btn.setStyleSheet(style) btn.clicked.connect(lambda checked, t=tag: self.tag_clicked.emit(t)) self._tags_flow.addWidget(btn) - else: - # Fallback: flat tag list (Gelbooru, Moebooru) + elif not self._categories_pending: + # Flat tag fallback — only when no category fetch is + # in-flight. When a fetch IS pending, leaving the tags + # area empty avoids the flat→categorized re-layout hitch + # (categories arrive ~200ms later and render in one pass). for tag in post.tag_list[:100]: btn = QPushButton(tag) btn.setFlat(True) diff --git a/booru_viewer/gui/main_window.py b/booru_viewer/gui/main_window.py index 656ba3b..bf67038 100644 --- a/booru_viewer/gui/main_window.py +++ b/booru_viewer/gui/main_window.py @@ -166,14 +166,15 @@ class BooruApp(QMainWindow): No-op if the active client doesn't have a CategoryFetcher (Danbooru/e621 categorize inline, no fetcher needed). - Does NOT check post.tag_categories — partial cache composes - from the background prefetch can leave the post at e.g. - 5/40 coverage. ensure_categories checks 100% cache coverage - internally and fetches the remainder if needed. + Sets _categories_pending on the info panel so it skips the + flat-tag fallback render (avoids the flat→categorized + re-layout hitch). The flag clears when categories arrive. """ client = self._make_client() if client is None or client.category_fetcher is None: + self._info_panel._categories_pending = False return + self._info_panel._categories_pending = True fetcher = client.category_fetcher signals = self._signals @@ -195,6 +196,7 @@ class BooruApp(QMainWindow): place by the CategoryFetcher, so we just call the panel's set_post / set_post_tags again to pick up the new dict. """ + self._info_panel._categories_pending = False if not post or not post.tag_categories: return idx = self._grid.selected_index