From e929a21e371b9ef17289484eac90bf691401733c Mon Sep 17 00:00:00 2001 From: viown <48097677+viown@users.noreply.github.com> Date: Fri, 27 Jun 2025 05:53:39 +0300 Subject: [PATCH] Use skeleton loading where possible --- .../components/widgets/ActivityLogWidget.tsx | 49 +++++++++----- .../components/widgets/AlertsLogWidget.tsx | 24 ++++--- .../components/widgets/DevicesWidget.tsx | 8 +-- .../components/widgets/ItemCountsWidget.tsx | 8 +-- .../components/widgets/ServerInfoWidget.tsx | 25 +++++-- .../components/widgets/ServerPathWidget.tsx | 8 +-- src/apps/dashboard/routes/index.tsx | 66 ++++--------------- 7 files changed, 90 insertions(+), 98 deletions(-) diff --git a/src/apps/dashboard/components/widgets/ActivityLogWidget.tsx b/src/apps/dashboard/components/widgets/ActivityLogWidget.tsx index 847af0edb..663053b6f 100644 --- a/src/apps/dashboard/components/widgets/ActivityLogWidget.tsx +++ b/src/apps/dashboard/components/widgets/ActivityLogWidget.tsx @@ -1,29 +1,48 @@ -import React from 'react'; +import React, { useMemo } from 'react'; import globalize from 'lib/globalize'; import Widget from './Widget'; import List from '@mui/material/List'; import ActivityListItem from 'apps/dashboard/features/activity/components/ActivityListItem'; -import type { ActivityLogEntry } from '@jellyfin/sdk/lib/generated-client/models/activity-log-entry'; +import { useLogEntries } from 'apps/dashboard/features/activity/api/useLogEntries'; +import subSeconds from 'date-fns/subSeconds'; +import Skeleton from '@mui/material/Skeleton'; +import Stack from '@mui/material/Stack'; -type IProps = { - logs?: ActivityLogEntry[]; -}; +const ActivityLogWidget = () => { + const dayBefore = useMemo(() => ( + subSeconds(new Date(), 24 * 60 * 60).toISOString() + ), []); + + const { data: logs, isPending } = useLogEntries({ + startIndex: 0, + limit: 7, + minDate: dayBefore, + hasUserId: true + }); -const ActivityLogWidget = ({ logs }: IProps) => { return ( - - {logs?.map(entry => ( - - ))} - + {isPending ? ( + + + + + + + ) : ( + + {logs?.Items?.map(entry => ( + + ))} + + )} ); }; diff --git a/src/apps/dashboard/components/widgets/AlertsLogWidget.tsx b/src/apps/dashboard/components/widgets/AlertsLogWidget.tsx index f1147b49d..c665e7293 100644 --- a/src/apps/dashboard/components/widgets/AlertsLogWidget.tsx +++ b/src/apps/dashboard/components/widgets/AlertsLogWidget.tsx @@ -1,16 +1,24 @@ -import React from 'react'; +import React, { useMemo } from 'react'; import globalize from 'lib/globalize'; import Widget from './Widget'; import List from '@mui/material/List'; import ActivityListItem from 'apps/dashboard/features/activity/components/ActivityListItem'; -import type { ActivityLogEntry } from '@jellyfin/sdk/lib/generated-client/models'; +import subSeconds from 'date-fns/subSeconds'; +import { useLogEntries } from 'apps/dashboard/features/activity/api/useLogEntries'; -type IProps = { - alerts?: ActivityLogEntry[]; -}; +const AlertsLogWidget = () => { + const weekBefore = useMemo(() => ( + subSeconds(new Date(), 7 * 24 * 60 * 60).toISOString() + ), []); -const AlertsLogWidget = ({ alerts }: IProps) => { - if (alerts?.length == 0) return null; + const { data: alerts, isPending } = useLogEntries({ + startIndex: 0, + limit: 4, + minDate: weekBefore, + hasUserId: false + }); + + if (isPending || alerts?.Items?.length == 0) return null; return ( { href='/dashboard/activity?useractivity=false' > - {alerts?.map(entry => ( + {alerts?.Items?.map(entry => ( { + const { data: devices } = useLiveSessions(); -const DevicesWidget = ({ devices }: IProps) => { return ( { + const { data: counts } = useItemCounts(); -const ItemCountsWidget = ({ counts }: IProps) => { return ( void; }; -const ServerInfoWidget = ({ systemInfo, onScanLibrariesClick, onRestartClick, onShutdownClick }: IProps) => { +const ServerInfoWidget = ({ onScanLibrariesClick, onRestartClick, onShutdownClick }: IProps) => { + const { data: systemInfo, isPending } = useSystemInfo(); + return ( {globalize.translate('LabelBuildVersion')} - {systemInfo?.ServerName} - {systemInfo?.Version} - {__PACKAGE_JSON_VERSION__} - {__JF_BUILD_VERSION__} + {isPending ? ( + <> + + + + + + ) : ( + <> + {systemInfo?.ServerName} + {systemInfo?.Version} + {__PACKAGE_JSON_VERSION__} + {__JF_BUILD_VERSION__} + + )} diff --git a/src/apps/dashboard/components/widgets/ServerPathWidget.tsx b/src/apps/dashboard/components/widgets/ServerPathWidget.tsx index 93d900cd3..36f673a32 100644 --- a/src/apps/dashboard/components/widgets/ServerPathWidget.tsx +++ b/src/apps/dashboard/components/widgets/ServerPathWidget.tsx @@ -3,13 +3,11 @@ import React from 'react'; import StorageListItem from 'apps/dashboard/features/storage/components/StorageListItem'; import globalize from 'lib/globalize'; import Widget from './Widget'; -import type { SystemStorageDto } from '@jellyfin/sdk/lib/generated-client/models/system-storage-dto'; +import { useSystemStorage } from 'apps/dashboard/features/storage/api/useSystemStorage'; -type IProps = { - systemStorage?: SystemStorageDto; -}; +const ServerPathWidget = () => { + const { data: systemStorage } = useSystemStorage(); -const ServerPathWidget = ({ systemStorage }: IProps) => { return ( { const theme = useTheme(); @@ -36,34 +29,7 @@ export const Component = () => { const restartServer = useRestartServer(); const shutdownServer = useShutdownServer(); - const { data: tasks, isPending: isTasksPending } = useLiveTasks({ isHidden: false }); - const { data: devices } = useLiveSessions(); - - const dayBefore = useMemo(() => ( - subSeconds(new Date(), 24 * 60 * 60).toISOString() - ), []); - - const weekBefore = useMemo(() => ( - subSeconds(new Date(), 7 * 24 * 60 * 60).toISOString() - ), []); - - const { data: logs, isPending: isLogsPending } = useLogEntries({ - startIndex: 0, - limit: 7, - minDate: dayBefore, - hasUserId: true - }); - - const { data: alerts, isPending: isAlertsPending } = useLogEntries({ - startIndex: 0, - limit: 4, - minDate: weekBefore, - hasUserId: false - }); - - const { data: systemStorage, isPending: isSystemStoragePending } = useSystemStorage(); - const { data: systemInfo, isPending: isSystemInfoPending } = useSystemInfo(); - const { data: itemCounts, isPending: isItemCountsPending } = useItemCounts(); + const { data: tasks } = useLiveTasks({ isHidden: false }); const promptRestart = useCallback(() => { setIsRestartConfirmDialogOpen(true); @@ -101,13 +67,6 @@ export const Component = () => { setIsShutdownConfirmDialogOpen(false); }, [ shutdownServer ]); - const isPending = isLogsPending || isAlertsPending || isSystemStoragePending - || isSystemInfoPending || isTasksPending || isItemCountsPending; - - if (isPending) { - return ; - } - return ( { - + - + - + {isMedium || isExtraLarge ? ( - - + + ) : ( <> - {(alerts?.Items && alerts.Items.length > 0) && ( - - - - )} - + + + + )}