49 lines
1.3 KiB
TypeScript
49 lines
1.3 KiB
TypeScript
import { listPinnedMessages, type PinnedMessage } from '@chat-app/shared/chat';
|
|
import { useEffect, useState } from 'react';
|
|
|
|
import { supabase } from './supabase';
|
|
|
|
// Live list of pinned messages for one conversation. Subscribes to the
|
|
// `pinned_messages` realtime channel for the conv so the header pill +
|
|
// side-panel update without a refetch.
|
|
export function usePinnedMessages(conversationId: string | undefined): PinnedMessage[] {
|
|
const [pins, setPins] = useState<PinnedMessage[]>([]);
|
|
|
|
useEffect(() => {
|
|
if (!conversationId) {
|
|
setPins([]);
|
|
return;
|
|
}
|
|
let cancelled = false;
|
|
|
|
void listPinnedMessages(supabase, conversationId).then((rows) => {
|
|
if (!cancelled) setPins(rows);
|
|
});
|
|
|
|
const channel = supabase
|
|
.channel('pinned_messages:' + conversationId)
|
|
.on(
|
|
'postgres_changes',
|
|
{
|
|
event: '*',
|
|
schema: 'public',
|
|
table: 'pinned_messages',
|
|
filter: 'conversation_id=eq.' + conversationId,
|
|
},
|
|
() => {
|
|
void listPinnedMessages(supabase, conversationId).then((rows) => {
|
|
if (!cancelled) setPins(rows);
|
|
});
|
|
},
|
|
)
|
|
.subscribe();
|
|
|
|
return () => {
|
|
cancelled = true;
|
|
void supabase.removeChannel(channel);
|
|
};
|
|
}, [conversationId]);
|
|
|
|
return pins;
|
|
}
|