import { useEffect } from 'react'; import { useAtomValue } from 'jotai'; import { MatrixEvent, Room, RoomEvent } from 'matrix-js-sdk'; import { useMatrixClient } from '../hooks/useMatrixClient'; import { searchCacheEnabledAtom } from '../state/searchCacheEnabled'; import { clearRoom, deleteRow } from './searchCache'; /** * Gitea #14 — the persistent search cache (`searchCache.ts`) had no * invalidation path other than logout or the manual "Clear cached index" * button, so redacted messages and rooms the user left kept their decrypted * plaintext searchable on disk indefinitely. * * While the cache is enabled, listen client-wide for redactions (delete the * redacted row) and for leaving/being banned from a room (wipe the room's * cached rows via the existing `clearRoom`). */ export const useSearchCacheInvalidation = (): void => { const mx = useMatrixClient(); const cacheEnabled = useAtomValue(searchCacheEnabledAtom); useEffect(() => { if (!cacheEnabled) return undefined; const onRedaction = (event: MatrixEvent, room: Room) => { const redactedEventId = event.getAssociatedId(); if (redactedEventId) deleteRow(room.roomId, redactedEventId); }; const onMyMembership = (room: Room, membership: string) => { if (membership === 'leave' || membership === 'ban') { clearRoom(room.roomId); } }; mx.on(RoomEvent.Redaction, onRedaction); mx.on(RoomEvent.MyMembership, onMyMembership); return () => { mx.off(RoomEvent.Redaction, onRedaction); mx.off(RoomEvent.MyMembership, onMyMembership); }; }, [mx, cacheEnabled]); };