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