mirror of
https://wget.la/https://github.com/leookun/cursor-byok
synced 2026-10-04 02:52:55 +08:00
fix(desktop): cache ads across refresh failures
This commit is contained in:
@@ -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; });
|
||||
};
|
||||
|
||||
@@ -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.
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user