resolve issues with new features
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import { useState, useRef, useEffect, useCallback } from 'react';
|
||||
import {
|
||||
Container,
|
||||
Typography,
|
||||
@@ -12,17 +13,25 @@ import {
|
||||
ToggleButtonGroup,
|
||||
ToggleButton,
|
||||
CircularProgress,
|
||||
Button,
|
||||
Chip,
|
||||
} from '@mui/material';
|
||||
import { Settings as SettingsIcon, Notifications, Palette, Language, SettingsBrightness, LightMode, DarkMode, Widgets } from '@mui/icons-material';
|
||||
import { Settings as SettingsIcon, Notifications, Palette, Language, SettingsBrightness, LightMode, DarkMode, Widgets, Cloud, LinkOff, Forum } from '@mui/icons-material';
|
||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import DashboardLayout from '../components/dashboard/DashboardLayout';
|
||||
import { useThemeMode } from '../contexts/ThemeContext';
|
||||
import { preferencesApi } from '../services/settings';
|
||||
import { WIDGETS, WidgetKey } from '../constants/widgets';
|
||||
import { nextcloudApi } from '../services/nextcloud';
|
||||
import { useNotification } from '../contexts/NotificationContext';
|
||||
|
||||
const POLL_INTERVAL = 2000;
|
||||
const POLL_TIMEOUT = 5 * 60 * 1000;
|
||||
|
||||
function Settings() {
|
||||
const { themeMode, setThemeMode } = useThemeMode();
|
||||
const queryClient = useQueryClient();
|
||||
const { showInfo } = useNotification();
|
||||
|
||||
const { data: preferences, isLoading: prefsLoading } = useQuery({
|
||||
queryKey: ['user-preferences'],
|
||||
@@ -47,6 +56,98 @@ function Settings() {
|
||||
mutation.mutate({ ...current, widgets });
|
||||
};
|
||||
|
||||
// Nextcloud Talk connection
|
||||
const { data: ncData, isLoading: ncLoading } = useQuery({
|
||||
queryKey: ['nextcloud-talk-rooms'],
|
||||
queryFn: () => nextcloudApi.getRooms(),
|
||||
retry: 1,
|
||||
});
|
||||
|
||||
const ncConnected = ncData?.connected ?? false;
|
||||
const ncLoginName = ncData?.loginName;
|
||||
|
||||
const [isConnecting, setIsConnecting] = useState(false);
|
||||
const pollIntervalRef = useRef<ReturnType<typeof setInterval> | null>(null);
|
||||
const popupRef = useRef<Window | null>(null);
|
||||
|
||||
// Show one-time info snackbar when not connected
|
||||
useEffect(() => {
|
||||
if (!ncLoading && !ncConnected && !sessionStorage.getItem('nextcloud-talk-notified')) {
|
||||
sessionStorage.setItem('nextcloud-talk-notified', '1');
|
||||
showInfo('Nextcloud Talk ist nicht verbunden. Verbinde dich in den Einstellungen.');
|
||||
}
|
||||
}, [ncLoading, ncConnected, showInfo]);
|
||||
|
||||
const stopPolling = useCallback(() => {
|
||||
if (pollIntervalRef.current) {
|
||||
clearInterval(pollIntervalRef.current);
|
||||
pollIntervalRef.current = null;
|
||||
}
|
||||
if (popupRef.current && !popupRef.current.closed) {
|
||||
popupRef.current.close();
|
||||
}
|
||||
popupRef.current = null;
|
||||
setIsConnecting(false);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (pollIntervalRef.current) {
|
||||
clearInterval(pollIntervalRef.current);
|
||||
}
|
||||
if (popupRef.current && !popupRef.current.closed) {
|
||||
popupRef.current.close();
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
const handleConnect = async () => {
|
||||
try {
|
||||
setIsConnecting(true);
|
||||
const { loginUrl, pollToken, pollEndpoint } = await nextcloudApi.connect();
|
||||
|
||||
const popup = window.open(loginUrl, '_blank', 'width=600,height=700');
|
||||
popupRef.current = popup;
|
||||
|
||||
const startTime = Date.now();
|
||||
|
||||
pollIntervalRef.current = setInterval(async () => {
|
||||
if (Date.now() - startTime > POLL_TIMEOUT) {
|
||||
stopPolling();
|
||||
return;
|
||||
}
|
||||
|
||||
if (popup && popup.closed) {
|
||||
stopPolling();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await nextcloudApi.poll(pollToken, pollEndpoint);
|
||||
if (result.completed) {
|
||||
stopPolling();
|
||||
queryClient.invalidateQueries({ queryKey: ['nextcloud-talk'] });
|
||||
queryClient.invalidateQueries({ queryKey: ['nextcloud-talk-rooms'] });
|
||||
}
|
||||
} catch {
|
||||
// Polling error — keep trying until timeout
|
||||
}
|
||||
}, POLL_INTERVAL);
|
||||
} catch {
|
||||
setIsConnecting(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleDisconnect = async () => {
|
||||
try {
|
||||
await nextcloudApi.disconnect();
|
||||
queryClient.invalidateQueries({ queryKey: ['nextcloud-talk'] });
|
||||
queryClient.invalidateQueries({ queryKey: ['nextcloud-talk-rooms'] });
|
||||
} catch {
|
||||
// Disconnect failed silently
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<DashboardLayout>
|
||||
<Container maxWidth="lg">
|
||||
@@ -89,6 +190,67 @@ function Settings() {
|
||||
</Card>
|
||||
</Grid>
|
||||
|
||||
{/* Nextcloud Talk */}
|
||||
<Grid item xs={12} md={6}>
|
||||
<Card>
|
||||
<CardContent>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', mb: 2 }}>
|
||||
<Forum color="primary" sx={{ mr: 2 }} />
|
||||
<Typography variant="h6">Nextcloud Talk</Typography>
|
||||
</Box>
|
||||
<Divider sx={{ mb: 2 }} />
|
||||
{ncLoading ? (
|
||||
<Box sx={{ display: 'flex', justifyContent: 'center', py: 2 }}>
|
||||
<CircularProgress size={24} />
|
||||
</Box>
|
||||
) : ncConnected ? (
|
||||
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
|
||||
<Chip label="Verbunden" size="small" color="success" />
|
||||
{ncLoginName && (
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
als {ncLoginName}
|
||||
</Typography>
|
||||
)}
|
||||
</Box>
|
||||
<Button
|
||||
variant="outlined"
|
||||
color="error"
|
||||
startIcon={<LinkOff />}
|
||||
onClick={handleDisconnect}
|
||||
size="small"
|
||||
>
|
||||
Verbindung trennen
|
||||
</Button>
|
||||
</Box>
|
||||
) : (
|
||||
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
|
||||
<Chip label="Nicht verbunden" size="small" color="default" />
|
||||
</Box>
|
||||
{isConnecting ? (
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
|
||||
<CircularProgress size={20} />
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
Warte auf Bestätigung...
|
||||
</Typography>
|
||||
</Box>
|
||||
) : (
|
||||
<Button
|
||||
variant="outlined"
|
||||
startIcon={<Cloud />}
|
||||
onClick={handleConnect}
|
||||
size="small"
|
||||
>
|
||||
Mit Nextcloud verbinden
|
||||
</Button>
|
||||
)}
|
||||
</Box>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Grid>
|
||||
|
||||
{/* Notification Settings */}
|
||||
<Grid item xs={12} md={6}>
|
||||
<Card>
|
||||
|
||||
Reference in New Issue
Block a user