feat: adds streaming services custom slider (#3361)

* feat: adding streaming services as a slider is now an option

* fix: truncated slider titles on mobile
pull/3223/head
Brandon Cohen 1 year ago committed by GitHub
parent 04980f93ab
commit 2520d8f739
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -20,6 +20,8 @@ export enum DiscoverSliderType {
TMDB_SEARCH, TMDB_SEARCH,
TMDB_STUDIO, TMDB_STUDIO,
TMDB_NETWORK, TMDB_NETWORK,
TMDB_MOVIE_STREAMING_SERVICES,
TMDB_TV_STREAMING_SERVICES,
} }
export const defaultSliders: Partial<DiscoverSlider>[] = [ export const defaultSliders: Partial<DiscoverSlider>[] = [

@ -2,6 +2,7 @@ import Button from '@app/components/Common/Button';
import Tooltip from '@app/components/Common/Tooltip'; import Tooltip from '@app/components/Common/Tooltip';
import { sliderTitles } from '@app/components/Discover/constants'; import { sliderTitles } from '@app/components/Discover/constants';
import MediaSlider from '@app/components/MediaSlider'; import MediaSlider from '@app/components/MediaSlider';
import { WatchProviderSelector } from '@app/components/Selector';
import { encodeURIExtraParams } from '@app/hooks/useDiscover'; import { encodeURIExtraParams } from '@app/hooks/useDiscover';
import type { import type {
TmdbCompanySearchResponse, TmdbCompanySearchResponse,
@ -55,7 +56,7 @@ type CreateOption = {
dataUrl: string; dataUrl: string;
params?: string; params?: string;
titlePlaceholderText: string; titlePlaceholderText: string;
dataPlaceholderText: string; dataPlaceholderText?: string;
}; };
const CreateSlider = ({ onCreate, slider }: CreateSliderProps) => { const CreateSlider = ({ onCreate, slider }: CreateSliderProps) => {
@ -276,6 +277,20 @@ const CreateSlider = ({ onCreate, slider }: CreateSliderProps) => {
titlePlaceholderText: intl.formatMessage(messages.slidernameplaceholder), titlePlaceholderText: intl.formatMessage(messages.slidernameplaceholder),
dataPlaceholderText: intl.formatMessage(messages.providetmdbsearch), dataPlaceholderText: intl.formatMessage(messages.providetmdbsearch),
}, },
{
type: DiscoverSliderType.TMDB_MOVIE_STREAMING_SERVICES,
title: intl.formatMessage(sliderTitles.tmdbmoviestreamingservices),
dataUrl: '/api/v1/discover/movies',
params: 'watchRegion=$regionValue&watchProviders=$providersValue',
titlePlaceholderText: intl.formatMessage(messages.slidernameplaceholder),
},
{
type: DiscoverSliderType.TMDB_TV_STREAMING_SERVICES,
title: intl.formatMessage(sliderTitles.tmdbtvstreamingservices),
dataUrl: '/api/v1/discover/tv',
params: 'watchRegion=$regionValue&watchProviders=$providersValue',
titlePlaceholderText: intl.formatMessage(messages.slidernameplaceholder),
},
]; ];
return ( return (
@ -417,6 +432,40 @@ const CreateSlider = ({ onCreate, slider }: CreateSliderProps) => {
/> />
); );
break; break;
case DiscoverSliderType.TMDB_MOVIE_STREAMING_SERVICES:
dataInput = (
<WatchProviderSelector
type={'movie'}
region={slider?.data?.split(',')[0]}
activeProviders={
slider?.data
?.split(',')[1]
.split('|')
.map((v) => Number(v)) ?? []
}
onChange={(region, providers) => {
setFieldValue('data', `${region},${providers.join('|')}`);
}}
/>
);
break;
case DiscoverSliderType.TMDB_TV_STREAMING_SERVICES:
dataInput = (
<WatchProviderSelector
type={'tv'}
region={slider?.data?.split(',')[0]}
activeProviders={
slider?.data
?.split(',')[1]
.split('|')
.map((v) => Number(v)) ?? []
}
onChange={(region, providers) => {
setFieldValue('data', `${region},${providers.join('|')}`);
}}
/>
);
break;
default: default:
dataInput = ( dataInput = (
<Field <Field
@ -488,10 +537,25 @@ const CreateSlider = ({ onCreate, slider }: CreateSliderProps) => {
'$value', '$value',
encodeURIExtraParams(values.data) encodeURIExtraParams(values.data)
)} )}
extraParams={activeOption.params?.replace( extraParams={
'$value', activeOption.type ===
encodeURIExtraParams(values.data) DiscoverSliderType.TMDB_MOVIE_STREAMING_SERVICES ||
)} activeOption.type ===
DiscoverSliderType.TMDB_TV_STREAMING_SERVICES
? activeOption.params
?.replace(
'$regionValue',
encodeURIExtraParams(values?.data.split(',')[0])
)
.replace(
'$providersValue',
encodeURIExtraParams(values?.data.split(',')[1])
)
: activeOption.params?.replace(
'$value',
encodeURIExtraParams(values.data)
)
}
onNewTitles={updateResultCount} onNewTitles={updateResultCount}
/> />
</div> </div>

@ -164,6 +164,10 @@ const DiscoverSliderEdit = ({
return intl.formatMessage(sliderTitles.tmdbnetwork); return intl.formatMessage(sliderTitles.tmdbnetwork);
case DiscoverSliderType.TMDB_SEARCH: case DiscoverSliderType.TMDB_SEARCH:
return intl.formatMessage(sliderTitles.tmdbsearch); return intl.formatMessage(sliderTitles.tmdbsearch);
case DiscoverSliderType.TMDB_MOVIE_STREAMING_SERVICES:
return intl.formatMessage(sliderTitles.tmdbmoviestreamingservices);
case DiscoverSliderType.TMDB_TV_STREAMING_SERVICES:
return intl.formatMessage(sliderTitles.tmdbtvstreamingservices);
default: default:
return 'Unknown Slider'; return 'Unknown Slider';
} }
@ -195,7 +199,9 @@ const DiscoverSliderEdit = ({
className={`${slider.data ? 'mb-4' : 'mb-0'} flex space-x-2 md:mb-0`} className={`${slider.data ? 'mb-4' : 'mb-0'} flex space-x-2 md:mb-0`}
> >
<Bars3Icon className="h-6 w-6" /> <Bars3Icon className="h-6 w-6" />
<div>{getSliderTitle(slider)}</div> <div className="w-7/12 truncate md:w-full">
{getSliderTitle(slider)}
</div>
</div> </div>
<div <div
className={`pointer-events-none ${ className={`pointer-events-none ${

@ -86,6 +86,8 @@ export const sliderTitles = defineMessages({
tmdbnetwork: 'TMDB Network', tmdbnetwork: 'TMDB Network',
tmdbstudio: 'TMDB Studio', tmdbstudio: 'TMDB Studio',
tmdbsearch: 'TMDB Search', tmdbsearch: 'TMDB Search',
tmdbmoviestreamingservices: 'TMDB Movie Streaming Services',
tmdbtvstreamingservices: 'TMDB TV Streaming Services',
}); });
export const QueryFilterOptions = z.object({ export const QueryFilterOptions = z.object({

@ -365,6 +365,36 @@ const Discover = () => {
/> />
); );
break; break;
case DiscoverSliderType.TMDB_MOVIE_STREAMING_SERVICES:
sliderComponent = (
<MediaSlider
sliderKey={`custom-slider-${slider.id}`}
title={slider.title ?? ''}
url="/api/v1/discover/movies"
extraParams={`watchRegion=${
slider.data?.split(',')[0]
}&watchProviders=${slider.data?.split(',')[1]}`}
linkUrl={`/discover/movies?watchRegion=${
slider.data?.split(',')[0]
}&watchProviders=${slider.data?.split(',')[1]}`}
/>
);
break;
case DiscoverSliderType.TMDB_TV_STREAMING_SERVICES:
sliderComponent = (
<MediaSlider
sliderKey={`custom-slider-${slider.id}`}
title={slider.title ?? ''}
url="/api/v1/discover/tv"
extraParams={`watchRegion=${
slider.data?.split(',')[0]
}&watchProviders=${slider.data?.split(',')[1]}`}
linkUrl={`/discover/tv?watchRegion=${
slider.data?.split(',')[0]
}&watchProviders=${slider.data?.split(',')[1]}`}
/>
);
break;
} }
if (isEditing) { if (isEditing) {

@ -305,7 +305,9 @@ export const WatchProviderSelector = ({
useEffect(() => { useEffect(() => {
onChange(watchRegion, activeProvider); onChange(watchRegion, activeProvider);
}, [activeProvider, watchRegion, onChange]); // removed onChange as a dependency as we only need to call it when the value(s) change
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [activeProvider, watchRegion]);
const orderedData = useMemo(() => { const orderedData = useMemo(() => {
if (!data) { if (!data) {
@ -344,7 +346,7 @@ export const WatchProviderSelector = ({
<SmallLoadingSpinner /> <SmallLoadingSpinner />
) : ( ) : (
<div className="grid"> <div className="grid">
<div className="grid grid-cols-6 gap-2"> <div className="provider-icons grid gap-2">
{initialProviders.map((provider) => { {initialProviders.map((provider) => {
const isActive = activeProvider.includes(provider.id); const isActive = activeProvider.includes(provider.id);
return ( return (
@ -353,7 +355,7 @@ export const WatchProviderSelector = ({
key={`prodiver-${provider.id}`} key={`prodiver-${provider.id}`}
> >
<div <div
className={`provider-container relative h-full w-full cursor-pointer rounded-lg p-2 ring-1 ${ className={`provider-container relative w-full cursor-pointer rounded-lg p-2 ring-1 ${
isActive isActive
? 'bg-gray-600 ring-indigo-500 hover:bg-gray-500' ? 'bg-gray-600 ring-indigo-500 hover:bg-gray-500'
: 'bg-gray-700 ring-gray-500 hover:bg-gray-600' : 'bg-gray-700 ring-gray-500 hover:bg-gray-600'
@ -386,7 +388,7 @@ export const WatchProviderSelector = ({
})} })}
</div> </div>
{showMore && otherProviders.length > 0 && ( {showMore && otherProviders.length > 0 && (
<div className="relative top-2 grid grid-cols-6 gap-2"> <div className="provider-icons relative top-2 grid gap-2">
{otherProviders.map((provider) => { {otherProviders.map((provider) => {
const isActive = activeProvider.includes(provider.id); const isActive = activeProvider.includes(provider.id);
return ( return (
@ -395,7 +397,7 @@ export const WatchProviderSelector = ({
key={`prodiver-${provider.id}`} key={`prodiver-${provider.id}`}
> >
<div <div
className={`provider-container relative h-full w-full cursor-pointer rounded-lg p-2 ring-1 transition ${ className={`provider-container relative w-full cursor-pointer rounded-lg p-2 ring-1 transition ${
isActive isActive
? 'bg-gray-600 ring-indigo-500 hover:bg-gray-500' ? 'bg-gray-600 ring-indigo-500 hover:bg-gray-500'
: 'bg-gray-700 ring-gray-500 hover:bg-gray-600' : 'bg-gray-700 ring-gray-500 hover:bg-gray-600'

@ -105,11 +105,13 @@
"components.Discover.studios": "Studios", "components.Discover.studios": "Studios",
"components.Discover.tmdbmoviegenre": "TMDB Movie Genre", "components.Discover.tmdbmoviegenre": "TMDB Movie Genre",
"components.Discover.tmdbmoviekeyword": "TMDB Movie Keyword", "components.Discover.tmdbmoviekeyword": "TMDB Movie Keyword",
"components.Discover.tmdbmoviestreamingservices": "TMDB Movie Streaming Services",
"components.Discover.tmdbnetwork": "TMDB Network", "components.Discover.tmdbnetwork": "TMDB Network",
"components.Discover.tmdbsearch": "TMDB Search", "components.Discover.tmdbsearch": "TMDB Search",
"components.Discover.tmdbstudio": "TMDB Studio", "components.Discover.tmdbstudio": "TMDB Studio",
"components.Discover.tmdbtvgenre": "TMDB Series Genre", "components.Discover.tmdbtvgenre": "TMDB Series Genre",
"components.Discover.tmdbtvkeyword": "TMDB Series Keyword", "components.Discover.tmdbtvkeyword": "TMDB Series Keyword",
"components.Discover.tmdbtvstreamingservices": "TMDB TV Streaming Services",
"components.Discover.trending": "Trending", "components.Discover.trending": "Trending",
"components.Discover.tvgenres": "Series Genres", "components.Discover.tvgenres": "Series Genres",
"components.Discover.upcoming": "Upcoming Movies", "components.Discover.upcoming": "Upcoming Movies",

@ -73,6 +73,10 @@
grid-template-columns: repeat(auto-fill, minmax(16.5rem, 1fr)); grid-template-columns: repeat(auto-fill, minmax(16.5rem, 1fr));
} }
.provider-icons {
grid-template-columns: repeat(auto-fill, minmax(3.5rem, 1fr));
}
.slider-header { .slider-header {
@apply relative mt-6 mb-4 flex; @apply relative mt-6 mb-4 flex;
} }

Loading…
Cancel
Save