Staggered infinite scroll — posts appear one at a time

Posts from infinite scroll are queued and added individually
with 50ms delay between each, creating a smooth flowing
appearance instead of 40 empty cells appearing at once.
This commit is contained in:
pax 2026-04-05 14:55:16 -05:00
parent 6f684bb491
commit 6524104008

View File

@ -814,43 +814,57 @@ class BooruApp(QMainWindow):
self._prefetch_adjacent(0) self._prefetch_adjacent(0)
def _on_search_append(self, posts: list) -> None: def _on_search_append(self, posts: list) -> None:
"""Append more posts to the grid (infinite scroll).""" """Queue posts and add them one at a time as thumbnails arrive."""
if not posts: if not posts:
self._loading = False self._loading = False
self._infinite_exhausted = True self._infinite_exhausted = True
self._status.showMessage(f"{len(self._posts)} results (end)") self._status.showMessage(f"{len(self._posts)} results (end)")
return return
self._shown_post_ids.update(p.id for p in posts) self._shown_post_ids.update(p.id for p in posts)
start = len(self._posts)
self._posts.extend(posts)
self._page_label.setText(f"Page {self._current_page}")
self._status.showMessage(f"{len(self._posts)} results")
thumbs = self._grid.append_posts(len(posts))
QTimer.singleShot(100, self._clear_loading) QTimer.singleShot(100, self._clear_loading)
from ..core.config import saved_dir, saved_folder_dir if not hasattr(self, '_append_queue'):
self._append_queue = []
self._append_queue.extend(posts)
self._drain_append_queue()
def _drain_append_queue(self) -> None:
"""Add queued posts to the grid one at a time with thumbnail fetch."""
if not getattr(self, '_append_queue', None):
return
from ..core.config import saved_dir
from ..core.cache import cached_path_for
site_id = self._site_combo.currentData() site_id = self._site_combo.currentData()
_sd = saved_dir() _sd = saved_dir()
_saved_ids: set[int] = set() _saved_ids: set[int] = set()
if _sd.exists(): if _sd.exists():
_saved_ids = {int(f.stem) for f in _sd.iterdir() if f.is_file() and f.stem.isdigit()} _saved_ids = {int(f.stem) for f in _sd.iterdir() if f.is_file() and f.stem.isdigit()}
for i, (post, thumb) in enumerate(zip(posts, thumbs)): post = self._append_queue.pop(0)
if site_id and self._db.is_bookmarked(site_id, post.id): idx = len(self._posts)
thumb.set_bookmarked(True) self._posts.append(post)
saved = post.id in _saved_ids thumbs = self._grid.append_posts(1)
thumb.set_saved_locally(saved) thumb = thumbs[0]
from ..core.cache import cached_path_for
cached = cached_path_for(post.file_url)
if cached.exists():
thumb._cached_path = str(cached)
if post.preview_url:
self._fetch_thumbnail(start + i, post.preview_url)
# Prefetch new posts if site_id and self._db.is_bookmarked(site_id, post.id):
if self._db.get_setting_bool("prefetch_adjacent") and posts: thumb.set_bookmarked(True)
self._prefetch_adjacent(start) thumb.set_saved_locally(post.id in _saved_ids)
cached = cached_path_for(post.file_url)
if cached.exists():
thumb._cached_path = str(cached)
if post.preview_url:
self._fetch_thumbnail(idx, post.preview_url)
self._status.showMessage(f"{len(self._posts)} results")
# Schedule next post
if self._append_queue:
QTimer.singleShot(50, self._drain_append_queue)
else:
# All done — prefetch
if self._db.get_setting_bool("prefetch_adjacent"):
self._prefetch_adjacent(idx)
def _fetch_thumbnail(self, index: int, url: str) -> None: def _fetch_thumbnail(self, index: int, url: str) -> None:
async def _download(): async def _download():