Add Internet Radio support (#2063)

* add internet radio support

* Add dynamic sidebar icon to Radios

* Fix typos

* Make URL suffix consistent

* Fix typo

* address feedback

* Don't need to preload when playing Internet Radios

* Reorder migration, or else it won't be applied

* Make Radio list view responsive

Also added filter by name, removed RadioActions and RadioContextMenu, and added a default radio icon, in case of favicon is not available.

* Simplify StreamField usage

* fix button, hide progress on mobile

* use js styles over index.css

Co-authored-by: Deluan <deluan@navidrome.org>
This commit is contained in:
Kendall Garner
2023-01-15 20:11:37 +00:00
committed by GitHub
parent aa21a2a305
commit 8877b1695a
34 changed files with 1304 additions and 9 deletions
+139
View File
@@ -0,0 +1,139 @@
import { makeStyles, useMediaQuery } from '@material-ui/core'
import React, { cloneElement } from 'react'
import {
CreateButton,
Datagrid,
DateField,
Filter,
List,
sanitizeListRestProps,
SearchInput,
SimpleList,
TextField,
TopToolbar,
UrlField,
useTranslate,
} from 'react-admin'
import { ToggleFieldsMenu, useSelectedFields } from '../common'
import { StreamField } from './StreamField'
const useStyles = makeStyles({
row: {
'&:hover': {
'& $contextMenu': {
visibility: 'visible',
},
},
},
contextMenu: {
visibility: 'hidden',
},
})
const RadioFilter = (props) => (
<Filter {...props} variant={'outlined'}>
<SearchInput id="search" source="name" alwaysOn />
</Filter>
)
const RadioListActions = ({
className,
filters,
resource,
showFilter,
displayedFilters,
filterValues,
isAdmin,
...rest
}) => {
const isNotSmall = useMediaQuery((theme) => theme.breakpoints.up('sm'))
const translate = useTranslate()
return (
<TopToolbar className={className} {...sanitizeListRestProps(rest)}>
{isAdmin && (
<CreateButton basePath="/radio">
{translate('ra.action.create')}
</CreateButton>
)}
{filters &&
cloneElement(filters, {
resource,
showFilter,
displayedFilters,
filterValues,
context: 'button',
})}
{isNotSmall && <ToggleFieldsMenu resource="radio" />}
</TopToolbar>
)
}
const RadioList = ({ permissions, ...props }) => {
const isXsmall = useMediaQuery((theme) => theme.breakpoints.down('xs'))
const classes = useStyles()
const isAdmin = permissions === 'admin'
const toggleableFields = {
name: <TextField source="name" />,
homePageUrl: (
<UrlField
source="homePageUrl"
onClick={(e) => e.stopPropagation()}
target="_blank"
rel="noopener noreferrer"
/>
),
streamUrl: <StreamField source="streamUrl" />,
createdAt: <DateField source="createdAt" showTime />,
updatedAt: <DateField source="updatedAt" showTime />,
}
const columns = useSelectedFields({
resource: 'radio',
columns: toggleableFields,
defaultOff: ['updatedAt'],
})
return (
<List
{...props}
exporter={false}
bulkActionButtons={isAdmin ? undefined : false}
hasCreate={isAdmin}
actions={<RadioListActions isAdmin={isAdmin} />}
filters={<RadioFilter />}
perPage={isXsmall ? 25 : 10}
>
{isXsmall ? (
<SimpleList
linkType={isAdmin ? 'edit' : 'show'}
leftIcon={(r) => (
<StreamField
record={r}
source={'streamUrl'}
hideUrl
onClick={(e) => {
e.preventDefault()
e.stopPropagation()
}}
/>
)}
primaryText={(r) => r.name}
secondaryText={(r) => r.homePageUrl}
/>
) : (
<Datagrid
rowClick={isAdmin ? 'edit' : 'show'}
classes={{ row: classes.row }}
>
{columns}
</Datagrid>
)}
</List>
)
}
export default RadioList