1
0
Fork 0
mirror of https://github.com/jellyfin/jellyfin-web synced 2025-03-30 19:56:21 +00:00

Migrate scheduled tasks to React (#6506)

* Migrate scheduled tasks to React

* Adjust margins

* Use localeCompare

* Clean up imports

* Use legacy apiclient from useApi

* Fix import

* Fix nested typography

* Add polling fallback

* Cleanup code

* Rename to tasks

* Rename to Component

* Use constants for websocket events

* Use memo to fix timestamp rerender on run
This commit is contained in:
viown 2025-02-21 00:18:42 +03:00 committed by GitHub
parent 201a3c32f8
commit f573221643
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 362 additions and 224 deletions

View file

@ -0,0 +1,75 @@
import React, { useEffect } from 'react';
import Page from 'components/Page';
import globalize from 'lib/globalize';
import Box from '@mui/material/Box';
import Stack from '@mui/material/Stack';
import { QUERY_KEY, useTasks } from '../../features/scheduledtasks/api/useTasks';
import { getCategories, getTasksByCategory } from '../../features/scheduledtasks/utils/tasks';
import Loading from 'components/loading/LoadingComponent';
import Tasks from '../../features/scheduledtasks/components/Tasks';
import type { TaskInfo } from '@jellyfin/sdk/lib/generated-client/models/task-info';
import { SessionMessageType } from '@jellyfin/sdk/lib/generated-client/models/session-message-type';
import serverNotifications from 'scripts/serverNotifications';
import Events, { Event } from 'utils/events';
import { ApiClient } from 'jellyfin-apiclient';
import { useApi } from 'hooks/useApi';
import { queryClient } from 'utils/query/queryClient';
export const Component = () => {
const { __legacyApiClient__ } = useApi();
const { data: tasks, isPending } = useTasks({ isHidden: false });
// TODO: Replace usage of the legacy apiclient when websocket support is added to the TS SDK.
useEffect(() => {
const onScheduledTasksUpdate = (_e: Event, _apiClient: ApiClient, info: TaskInfo[]) => {
queryClient.setQueryData([ QUERY_KEY ], info);
};
const fallbackInterval = setInterval(() => {
if (!__legacyApiClient__?.isMessageChannelOpen()) {
void queryClient.invalidateQueries({
queryKey: [ QUERY_KEY ]
});
}
}, 1e4);
__legacyApiClient__?.sendMessage(SessionMessageType.ScheduledTasksInfoStart, '1000,1000');
Events.on(serverNotifications, SessionMessageType.ScheduledTasksInfo, onScheduledTasksUpdate);
return () => {
clearInterval(fallbackInterval);
__legacyApiClient__?.sendMessage(SessionMessageType.ScheduledTasksInfoStop, null);
Events.off(serverNotifications, SessionMessageType.ScheduledTasksInfo, onScheduledTasksUpdate);
};
}, [__legacyApiClient__]);
if (isPending || !tasks) {
return <Loading />;
}
const categories = getCategories(tasks);
return (
<Page
id='scheduledTasksPage'
title={globalize.translate('TabScheduledTasks')}
className='mainAnimatedPage type-interior'
>
<Box className='content-primary'>
<Box className='readOnlyContent'>
<Stack spacing={3} mt={2}>
{categories.map(category => {
return <Tasks
key={category}
category={category}
tasks={getTasksByCategory(tasks, category)}
/>;
})}
</Stack>
</Box>
</Box>
</Page>
);
};
Component.displayName = 'TasksPage';