mirror of
https://wget.la/https://github.com/leookun/cursor-byok
synced 2026-10-08 15:43:10 +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 { api } from "../shared/api";
|
||||||
import { AdMenu } from "./ads/AdMenu";
|
import { AdMenu } from "./ads/AdMenu";
|
||||||
import { FloatingAd } from "./ads/FloatingAd";
|
import { FloatingAd } from "./ads/FloatingAd";
|
||||||
|
import { loadCachedAds, saveCachedAds } from "./ads/cache";
|
||||||
import { AdActionType, type AdAction, type AdSlot } from "./ads/types";
|
import { AdActionType, type AdAction, type AdSlot } from "./ads/types";
|
||||||
import { PageLayout } from "./layout/PageLayout";
|
import { PageLayout } from "./layout/PageLayout";
|
||||||
import { Card } from "../shared/ui/Card";
|
import { Card } from "../shared/ui/Card";
|
||||||
@@ -50,7 +51,7 @@ export function AppLayout() {
|
|||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const [leftActionTarget, setLeftActionTarget] = useState<HTMLDivElement | null>(null);
|
const [leftActionTarget, setLeftActionTarget] = useState<HTMLDivElement | null>(null);
|
||||||
const [rightActionTarget, setRightActionTarget] = 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 [activeAd, setActiveAd] = useState<AdSlot | null>(null);
|
||||||
const [dismissCandidate, setDismissCandidate] = useState<AdSlot | null>(null);
|
const [dismissCandidate, setDismissCandidate] = useState<AdSlot | null>(null);
|
||||||
const [dismissReason, setDismissReason] = useState("");
|
const [dismissReason, setDismissReason] = useState("");
|
||||||
@@ -98,6 +99,8 @@ export function AppLayout() {
|
|||||||
let disposed = false;
|
let disposed = false;
|
||||||
let pending = false;
|
let pending = false;
|
||||||
let lastRequestedAt = 0;
|
let lastRequestedAt = 0;
|
||||||
|
setAds(loadCachedAds());
|
||||||
|
setActiveAd(null);
|
||||||
const refreshAds = () => {
|
const refreshAds = () => {
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
if (pending || now - lastRequestedAt < 10_000) return;
|
if (pending || now - lastRequestedAt < 10_000) return;
|
||||||
@@ -105,6 +108,7 @@ export function AppLayout() {
|
|||||||
lastRequestedAt = now;
|
lastRequestedAt = now;
|
||||||
void api.ads(dismissedAdIdsRef.current, locale)
|
void api.ads(dismissedAdIdsRef.current, locale)
|
||||||
.then((runtime) => {
|
.then((runtime) => {
|
||||||
|
saveCachedAds(runtime.slots);
|
||||||
if (disposed) return;
|
if (disposed) return;
|
||||||
setAds(runtime.slots);
|
setAds(runtime.slots);
|
||||||
setActiveAd((current) => current
|
setActiveAd((current) => current
|
||||||
@@ -112,9 +116,7 @@ export function AppLayout() {
|
|||||||
: null);
|
: null);
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
if (disposed) return;
|
// Keep the current ads and local cache available when refreshing fails.
|
||||||
setAds([]);
|
|
||||||
setActiveAd(null);
|
|
||||||
})
|
})
|
||||||
.finally(() => { pending = false; });
|
.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