SkateSpots/src/hooks/useCordnRoomRead.ts

47 lines
1.5 KiB
TypeScript

import { useCallback, useEffect, useState } from 'react';
import {
cordnRoomReadEventName,
markCordnRoomActive,
markCordnRoomSeen,
readCordnRoomReads,
type CordnRoomReadMap,
} from '@/lib/cordnRoomRead';
/**
* Reactive view of {@link readCordnRoomReads}. Safe to mount on list pages:
* it only reads localStorage and listens for same-tab/cross-tab updates.
*/
export function useCordnRoomRead(pubkey: string | undefined) {
const [reads, setReads] = useState<CordnRoomReadMap>(() => readCordnRoomReads(pubkey));
useEffect(() => {
setReads(readCordnRoomReads(pubkey));
const onChange = (event: Event) => {
const detail = (event as CustomEvent<{ pubkey?: string; reads?: CordnRoomReadMap }>).detail;
if (!detail || detail.pubkey !== pubkey || !detail.reads) return;
setReads(detail.reads);
};
window.addEventListener(cordnRoomReadEventName(), onChange);
return () => window.removeEventListener(cordnRoomReadEventName(), onChange);
}, [pubkey]);
const isUnread = useCallback(
(gid: string | undefined) => {
if (!gid) return false;
const state = reads[gid];
return !!state && state.latestAt > state.seenAt;
},
[reads],
);
const markActive = useCallback(
(gid: string, latestAt: number) => markCordnRoomActive(pubkey, gid, latestAt),
[pubkey],
);
const markSeen = useCallback(
(gid: string, latestAt: number) => markCordnRoomSeen(pubkey, gid, latestAt),
[pubkey],
);
return { reads, isUnread, markActive, markSeen };
}