mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-07-25 13:45:03 +08:00
29e87487a1
Closes #2139 Two related defects let the installed-skills count balloon when users tap the import confirm button multiple times — either deliberately or because the button is still clickable while a slow import is in flight: - The confirm button only disabled itself while `selected.size === 0`, so it stayed clickable during a pending mutation. Each extra click triggered another `importFromApps` mutation. - `useImportSkillsFromApps` appended the server response to the installed cache without deduping, so re-firing the mutation stacked the same skills into the list again. Disable the confirm (and cancel) buttons while the mutation is pending — matching the `isRestoring` / `isDeleting` pattern already used by `RestoreSkillsDialog` — and merge success payloads by `InstalledSkill.id` so repeated results overwrite rather than accumulate. The merge is extracted as a pure `mergeImportedSkills` reducer to make the behaviour unit-testable and to short-circuit on an empty payload, returning the existing reference so React Query does not notify subscribers about a no-op cache update.
20 lines
733 B
TypeScript
20 lines
733 B
TypeScript
import type { InstalledSkill } from "@/lib/api/skills";
|
|
|
|
/**
|
|
* 合并本次导入结果到已安装缓存,按 id 去重。
|
|
*
|
|
* 同一技能重复出现时以新记录为准,避免 mutation 被重复触发时
|
|
* 在 installed 列表中看到重复条目。imported 为空时返回原引用,
|
|
* 让 React Query 跳过无谓的订阅者通知。
|
|
*/
|
|
export function mergeImportedSkills(
|
|
existing: InstalledSkill[] | undefined,
|
|
imported: InstalledSkill[],
|
|
): InstalledSkill[] {
|
|
if (!existing) return imported;
|
|
if (imported.length === 0) return existing;
|
|
const importedIds = new Set(imported.map((s) => s.id));
|
|
const preserved = existing.filter((s) => !importedIds.has(s.id));
|
|
return [...preserved, ...imported];
|
|
}
|