feat: unread indicators + DM bug fixes + data-driven isDmChannel
- Fix stale message cache: add force param to loadMessages, clearAllMessages action - Fix reload race condition: URL-based isDmChannel fallback before WS ready - Add read_states DB table for persistent unread tracking - Add channel_ack WS event (client→server→echo) with BigInt comparison - Wire up unread state in chatStore (readStates, unreadChannels, ackChannel) - Auto-ack channels on MessageList view (200ms debounced) - Unread pill indicators on server icons in ServerSidebar - Bold text + white dot on unread channels/DMs in ChannelSidebar - Replace all showDms reads with data-driven isDmChannel() across 8 files - Design system, UI polish, and component fixes from previous sessions
This commit is contained in:
@@ -39,16 +39,27 @@ export function MessageList({ channelId }: MessageListProps) {
|
||||
const loadMoreMessages = useChatStore((s) => s.loadMoreMessages);
|
||||
const isLoading = useChatStore((s) => s.isLoading);
|
||||
const hasMore = useChatStore((s) => s.hasMore.get(channelId) ?? true);
|
||||
const ackChannel = useChatStore((s) => s.ackChannel);
|
||||
const bottomRef = useRef<HTMLDivElement>(null);
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const [isNearBottom, setIsNearBottom] = useState(true);
|
||||
const [isLoadingMore, setIsLoadingMore] = useState(false);
|
||||
const prevMessagesLength = useRef(0);
|
||||
const ackTimerRef = useRef<ReturnType<typeof setTimeout>>();
|
||||
|
||||
useEffect(() => {
|
||||
loadMessages(channelId);
|
||||
}, [channelId, loadMessages]);
|
||||
|
||||
// Ack channel when messages load or when new messages arrive while near bottom
|
||||
useEffect(() => {
|
||||
if (messages.length > 0 && isNearBottom) {
|
||||
clearTimeout(ackTimerRef.current);
|
||||
ackTimerRef.current = setTimeout(() => ackChannel(channelId), 200);
|
||||
}
|
||||
return () => clearTimeout(ackTimerRef.current);
|
||||
}, [channelId, messages.length, isNearBottom, ackChannel]);
|
||||
|
||||
// Auto-scroll to bottom on new messages (if near bottom)
|
||||
useEffect(() => {
|
||||
if (messages.length > prevMessagesLength.current && isNearBottom) {
|
||||
@@ -98,7 +109,7 @@ export function MessageList({ channelId }: MessageListProps) {
|
||||
return (
|
||||
<div
|
||||
ref={containerRef}
|
||||
className="flex-1 overflow-y-auto overflow-x-hidden"
|
||||
className="flex-1 overflow-y-auto overflow-x-hidden scrollbar-thin"
|
||||
onScroll={handleScroll}
|
||||
>
|
||||
{isLoadingMore && (
|
||||
|
||||
Reference in New Issue
Block a user