Add provider list

This commit is contained in:
viown
2025-08-09 21:07:36 +03:00
parent 96024d3025
commit 62f61fa167
5 changed files with 124 additions and 68 deletions
@@ -2,7 +2,7 @@ import React, { useCallback, useRef, useState } from 'react';
import type { TunerHostInfo } from '@jellyfin/sdk/lib/generated-client/models/tuner-host-info';
import BaseCard from 'apps/dashboard/components/BaseCard';
import DvrIcon from '@mui/icons-material/Dvr';
import getProviderName from '../utils/getProviderName';
import getProviderName from '../utils/getTunerName';
import Menu from '@mui/material/Menu';
import MenuItem from '@mui/material/MenuItem';
import ListItemIcon from '@mui/material/ListItemIcon';
@@ -0,0 +1,10 @@
const getProviderConfigurationUrl = (providerId: string) => {
switch (providerId?.toLowerCase()) {
case 'xmltv':
return '/dashboard/livetv/guide?type=xmltv';
case 'schedulesdirect':
return '/dashboard/livetv/guide?type=schedulesdirect';
}
};
export default getProviderConfigurationUrl;
@@ -1,16 +1,12 @@
const getTunerName = (providerId: string | null | undefined) => {
const getProviderName = (providerId: string | null | undefined) => {
switch (providerId?.toLowerCase()) {
case 'm3u':
return 'M3U';
case 'hdhomerun':
return 'HDHomeRun';
case 'hauppauge':
return 'Hauppauge';
case 'satip':
return 'DVB';
case 'schedulesdirect':
return 'Schedules Direct';
case 'xmltv':
return 'XMLTV';
default:
return 'Unknown';
}
};
export default getTunerName;
export default getProviderName;
@@ -0,0 +1,16 @@
const getTunerName = (providerId: string | null | undefined) => {
switch (providerId?.toLowerCase()) {
case 'm3u':
return 'M3U';
case 'hdhomerun':
return 'HDHomeRun';
case 'hauppauge':
return 'Hauppauge';
case 'satip':
return 'DVB';
default:
return 'Unknown';
}
};
export default getTunerName;
+91 -57
View File
@@ -12,7 +12,8 @@ import useLiveTasks from 'apps/dashboard/features/tasks/hooks/useLiveTasks';
import Button from '@mui/material/Button';
import RefreshIcon from '@mui/icons-material/Refresh';
import AddIcon from '@mui/icons-material/Add';
import { Link, useNavigate } from 'react-router-dom';
import DvrIcon from '@mui/icons-material/Dvr';
import { Form, Link, useNavigate } from 'react-router-dom';
import { useStartTask } from 'apps/dashboard/features/tasks/api/useStartTask';
import { TaskState } from '@jellyfin/sdk/lib/generated-client/models/task-state';
import TaskProgress from 'apps/dashboard/features/tasks/components/TaskProgress';
@@ -20,6 +21,13 @@ import Menu from '@mui/material/Menu';
import MenuItem from '@mui/material/MenuItem';
import ListItemText from '@mui/material/ListItemText';
import Alert from '@mui/material/Alert';
import List from '@mui/material/List';
import ListItem from '@mui/material/ListItem';
import ListItemLink from 'components/ListItemLink';
import ListItemAvatar from '@mui/material/ListItemAvatar';
import Avatar from '@mui/material/Avatar';
import getProviderConfigurationUrl from 'apps/dashboard/features/livetv/utils/getProviderConfigurationUrl';
import getProviderName from 'apps/dashboard/features/livetv/utils/getProviderName';
const CONFIG_KEY = 'livetv';
@@ -79,70 +87,96 @@ export const Component = () => {
className='mainAnimatedPage type-interior'
>
<Box className='content-primary'>
{(isConfigError || isTasksError) ? (
<Alert severity='error'>{globalize.translate('HeaderError')}</Alert>
) : (
<Stack spacing={3}>
<Typography variant='h2'>{globalize.translate('HeaderTunerDevices')}</Typography>
<Form>
{(isConfigError || isTasksError) ? (
<Alert severity='error'>{globalize.translate('HeaderError')}</Alert>
) : (
<Stack spacing={3}>
<Typography variant='h2'>{globalize.translate('HeaderTunerDevices')}</Typography>
<Button
sx={{ alignSelf: 'flex-start' }}
startIcon={<AddIcon />}
component={Link}
to='/dashboard/livetv/tuner'
>
{globalize.translate('ButtonAddTunerDevice')}
</Button>
<Stack direction='row' spacing={2}>
{ config?.TunerHosts?.map(tunerHost => (
<TunerDeviceCard
key={tunerHost.Id}
tunerHost={tunerHost}
/>
)) }
</Stack>
<Typography variant='h2'>{globalize.translate('HeaderGuideProviders')}</Typography>
<Stack direction='row' spacing={1.5}>
<Button
sx={{ alignSelf: 'flex-start' }}
startIcon={<AddIcon />}
onClick={showProviderMenu}
ref={providerButtonRef}
component={Link}
to='/dashboard/livetv/tuner'
>
{globalize.translate('ButtonAddProvider')}
{globalize.translate('ButtonAddTunerDevice')}
</Button>
<Button
sx={{ alignSelf: 'flex-start' }}
startIcon={<RefreshIcon />}
variant='outlined'
onClick={refreshGuideData}
>
{globalize.translate('ButtonRefreshGuideData')}
</Button>
</Stack>
{(refreshGuideTask && refreshGuideTask.State === TaskState.Running) && (
<Box maxWidth={200}>
<Stack direction='row' spacing={2}>
{ config.TunerHosts?.map(tunerHost => (
<TunerDeviceCard
key={tunerHost.Id}
tunerHost={tunerHost}
/>
)) }
</Stack>
<Typography variant='h2'>{globalize.translate('HeaderGuideProviders')}</Typography>
<Stack direction='row' spacing={1.5}>
<Button
sx={{ alignSelf: 'flex-start' }}
startIcon={<AddIcon />}
onClick={showProviderMenu}
ref={providerButtonRef}
>
{globalize.translate('ButtonAddProvider')}
</Button>
<Button
sx={{ alignSelf: 'flex-start' }}
startIcon={<RefreshIcon />}
variant='outlined'
onClick={refreshGuideData}
>
{globalize.translate('ButtonRefreshGuideData')}
</Button>
</Stack>
{(refreshGuideTask && refreshGuideTask.State === TaskState.Running) && (
<TaskProgress task={refreshGuideTask} />
</Box>
)}
<Menu
anchorEl={anchorEl}
open={isMenuOpen}
onClose={onMenuClose}
>
<MenuItem onClick={navigateToSchedulesDirect}>
<ListItemText>Schedules Direct</ListItemText>
</MenuItem>
<MenuItem onClick={navigateToXMLTV}>
<ListItemText>XMLTV</ListItemText>
</MenuItem>
</Menu>
</Stack>
)}
)}
<Menu
anchorEl={anchorEl}
open={isMenuOpen}
onClose={onMenuClose}
>
<MenuItem onClick={navigateToSchedulesDirect}>
<ListItemText>Schedules Direct</ListItemText>
</MenuItem>
<MenuItem onClick={navigateToXMLTV}>
<ListItemText>XMLTV</ListItemText>
</MenuItem>
</Menu>
<List sx={{ backgroundColor: 'background.paper' }}>
{config.ListingProviders?.map(provider => (
<ListItem disablePadding key={provider.Id}>
<ListItemLink to={getProviderConfigurationUrl(provider.Type || '') + '&id=' + provider.Id}>
<ListItemAvatar>
<Avatar>
<DvrIcon />
</Avatar>
</ListItemAvatar>
<ListItemText
primary={getProviderName(provider.Type)}
secondary={provider.Path || provider.ListingsId}
slotProps={{
primary: {
variant: 'h3'
},
secondary: {
variant: 'body1'
}
}}
/>
</ListItemLink>
</ListItem>
))}
</List>
</Stack>
)}
</Form>
</Box>
</Page>
);