From d882e349a9b732cccc275ab9d3f0ebe823917269 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Padez?= Date: Sat, 5 Sep 2026 21:45:07 +0100 Subject: [PATCH] the grid never noticed the crawler finishing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It loaded once. A bookmark is not finished when it is saved - Karakeep crawls it afterwards, and the picture, description and favicon arrive minutes later - so the panel sat on "fetching…" while the work quietly completed behind it. Worse, the page most likely to be full of unfinished ones is the FIRST page. Newest first, and the crawler works through the backlog, so a fresh import shows exactly the page with the least on it. Measured while diagnosing: 79 of 97 crawled, and all 16 pending sitting on page one - which reads as a stalled crawler and is the opposite. Polls every five seconds while anything is pending, through the same code path as a first load so a refresh cannot drift from it. Self-limiting and needs no switch: it re-arms only while something is actually pending, so a settled library makes no requests at all. --- manifest.ts | 2 +- web/BookmarksPanel.tsx | 39 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/manifest.ts b/manifest.ts index e086837..701a15c 100644 --- a/manifest.ts +++ b/manifest.ts @@ -40,7 +40,7 @@ import type { PluginManifest } from '@@/plugins/manifest'; */ export const manifest: PluginManifest = { publisher: 'officerdev', - version: '2026.09.05.02', + version: '2026.09.05.03', platform: '>=1.0.0', label: 'Karakeep', diff --git a/web/BookmarksPanel.tsx b/web/BookmarksPanel.tsx index 1aabf5b..af5b648 100644 --- a/web/BookmarksPanel.tsx +++ b/web/BookmarksPanel.tsx @@ -79,15 +79,46 @@ export const BookmarksPanel = () => { } }, []); + /* + `tick` exists to re-ask the same question, which is different from asking a new one. + + Everything else in this effect is a NEW question — a different list, different words. This one is + the poll below saying "ask that again", and it has to go through the same path so a refresh cannot + drift from a first load. + */ + const [tick, setTick] = useState(0); + // Debounced: long enough that a five-letter word is one query instead of five, short enough that the // grid moves while you type. useEffect(() => { const timer = setTimeout(() => void load(list, query), 250); return () => clearTimeout(timer); - }, [list, query, load]); + }, [list, query, load, tick]); const waiting = rows?.filter((b) => b.content?.type === 'link' && b.content.crawlStatus === 'pending').length ?? 0; + /* + ── While anything is still being fetched, ask again ── + + Without this the panel loads once and never moves. That is wrong here in a way it would not be for + most lists, because a bookmark is not finished when it is saved: Karakeep crawls it afterwards, and + the picture, the description and the favicon all arrive minutes later. + + Worse, the page most likely to be full of unfinished ones is the FIRST page — newest first, and the + crawler works through the backlog — so a fresh import shows a grid of "fetching…" that never + resolves until somebody reloads by hand. Measured on this instance: 79 of 97 crawled, and all 16 + pending sitting on page one. + + The poll is self-limiting and needs no switch: it only re-arms while something is actually pending, + so a settled library makes no requests at all. Five seconds because a crawl takes a few and nobody + is watching the clock. + */ + useEffect(() => { + if (waiting === 0) return; + const timer = setTimeout(() => setTick((n) => n + 1), 5000); + return () => clearTimeout(timer); + }, [waiting, tick]); + return (
@@ -105,7 +136,11 @@ export const BookmarksPanel = () => { A bookmark has no picture until Karakeep has crawled it, and on a fresh import that is most of them for a while. Without this the panel looks broken at exactly the moment it is working. */} - {waiting > 0 && {waiting} still being fetched — pictures appear as they finish.} + {waiting > 0 && ( + + {waiting} still being fetched — this updates itself as they finish. + + )}