update
This commit is contained in:
@@ -24,6 +24,8 @@ const ChatMessageView: React.FC = () => {
|
||||
const { chatPanelOpen } = useLayout();
|
||||
const queryClient = useQueryClient();
|
||||
const messagesEndRef = useRef<HTMLDivElement>(null);
|
||||
const scrollContainerRef = useRef<HTMLDivElement>(null);
|
||||
const isInitialLoadRef = useRef(true);
|
||||
const [input, setInput] = useState('');
|
||||
const [messages, setMessages] = useState<NextcloudMessage[]>([]);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
@@ -63,6 +65,7 @@ const ChatMessageView: React.FC = () => {
|
||||
setIsLoading(true);
|
||||
setMessages([]);
|
||||
setReactionsMap(new Map());
|
||||
isInitialLoadRef.current = true;
|
||||
lastMsgIdRef.current = 0;
|
||||
|
||||
// Step 1: Initial fetch — Nextcloud returns newest-first, so reverse for chronological display
|
||||
@@ -143,17 +146,31 @@ const ChatMessageView: React.FC = () => {
|
||||
},
|
||||
});
|
||||
|
||||
// Mark room as read while viewing messages
|
||||
// Mark room as read when first opened
|
||||
useEffect(() => {
|
||||
if (selectedRoomToken && chatPanelOpen) {
|
||||
nextcloudApi.markAsRead(selectedRoomToken).then(() => {
|
||||
queryClient.invalidateQueries({ queryKey: ['nextcloud', 'rooms'] });
|
||||
}).catch(() => {});
|
||||
}
|
||||
}, [selectedRoomToken, chatPanelOpen, queryClient, messages.length]);
|
||||
}, [selectedRoomToken, chatPanelOpen, queryClient]);
|
||||
|
||||
// Smart scroll: instant on initial load, smooth only when user is near bottom
|
||||
useEffect(() => {
|
||||
messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
|
||||
if (!messagesEndRef.current) return;
|
||||
if (isInitialLoadRef.current) {
|
||||
messagesEndRef.current.scrollIntoView();
|
||||
if (messages.length > 0) isInitialLoadRef.current = false;
|
||||
return;
|
||||
}
|
||||
const container = scrollContainerRef.current;
|
||||
if (container) {
|
||||
const { scrollHeight, scrollTop, clientHeight } = container;
|
||||
const isNearBottom = scrollHeight - scrollTop - clientHeight < 150;
|
||||
if (isNearBottom) {
|
||||
messagesEndRef.current.scrollIntoView({ behavior: 'smooth' });
|
||||
}
|
||||
}
|
||||
}, [messages]);
|
||||
|
||||
const handleSend = () => {
|
||||
@@ -230,6 +247,7 @@ const ChatMessageView: React.FC = () => {
|
||||
</Box>
|
||||
|
||||
<Box
|
||||
ref={scrollContainerRef}
|
||||
sx={{
|
||||
flex: 1,
|
||||
overflow: 'auto',
|
||||
|
||||
@@ -30,6 +30,7 @@ const ChatPanelInner: React.FC = () => {
|
||||
const { chatPanelOpen, setChatPanelOpen } = useLayout();
|
||||
const { rooms, selectedRoomToken, selectRoom, connected } = useChat();
|
||||
const queryClient = useQueryClient();
|
||||
const markedRoomsRef = React.useRef(new Set<string>());
|
||||
const { data: externalLinks } = useQuery({
|
||||
queryKey: ['external-links'],
|
||||
queryFn: () => configApi.getExternalLinks(),
|
||||
@@ -46,11 +47,17 @@ const ChatPanelInner: React.FC = () => {
|
||||
}).catch(() => {});
|
||||
}, [chatPanelOpen, queryClient]);
|
||||
|
||||
// Mark unread rooms as read in Nextcloud whenever panel is open and rooms update
|
||||
// Mark unread rooms as read in Nextcloud whenever panel is open
|
||||
React.useEffect(() => {
|
||||
if (!chatPanelOpen) return;
|
||||
const unread = rooms.filter((r) => r.unreadMessages > 0);
|
||||
if (!chatPanelOpen) {
|
||||
markedRoomsRef.current.clear();
|
||||
return;
|
||||
}
|
||||
const unread = rooms.filter(
|
||||
(r) => r.unreadMessages > 0 && !markedRoomsRef.current.has(r.token),
|
||||
);
|
||||
if (unread.length === 0) return;
|
||||
unread.forEach((r) => markedRoomsRef.current.add(r.token));
|
||||
Promise.allSettled(unread.map((r) => nextcloudApi.markAsRead(r.token))).then(() => {
|
||||
queryClient.invalidateQueries({ queryKey: ['nextcloud', 'rooms'] });
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState } from 'react';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import Dialog from '@mui/material/Dialog';
|
||||
import DialogTitle from '@mui/material/DialogTitle';
|
||||
import DialogContent from '@mui/material/DialogContent';
|
||||
@@ -25,6 +25,14 @@ const NewChatDialog: React.FC<NewChatDialogProps> = ({ open, onClose, onRoomCrea
|
||||
const [search, setSearch] = useState('');
|
||||
const [creating, setCreating] = useState(false);
|
||||
|
||||
// Reset state when dialog opens
|
||||
useEffect(() => {
|
||||
if (open) {
|
||||
setSearch('');
|
||||
setCreating(false);
|
||||
}
|
||||
}, [open]);
|
||||
|
||||
const { data: users, isLoading } = useQuery({
|
||||
queryKey: ['nextcloud', 'users', search],
|
||||
queryFn: () => nextcloudApi.searchUsers(search),
|
||||
|
||||
Reference in New Issue
Block a user