Spiral prefetch: gradually preloads entire page from clicked post

Expands outward from the selected post (±1, ±2, ±3...) with
200ms pacing between each download. Already-cached files skip
instantly. Setting renamed to "Prefetch whole page over time".
This commit is contained in:
pax 2026-04-05 12:47:57 -05:00
parent a7a76018d8
commit 2156dec91d
2 changed files with 22 additions and 11 deletions

View File

@ -809,23 +809,34 @@ class BooruApp(QMainWindow):
self._prefetch_adjacent(index) self._prefetch_adjacent(index)
def _prefetch_adjacent(self, index: int) -> None: def _prefetch_adjacent(self, index: int) -> None:
"""Prefetch posts in all 4 directions (left, right, up, down).""" """Prefetch outward from clicked post, gradually covering the whole page."""
cols = self._grid._flow.columns total = len(self._posts)
offsets = [1, -1, cols, -cols] if total == 0:
async def _prefetch_batch(): return
for offset in offsets:
adj = index + offset # Build spiral order: distance 1, 2, 3... from index
order = []
for dist in range(1, total):
for adj in (index + dist, index - dist):
if 0 <= adj < total:
order.append(adj)
if len(order) >= total - 1:
break
async def _prefetch_spiral():
for adj in order:
if 0 <= adj < len(self._posts) and self._posts[adj].file_url: if 0 <= adj < len(self._posts) and self._posts[adj].file_url:
self._signals.prefetch_progress.emit(adj, 0.0) self._signals.prefetch_progress.emit(adj, 0.0)
try: try:
def _progress(dl, total, idx=adj): def _progress(dl, total_bytes, idx=adj):
if total > 0: if total_bytes > 0:
self._signals.prefetch_progress.emit(idx, dl / total) self._signals.prefetch_progress.emit(idx, dl / total_bytes)
await download_image(self._posts[adj].file_url, progress_callback=_progress) await download_image(self._posts[adj].file_url, progress_callback=_progress)
except Exception as e: except Exception as e:
log.warning(f"Operation failed: {e}") log.warning(f"Operation failed: {e}")
self._signals.prefetch_progress.emit(adj, -1) self._signals.prefetch_progress.emit(adj, -1)
self._run_async(_prefetch_batch) await asyncio.sleep(0.2) # gentle pacing
self._run_async(_prefetch_spiral)
def _on_download_progress(self, downloaded: int, total: int) -> None: def _on_download_progress(self, downloaded: int, total: int) -> None:
if total > 0: if total > 0:

View File

@ -111,7 +111,7 @@ class SettingsDialog(QDialog):
form.addRow("", self._preload) form.addRow("", self._preload)
# Prefetch adjacent posts # Prefetch adjacent posts
self._prefetch = QCheckBox("Prefetch adjacent posts") self._prefetch = QCheckBox("Prefetch whole page over time")
self._prefetch.setChecked(self._db.get_setting_bool("prefetch_adjacent")) self._prefetch.setChecked(self._db.get_setting_bool("prefetch_adjacent"))
form.addRow("", self._prefetch) form.addRow("", self._prefetch)