fix(desktop): cache ads across refresh failures

This commit is contained in:
leookun
2026-09-05 01:35:30 +08:00
parent f1ab8c7221
commit d8190fc07e
2 changed files with 27 additions and 4 deletions
+6 -4
View File
@@ -6,6 +6,7 @@ import cursorIconUrl from "../shared/assets/icons/cursor.svg";
import { api } from "../shared/api";
import { AdMenu } from "./ads/AdMenu";
import { FloatingAd } from "./ads/FloatingAd";
import { loadCachedAds, saveCachedAds } from "./ads/cache";
import { AdActionType, type AdAction, type AdSlot } from "./ads/types";
import { PageLayout } from "./layout/PageLayout";
import { Card } from "../shared/ui/Card";
@@ -50,7 +51,7 @@ export function AppLayout() {
const location = useLocation();
const [leftActionTarget, setLeftActionTarget] = useState<HTMLDivElement | null>(null);
const [rightActionTarget, setRightActionTarget] = useState<HTMLDivElement | null>(null);
const [ads, setAds] = useState<AdSlot[]>([]);
const [ads, setAds] = useState<AdSlot[]>(() => loadCachedAds());
const [activeAd, setActiveAd] = useState<AdSlot | null>(null);
const [dismissCandidate, setDismissCandidate] = useState<AdSlot | null>(null);
const [dismissReason, setDismissReason] = useState("");
@@ -98,6 +99,8 @@ export function AppLayout() {
let disposed = false;
let pending = false;
let lastRequestedAt = 0;
setAds(loadCachedAds());
setActiveAd(null);
const refreshAds = () => {
const now = Date.now();
if (pending || now - lastRequestedAt < 10_000) return;
@@ -105,6 +108,7 @@ export function AppLayout() {
lastRequestedAt = now;
void api.ads(dismissedAdIdsRef.current, locale)
.then((runtime) => {
saveCachedAds(runtime.slots);
if (disposed) return;
setAds(runtime.slots);
setActiveAd((current) => current
@@ -112,9 +116,7 @@ export function AppLayout() {
: null);
})
.catch(() => {
if (disposed) return;
setAds([]);
setActiveAd(null);
// Keep the current ads and local cache available when refreshing fails.
})
.finally(() => { pending = false; });
};
+21
View File
@@ -0,0 +1,21 @@
import type { AdSlot } from "./types";
const adCacheStorageKey = "cursor-byok:ad-runtime";
export function loadCachedAds(): AdSlot[] {
try {
const value: unknown = JSON.parse(localStorage.getItem(adCacheStorageKey) ?? "null");
if (!value || typeof value !== "object" || !Array.isArray((value as { slots?: unknown }).slots)) return [];
return (value as { slots: AdSlot[] }).slots;
} catch {
return [];
}
}
export function saveCachedAds(slots: AdSlot[]): void {
try {
localStorage.setItem(adCacheStorageKey, JSON.stringify({ slots }));
} catch {
// The current session still uses the fetched ads when storage is unavailable.
}
}