From 208a10d6d8c6b7ba314f235732d2e0e98d979e87 Mon Sep 17 00:00:00 2001 From: scanash00 Date: Mon, 16 Feb 2026 19:17:54 -0900 Subject: [PATCH] bug fixes and some caching stuff --- backend/internal/api/handler.go | 24 ++++++++---------------- extension/src/entrypoints/background.ts | 2 +- extension/src/utils/api.ts | 12 ++++++++++-- extension/src/utils/messaging.ts | 2 +- extension/src/utils/overlay.ts | 15 +++++++++------ web/src/api/client.ts | 1 + web/src/lib/og.ts | 3 ++- web/src/middleware.ts | 2 +- web/src/pages/og-image.ts | 13 ++++++------- 9 files changed, 39 insertions(+), 35 deletions(-) diff --git a/backend/internal/api/handler.go b/backend/internal/api/handler.go index 5be4d45..1fcfe62 100644 --- a/backend/internal/api/handler.go +++ b/backend/internal/api/handler.go @@ -478,22 +478,6 @@ func (h *Handler) GetFeed(w http.ResponseWriter, r *http.Request) { }) } -func containsTag(tagsJSON *string, tag string) bool { - if tagsJSON == nil || *tagsJSON == "" { - return false - } - var tags []string - if err := json.Unmarshal([]byte(*tagsJSON), &tags); err != nil { - return false - } - for _, t := range tags { - if t == tag { - return true - } - } - return false -} - func sortFeed(feed []interface{}) { sort.Slice(feed, func(i, j int) bool { t1 := getCreatedAt(feed[i]) @@ -764,6 +748,14 @@ func (h *Handler) GetByTarget(w http.ResponseWriter, r *http.Request) { enrichedHighlights, _ := hydrateHighlights(h.db, highlights, h.getViewerDID(r)) enrichedBookmarks, _ := hydrateBookmarks(h.db, bookmarks, h.getViewerDID(r)) + totalItems := len(enrichedAnnotations) + len(enrichedHighlights) + len(enrichedBookmarks) + + if totalItems == 0 { + w.Header().Set("Cache-Control", "public, max-age=60, s-maxage=300") + } else { + w.Header().Set("Cache-Control", "private, max-age=0, no-store") + } + w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(map[string]interface{}{ "@context": "http://www.w3.org/ns/anno.jsonld", diff --git a/extension/src/entrypoints/background.ts b/extension/src/entrypoints/background.ts index 76f22db..14e5817 100644 --- a/extension/src/entrypoints/background.ts +++ b/extension/src/entrypoints/background.ts @@ -54,7 +54,7 @@ export default defineBackground(() => { }); onMessage('getAnnotations', async ({ data }) => { - return await getAnnotations(data.url); + return await getAnnotations(data.url, [], data.cacheBust); }); onMessage('activateOnPdf', async ({ data }) => { diff --git a/extension/src/utils/api.ts b/extension/src/utils/api.ts index 7f100ef..2fd2031 100644 --- a/extension/src/utils/api.ts +++ b/extension/src/utils/api.ts @@ -81,14 +81,22 @@ async function apiRequest(path: string, options: RequestInit = {}): Promise { try { - const res = await fetch(`${apiUrl}/api/targets?source=${encodeURIComponent(u)}`); + let requestUrl = `${apiUrl}/api/targets?source=${encodeURIComponent(u)}`; + if (cacheBust) { + requestUrl += `&t=${Date.now()}`; + } + const res = await fetch(requestUrl); if (!res.ok) return { annotations: [], highlights: [], bookmarks: [] }; return await res.json(); } catch { diff --git a/extension/src/utils/messaging.ts b/extension/src/utils/messaging.ts index 1e67a0f..3626fa1 100644 --- a/extension/src/utils/messaging.ts +++ b/extension/src/utils/messaging.ts @@ -11,7 +11,7 @@ import type { interface ProtocolMap { checkSession(): MarginSession; - getAnnotations(data: { url: string }): Annotation[]; + getAnnotations(data: { url: string; cacheBust?: boolean }): Annotation[]; activateOnPdf(data: { tabId: number; url: string }): { redirected: boolean }; createAnnotation(data: { url: string; diff --git a/extension/src/utils/overlay.ts b/extension/src/utils/overlay.ts index c8c9df7..0bff322 100644 --- a/extension/src/utils/overlay.ts +++ b/extension/src/utils/overlay.ts @@ -398,7 +398,7 @@ export async function initContentScript(ctx: { onInvalidated: (cb: () => void) = composeModal?.remove(); composeModal = null; - setTimeout(() => fetchAnnotations(), 500); + setTimeout(() => fetchAnnotations(0, true), 500); } catch (error) { console.error('Failed to create annotation:', error); showToast('Failed to create annotation', 'error'); @@ -415,7 +415,7 @@ export async function initContentScript(ctx: { onInvalidated: (cb: () => void) = showComposeModal(message.data.selector.exact); } if (message.type === 'REFRESH_ANNOTATIONS') { - fetchAnnotations(); + fetchAnnotations(0, true); } if (message.type === 'SCROLL_TO_TEXT' && message.text) { scrollToText(message.text); @@ -512,14 +512,17 @@ export async function initContentScript(ctx: { onInvalidated: (cb: () => void) = }, 2500); } - async function fetchAnnotations(retryCount = 0) { + async function fetchAnnotations(retryCount = 0, cacheBust = false) { if (!overlayEnabled) { sendMessage('updateBadge', { count: 0 }); return; } try { - const annotations = await sendMessage('getAnnotations', { url: getPageUrl() }); + const annotations = await sendMessage('getAnnotations', { + url: getPageUrl(), + cacheBust, + }); sendMessage('updateBadge', { count: annotations?.length || 0 }); @@ -530,12 +533,12 @@ export async function initContentScript(ctx: { onInvalidated: (cb: () => void) = if (annotations && annotations.length > 0) { renderBadges(annotations); } else if (retryCount < 3) { - setTimeout(() => fetchAnnotations(retryCount + 1), 1000 * (retryCount + 1)); + setTimeout(() => fetchAnnotations(retryCount + 1, cacheBust), 1000 * (retryCount + 1)); } } catch (error) { console.error('Failed to fetch annotations:', error); if (retryCount < 3) { - setTimeout(() => fetchAnnotations(retryCount + 1), 1000 * (retryCount + 1)); + setTimeout(() => fetchAnnotations(retryCount + 1, cacheBust), 1000 * (retryCount + 1)); } } } diff --git a/web/src/api/client.ts b/web/src/api/client.ts index 69918ae..c0df95b 100644 --- a/web/src/api/client.ts +++ b/web/src/api/client.ts @@ -649,6 +649,7 @@ export async function searchActors( } export async function resolveHandle(handle: string): Promise { + if (handle.startsWith("did:")) return handle; try { const res = await fetch( `https://public.api.bsky.app/xrpc/com.atproto.identity.resolveHandle?handle=${encodeURIComponent(handle)}`, diff --git a/web/src/lib/og.ts b/web/src/lib/og.ts index 7088515..86d0684 100644 --- a/web/src/lib/og.ts +++ b/web/src/lib/og.ts @@ -61,6 +61,7 @@ interface APICollection { } export async function resolveHandle(handle: string): Promise { + if (handle.startsWith("did:")) return handle; try { const res = await fetch( `https://public.api.bsky.app/xrpc/com.atproto.identity.resolveHandle?handle=${encodeURIComponent(handle)}`, @@ -221,7 +222,7 @@ export async function fetchCollectionOG(uri: string): Promise { const icon = item.icon || "๐Ÿ“"; const title = `${icon} ${item.name}`; - let description = ""; + let description; if (item.description) { description = `By ${author} ยท ${truncate(item.description, 170)}`; } else { diff --git a/web/src/middleware.ts b/web/src/middleware.ts index 7ead75c..76de07b 100644 --- a/web/src/middleware.ts +++ b/web/src/middleware.ts @@ -35,7 +35,7 @@ export async function onRequest( if (request.method !== "GET" && request.method !== "HEAD" && request.body) { init.body = request.body; - // @ts-expect-error + // @ts-expect-error duplex is generic on RequestInit init.duplex = "half"; } diff --git a/web/src/pages/og-image.ts b/web/src/pages/og-image.ts index 8b342cb..0118a8b 100644 --- a/web/src/pages/og-image.ts +++ b/web/src/pages/og-image.ts @@ -389,8 +389,7 @@ function buildAnnotationImage(data: RecordData, logo: string) { }, }); - (children as any).__accent = tc.accent; - return wrapCard(children); + return wrapCard(children, tc.accent); } function buildBookmarkImage(data: RecordData, logo: string) { @@ -516,8 +515,7 @@ function buildBookmarkImage(data: RecordData, logo: string) { }, }); - (children as any).__accent = tc.accent; - return wrapCard(children); + return wrapCard(children, tc.accent); } function buildCollectionImage(data: RecordData, logo: string) { @@ -599,8 +597,7 @@ function buildCollectionImage(data: RecordData, logo: string) { return wrapCard(children); } -function wrapCard(children: unknown[]) { - const accent = (children as any).__accent || "#3b82f6"; +function wrapCard(children: unknown[], accent: string = "#3b82f6") { return { type: "div", props: { @@ -674,7 +671,9 @@ export const GET: APIRoute = async ({ url }) => { const res = await fetch(url); if (res.ok) return `data:image/svg+xml,${encodeURIComponent(await res.text())}`; - } catch {} + } catch { + // ignore + } } return ""; }, -- 2.51.2