import React from 'react';
import Box from '@mui/material/Box';
import Paper from '@mui/material/Paper';
import IconButton from '@mui/material/IconButton';
import ChatIcon from '@mui/icons-material/Chat';
import OpenInNewIcon from '@mui/icons-material/OpenInNew';
import Typography from '@mui/material/Typography';
import Avatar from '@mui/material/Avatar';
import Badge from '@mui/material/Badge';
import Toolbar from '@mui/material/Toolbar';
import Tooltip from '@mui/material/Tooltip';
import List from '@mui/material/List';
import ListItem from '@mui/material/ListItem';
import { useLayout } from '../../contexts/LayoutContext';
import { ChatProvider, useChat } from '../../contexts/ChatContext';
import { Link } from 'react-router-dom';
import { useQuery, useQueryClient } from '@tanstack/react-query';
import { configApi } from '../../services/config';
import { notificationsApi } from '../../services/notifications';
import { nextcloudApi } from '../../services/nextcloud';
import { safeOpenUrl } from '../../utils/safeOpenUrl';
import ChatRoomList from './ChatRoomList';
import ChatMessageView from './ChatMessageView';
const TRANSITION = 'width 225ms cubic-bezier(0.4, 0, 0.6, 1)';
const COLLAPSED_WIDTH = 64;
const EXPANDED_WIDTH = 360;
const ChatPanelInner: React.FC = () => {
const { chatPanelOpen, setChatPanelOpen } = useLayout();
const { rooms, selectedRoomToken, selectRoom, connected } = useChat();
const queryClient = useQueryClient();
const { data: externalLinks } = useQuery({
queryKey: ['external-links'],
queryFn: () => configApi.getExternalLinks(),
staleTime: 10 * 60 * 1000,
});
const nextcloudUrl = externalLinks?.nextcloud;
// Dismiss internal notifications when panel opens
React.useEffect(() => {
if (!chatPanelOpen) return;
notificationsApi.dismissByType('nextcloud_talk').then(() => {
queryClient.invalidateQueries({ queryKey: ['notifications'] });
queryClient.invalidateQueries({ queryKey: ['unreadNotificationCount'] });
}).catch(() => {});
}, [chatPanelOpen, queryClient]);
// Mark unread rooms as read in Nextcloud whenever panel is open and rooms update
React.useEffect(() => {
if (!chatPanelOpen) return;
const unread = rooms.filter((r) => r.unreadMessages > 0);
if (unread.length === 0) return;
Promise.allSettled(unread.map((r) => nextcloudApi.markAsRead(r.token))).then(() => {
queryClient.invalidateQueries({ queryKey: ['nextcloud', 'rooms'] });
});
}, [chatPanelOpen, rooms, queryClient]);
// Mark the selected room as read when a conversation is opened
React.useEffect(() => {
if (!selectedRoomToken) return;
nextcloudApi.markAsRead(selectedRoomToken).then(() => {
queryClient.invalidateQueries({ queryKey: ['nextcloud', 'rooms'] });
}).catch(() => {});
}, [selectedRoomToken, queryClient]);
if (!chatPanelOpen) {
return (
setChatPanelOpen(true)} aria-label="Chat öffnen">
{connected && (
{rooms.map((room) => (
{
setChatPanelOpen(true);
selectRoom(room.token);
}}
sx={{ p: 0.5 }}
>
{room.displayName.substring(0, 2).toUpperCase()}
))}
)}
);
}
return (
theme.zIndex.drawer + 2, sm: 'auto' },
height: { xs: '100vh', sm: '100vh' },
display: 'flex',
flexDirection: 'column',
flexShrink: 0,
transition: TRANSITION,
overflow: 'hidden',
}}
>
Chat
{nextcloudUrl && (
safeOpenUrl(`${nextcloudUrl}/apps/spreed`)} aria-label="In Nextcloud öffnen">
)}
setChatPanelOpen(false)} aria-label="Chat einklappen">
{!connected ? (
Nextcloud nicht verbunden. Bitte verbinden Sie sich in den Einstellungen.
) : selectedRoomToken ? (
) : (
)}
);
};
const ChatPanel: React.FC = () => {
return (
);
};
export default ChatPanel;