44 lines
1.6 KiB
TypeScript
44 lines
1.6 KiB
TypeScript
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]);
|
||
|
|
};
|