feat: add full-page chat route and sidebar menu ordering

This commit is contained in:
Matthias Hochmeister
2026-03-27 18:00:58 +01:00
parent 1a66a66aab
commit c1b4a92a12
7 changed files with 284 additions and 24 deletions

View File

@@ -1,5 +1,6 @@
import React, { createContext, useContext, useState, useCallback, useEffect, useRef, ReactNode } from 'react';
import { useQuery, useQueryClient } from '@tanstack/react-query';
import { useLocation } from 'react-router-dom';
import { nextcloudApi } from '../services/nextcloud';
import { useLayout } from './LayoutContext';
import { useNotification } from './NotificationContext';
@@ -24,7 +25,10 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({ children }) => {
const { chatPanelOpen } = useLayout();
const { showNotificationToast } = useNotification();
const queryClient = useQueryClient();
const location = useLocation();
const onChatPage = location.pathname === '/chat';
const prevPanelOpenRef = useRef(chatPanelOpen);
const prevOnChatPageRef = useRef(onChatPage);
const prevUnreadRef = useRef<Map<string, number>>(new Map());
// Invalidate rooms/connection when panel opens so data is fresh immediately
@@ -36,10 +40,21 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({ children }) => {
prevPanelOpenRef.current = chatPanelOpen;
}, [chatPanelOpen, queryClient]);
// Invalidate rooms/connection when navigating to the chat page
useEffect(() => {
if (onChatPage && !prevOnChatPageRef.current) {
queryClient.invalidateQueries({ queryKey: ['nextcloud', 'connection'] });
queryClient.invalidateQueries({ queryKey: ['nextcloud', 'rooms'] });
}
prevOnChatPageRef.current = onChatPage;
}, [onChatPage, queryClient]);
const isActive = chatPanelOpen || onChatPage;
const { data: connData } = useQuery({
queryKey: ['nextcloud', 'connection'],
queryFn: () => nextcloudApi.getConversations(),
refetchInterval: chatPanelOpen ? 5000 : 15000,
refetchInterval: isActive ? 5000 : 15000,
retry: false,
});
@@ -48,7 +63,7 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({ children }) => {
const { data } = useQuery({
queryKey: ['nextcloud', 'rooms'],
queryFn: () => nextcloudApi.getRooms(),
refetchInterval: chatPanelOpen ? 5000 : 15000,
refetchInterval: isActive ? 5000 : 15000,
enabled: isConnected,
});
@@ -65,7 +80,7 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({ children }) => {
}
}, [isConnected]);
// Detect new unread messages while panel is closed and show toast
// Detect new unread messages while panel is closed and not on chat page — show toast
useEffect(() => {
if (!rooms.length) return;
const prev = prevUnreadRef.current;
@@ -81,7 +96,7 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({ children }) => {
for (const room of rooms) {
const prevCount = prev.get(room.token) ?? 0;
if (!chatPanelOpen && room.unreadMessages > prevCount) {
if (!chatPanelOpen && !onChatPage && room.unreadMessages > prevCount) {
showNotificationToast(room.displayName, 'info');
}
prev.set(room.token, room.unreadMessages);
@@ -92,7 +107,7 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({ children }) => {
for (const key of prev.keys()) {
if (!currentTokens.has(key)) prev.delete(key);
}
}, [rooms, chatPanelOpen, showNotificationToast]);
}, [rooms, chatPanelOpen, onChatPage, showNotificationToast]);
const selectRoom = useCallback((token: string | null) => {
setSelectedRoomToken(token);