Instant infinite scroll drain, trigger 3 rows early
Old staggered drain (50ms per post) was added for visual polish but made infinite scroll painfully slow — a 40-post page took 2 seconds just to add to the grid. Thumbnails already load async via _fetch_thumbnail, so the stagger was just delaying grid population for no real benefit. Now all posts are added instantly in one pass with thumbnails filling in as they arrive. Scroll trigger widened from 1 row to 3 rows from bottom so the next page starts loading before you reach the end.
This commit is contained in:
parent
a93a8bc70f
commit
bda92a0a87
@ -920,7 +920,7 @@ class BooruApp(QMainWindow):
|
|||||||
self._drain_append_queue()
|
self._drain_append_queue()
|
||||||
|
|
||||||
def _drain_append_queue(self) -> None:
|
def _drain_append_queue(self) -> None:
|
||||||
"""Add queued posts to the grid one at a time with thumbnail fetch."""
|
"""Add all queued posts to the grid at once, thumbnails load async."""
|
||||||
if not getattr(self, '_append_queue', None) or len(self._append_queue) == 0:
|
if not getattr(self, '_append_queue', None) or len(self._append_queue) == 0:
|
||||||
self._loading = False
|
self._loading = False
|
||||||
return
|
return
|
||||||
@ -933,36 +933,34 @@ class BooruApp(QMainWindow):
|
|||||||
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()}
|
||||||
|
|
||||||
post = self._append_queue.pop(0)
|
posts = self._append_queue[:]
|
||||||
idx = len(self._posts)
|
self._append_queue.clear()
|
||||||
self._posts.append(post)
|
start_idx = len(self._posts)
|
||||||
thumbs = self._grid.append_posts(1)
|
self._posts.extend(posts)
|
||||||
thumb = thumbs[0]
|
thumbs = self._grid.append_posts(len(posts))
|
||||||
|
|
||||||
if site_id and self._db.is_bookmarked(site_id, post.id):
|
for i, (post, thumb) in enumerate(zip(posts, thumbs)):
|
||||||
thumb.set_bookmarked(True)
|
idx = start_idx + i
|
||||||
thumb.set_saved_locally(post.id in _saved_ids)
|
if site_id and self._db.is_bookmarked(site_id, post.id):
|
||||||
cached = cached_path_for(post.file_url)
|
thumb.set_bookmarked(True)
|
||||||
if cached.exists():
|
thumb.set_saved_locally(post.id in _saved_ids)
|
||||||
thumb._cached_path = str(cached)
|
cached = cached_path_for(post.file_url)
|
||||||
if post.preview_url:
|
if cached.exists():
|
||||||
self._fetch_thumbnail(idx, post.preview_url)
|
thumb._cached_path = str(cached)
|
||||||
|
if post.preview_url:
|
||||||
|
self._fetch_thumbnail(idx, post.preview_url)
|
||||||
|
|
||||||
self._status.showMessage(f"{len(self._posts)} results")
|
self._status.showMessage(f"{len(self._posts)} results")
|
||||||
|
|
||||||
# Schedule next post
|
# All done — unlock loading, evict
|
||||||
if self._append_queue:
|
self._loading = False
|
||||||
QTimer.singleShot(50, self._drain_append_queue)
|
self._auto_evict_cache()
|
||||||
else:
|
# Check if still at bottom or content doesn't fill viewport
|
||||||
# All done — unlock loading, evict
|
sb = self._grid.verticalScrollBar()
|
||||||
self._loading = False
|
from .grid import THUMB_SIZE, THUMB_SPACING
|
||||||
self._auto_evict_cache()
|
threshold = THUMB_SIZE + THUMB_SPACING * 2
|
||||||
# Check if still at bottom or content doesn't fill viewport
|
if sb.maximum() == 0 or sb.value() >= sb.maximum() - threshold:
|
||||||
sb = self._grid.verticalScrollBar()
|
self._on_reached_bottom()
|
||||||
from .grid import THUMB_SIZE, THUMB_SPACING
|
|
||||||
threshold = THUMB_SIZE + THUMB_SPACING * 2
|
|
||||||
if sb.maximum() == 0 or sb.value() >= sb.maximum() - threshold:
|
|
||||||
self._on_reached_bottom()
|
|
||||||
|
|
||||||
def _fetch_thumbnail(self, index: int, url: str) -> None:
|
def _fetch_thumbnail(self, index: int, url: str) -> None:
|
||||||
async def _download():
|
async def _download():
|
||||||
|
|||||||
@ -482,8 +482,8 @@ class ThumbnailGrid(QScrollArea):
|
|||||||
|
|
||||||
def _check_scroll_bottom(self, value: int) -> None:
|
def _check_scroll_bottom(self, value: int) -> None:
|
||||||
sb = self.verticalScrollBar()
|
sb = self.verticalScrollBar()
|
||||||
# Trigger when within one row height of the bottom
|
# Trigger when within 3 rows of the bottom for early prefetch
|
||||||
threshold = THUMB_SIZE + THUMB_SPACING * 2
|
threshold = (THUMB_SIZE + THUMB_SPACING) * 3
|
||||||
if sb.maximum() > 0 and value >= sb.maximum() - threshold:
|
if sb.maximum() > 0 and value >= sb.maximum() - threshold:
|
||||||
self.reached_bottom.emit()
|
self.reached_bottom.emit()
|
||||||
if value <= 0 and sb.maximum() > 0:
|
if value <= 0 and sb.maximum() > 0:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user