Files
cc-switch/src/hooks/useUsageCacheBridge.ts
T
zcb 8cdaf90d8d refactor: replace JSON deep copy with deepClone helper and extract useTauriEvent hook (#3140)
* refactor: replace JSON.parse(JSON.stringify()) with structuredClone and extract useTauriEvent hook

Replace all `JSON.parse(JSON.stringify())` deep copy patterns with native
`structuredClone()` across production source (9 occurrences), tests (11
occurrences), and a hand-rolled `deepClone` utility in providerConfigUtils.ts.
Add "ES2022" to tsconfig lib for type support.

Extract a `useTauriEvent` hook to eliminate the repeated Tauri event listener
boilerplate (`useEffect` + `active/disposed` flag + async `listen`) that was
duplicated across App.tsx (3 listeners) and useUsageCacheBridge.ts. The hook
handles async registration, race-condition guards, and cleanup automatically.

* fix: add compatible deepClone helper

- Add a shared deepClone helper with a structuredClone runtime guard and fallback.
- Route clone call sites through the helper.
- Preserve universal-provider-synced listener ordering and drop the dead-directory diff.

* fix: harden Tauri event handling

- Guard WebDAV sync status events against missing payloads.
- Preserve settings query invalidation ordering before showing auto-sync errors.
- Simplify useTauriEvent subscriptions to avoid dependency-driven re-listens.

---------

Co-authored-by: zcb <zhangchongbiao@qiyuanlab.com>
Co-authored-by: Jason <farion1231@gmail.com>
2026-05-26 23:39:16 +08:00

44 lines
1.4 KiB
TypeScript

import { useQueryClient } from "@tanstack/react-query";
import type { AppId } from "@/lib/api/types";
import type { UsageResult } from "@/types";
import type { SubscriptionQuota } from "@/types/subscription";
import { usageKeys } from "@/lib/query/usage";
import { subscriptionKeys } from "@/lib/query/subscription";
import { useTauriEvent } from "./useTauriEvent";
type UsageCacheUpdatedPayload =
| {
kind: "script";
appType: AppId;
providerId: string;
data: UsageResult;
}
| {
kind: "subscription";
appType: AppId;
data: SubscriptionQuota;
};
/**
* 后端 `UsageCache` 写入后会 emit `usage-cache-updated`,本 hook 把 payload 同步到
* React Query 缓存,让托盘触发的刷新(不经前端)也能立刻反映到主界面,避免
* React Query 与 Rust 侧两份缓存各自为战。
*/
export function useUsageCacheBridge() {
const queryClient = useQueryClient();
useTauriEvent<UsageCacheUpdatedPayload>("usage-cache-updated", (payload) => {
if (payload.kind === "script") {
queryClient.setQueryData<UsageResult>(
usageKeys.script(payload.providerId, payload.appType),
payload.data,
);
} else if (payload.kind === "subscription") {
queryClient.setQueryData<SubscriptionQuota>(
subscriptionKeys.quota(payload.appType),
payload.data,
);
}
});
}