From b6b6e1809a910d18a53bf938fbbb8b02718ee319 Mon Sep 17 00:00:00 2001 From: Philipinho <16838612+Philipinho@users.noreply.github.com> Date: Sat, 18 Apr 2026 16:47:05 +0100 Subject: [PATCH] feat(base): reconcile bulk delete over socket + prune selection --- .../features/base/hooks/use-base-socket.ts | 46 ++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/apps/client/src/features/base/hooks/use-base-socket.ts b/apps/client/src/features/base/hooks/use-base-socket.ts index fa036a41..020e2c70 100644 --- a/apps/client/src/features/base/hooks/use-base-socket.ts +++ b/apps/client/src/features/base/hooks/use-base-socket.ts @@ -1,5 +1,5 @@ import { useEffect } from "react"; -import { useAtomValue } from "jotai"; +import { useAtomValue, getDefaultStore } from "jotai"; import { useQueryClient, InfiniteData } from "@tanstack/react-query"; import { socketAtom } from "@/features/websocket/atoms/socket-atom"; import { @@ -7,6 +7,7 @@ import { IBaseRow, IBaseView, } from "@/features/base/types/base.types"; +import { selectedRowIdsAtom } from "@/features/base/atoms/base-atoms"; import { IPagination } from "@/lib/types"; type BaseRowCreated = { @@ -31,6 +32,13 @@ type BaseRowDeleted = { requestId?: string | null; }; +type BaseRowsDeleted = { + operation: "base:rows:deleted"; + baseId: string; + rowIds: string[]; + requestId?: string | null; +}; + type BaseRowReordered = { operation: "base:row:reordered"; baseId: string; @@ -65,6 +73,7 @@ type BaseInboundEvent = | BaseRowCreated | BaseRowUpdated | BaseRowDeleted + | BaseRowsDeleted | BaseRowReordered | BasePropertyEvent | BaseViewEvent @@ -173,6 +182,41 @@ export function useBaseSocket(baseId: string | undefined): void { })), }, ); + const store = getDefaultStore(); + const current = store.get(selectedRowIdsAtom); + if (current.has(e.rowId)) { + const next = new Set(current); + next.delete(e.rowId); + store.set(selectedRowIdsAtom, next); + } + break; + } + case "base:rows:deleted": { + const e = event as BaseRowsDeleted; + const removeSet = new Set(e.rowIds); + queryClient.setQueriesData>>( + { queryKey: ["base-rows", baseId] }, + (old) => { + if (!old) return old; + return { + ...old, + pages: old.pages.map((page) => ({ + ...page, + items: page.items.filter((row) => !removeSet.has(row.id)), + })), + }; + }, + ); + const store = getDefaultStore(); + const current = store.get(selectedRowIdsAtom); + if (current.size > 0) { + let changed = false; + const next = new Set(current); + for (const id of e.rowIds) { + if (next.delete(id)) changed = true; + } + if (changed) store.set(selectedRowIdsAtom, next); + } break; } case "base:row:reordered": {