Skip to content

Commit

Permalink
feat(frontend): add option to hide all available items from discovery (
Browse files Browse the repository at this point in the history
  • Loading branch information
sct committed Jan 20, 2021
1 parent e1032ff commit 6c1742e
Show file tree
Hide file tree
Showing 19 changed files with 192 additions and 19 deletions.
3 changes: 3 additions & 0 deletions overseerr-api.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ components:
applicationUrl:
type: string
example: https://os.example.com
hideAvailable:
type: boolean
example: false
defaultPermissions:
type: number
example: 32
Expand Down
1 change: 1 addition & 0 deletions server/interfaces/api/settingsInterfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ export interface PublicSettingsResponse {
initialized: boolean;
movie4kEnabled: boolean;
series4kEnabled: boolean;
hideAvailable: boolean;
}
4 changes: 4 additions & 0 deletions server/lib/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export interface MainSettings {
apiKey: string;
applicationUrl: string;
defaultPermissions: number;
hideAvailable: boolean;
}

interface PublicSettings {
Expand All @@ -58,6 +59,7 @@ interface PublicSettings {
interface FullPublicSettings extends PublicSettings {
movie4kEnabled: boolean;
series4kEnabled: boolean;
hideAvailable: boolean;
}

export interface NotificationAgentConfig {
Expand Down Expand Up @@ -150,6 +152,7 @@ class Settings {
main: {
apiKey: '',
applicationUrl: '',
hideAvailable: false,
defaultPermissions: Permission.REQUEST,
},
plex: {
Expand Down Expand Up @@ -281,6 +284,7 @@ class Settings {
series4kEnabled: this.data.sonarr.some(
(sonarr) => sonarr.is4k && sonarr.isDefault
),
hideAvailable: this.data.main.hideAvailable,
};
}

Expand Down
14 changes: 13 additions & 1 deletion src/components/Discover/DiscoverMovies.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import ListView from '../Common/ListView';
import { LanguageContext } from '../../context/LanguageContext';
import { defineMessages, FormattedMessage } from 'react-intl';
import Header from '../Common/Header';
import useSettings from '../../hooks/useSettings';
import { MediaStatus } from '../../../server/constants/media';

const messages = defineMessages({
discovermovies: 'Popular Movies',
Expand All @@ -18,6 +20,7 @@ interface SearchResult {
}

const DiscoverMovies: React.FC = () => {
const settings = useSettings();
const { locale } = useContext(LanguageContext);
const { data, error, size, setSize } = useSWRInfinite<SearchResult>(
(pageIndex: number, previousPageData: SearchResult | null) => {
Expand Down Expand Up @@ -45,11 +48,20 @@ const DiscoverMovies: React.FC = () => {
return <div>{error}</div>;
}

const titles = data?.reduce(
let titles = (data ?? []).reduce(
(a, v) => [...a, ...v.results],
[] as MovieResult[]
);

if (settings.currentSettings.hideAvailable) {
titles = titles.filter(
(i) =>
(i.mediaType === 'movie' || i.mediaType === 'tv') &&
i.mediaInfo?.status !== MediaStatus.AVAILABLE &&
i.mediaInfo?.status !== MediaStatus.PARTIALLY_AVAILABLE
);
}

const isEmpty = !isLoadingInitialData && titles?.length === 0;
const isReachingEnd =
isEmpty || (data && data[data.length - 1]?.results.length < 20);
Expand Down
16 changes: 15 additions & 1 deletion src/components/Discover/DiscoverTv.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import ListView from '../Common/ListView';
import { defineMessages, FormattedMessage } from 'react-intl';
import { LanguageContext } from '../../context/LanguageContext';
import Header from '../Common/Header';
import useSettings from '../../hooks/useSettings';
import { MediaStatus } from '../../../server/constants/media';

const messages = defineMessages({
discovertv: 'Popular Series',
Expand All @@ -18,6 +20,7 @@ interface SearchResult {
}

const DiscoverTv: React.FC = () => {
const settings = useSettings();
const { locale } = useContext(LanguageContext);
const { data, error, size, setSize } = useSWRInfinite<SearchResult>(
(pageIndex: number, previousPageData: SearchResult | null) => {
Expand Down Expand Up @@ -45,7 +48,18 @@ const DiscoverTv: React.FC = () => {
return <div>{error}</div>;
}

const titles = data?.reduce((a, v) => [...a, ...v.results], [] as TvResult[]);
let titles = (data ?? []).reduce(
(a, v) => [...a, ...v.results],
[] as TvResult[]
);

if (settings.currentSettings.hideAvailable) {
titles = titles.filter(
(i) =>
i.mediaInfo?.status !== MediaStatus.AVAILABLE &&
i.mediaInfo?.status !== MediaStatus.PARTIALLY_AVAILABLE
);
}

const isEmpty = !isLoadingInitialData && titles?.length === 0;
const isReachingEnd =
Expand Down
14 changes: 13 additions & 1 deletion src/components/Discover/Trending.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import ListView from '../Common/ListView';
import { LanguageContext } from '../../context/LanguageContext';
import { defineMessages, FormattedMessage } from 'react-intl';
import Header from '../Common/Header';
import useSettings from '../../hooks/useSettings';
import { MediaStatus } from '../../../server/constants/media';

const messages = defineMessages({
trending: 'Trending',
Expand All @@ -22,6 +24,7 @@ interface SearchResult {
}

const Trending: React.FC = () => {
const settings = useSettings();
const { locale } = useContext(LanguageContext);
const { data, error, size, setSize } = useSWRInfinite<SearchResult>(
(pageIndex: number, previousPageData: SearchResult | null) => {
Expand Down Expand Up @@ -51,11 +54,20 @@ const Trending: React.FC = () => {
return <div>{error}</div>;
}

const titles = data?.reduce(
let titles = (data ?? []).reduce(
(a, v) => [...a, ...v.results],
[] as (MovieResult | TvResult | PersonResult)[]
);

if (settings.currentSettings.hideAvailable) {
titles = titles.filter(
(i) =>
(i.mediaType === 'movie' || i.mediaType === 'tv') &&
i.mediaInfo?.status !== MediaStatus.AVAILABLE &&
i.mediaInfo?.status !== MediaStatus.PARTIALLY_AVAILABLE
);
}

const isEmpty = !isLoadingInitialData && titles?.length === 0;
const isReachingEnd =
isEmpty || (data && data[data.length - 1]?.results.length < 20);
Expand Down
13 changes: 12 additions & 1 deletion src/components/Discover/Upcoming.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import ListView from '../Common/ListView';
import { LanguageContext } from '../../context/LanguageContext';
import { defineMessages, FormattedMessage } from 'react-intl';
import Header from '../Common/Header';
import useSettings from '../../hooks/useSettings';
import { MediaStatus } from '../../../server/constants/media';

const messages = defineMessages({
upcomingmovies: 'Upcoming Movies',
Expand All @@ -18,6 +20,7 @@ interface SearchResult {
}

const UpcomingMovies: React.FC = () => {
const settings = useSettings();
const { locale } = useContext(LanguageContext);
const { data, error, size, setSize } = useSWRInfinite<SearchResult>(
(pageIndex: number, previousPageData: SearchResult | null) => {
Expand Down Expand Up @@ -47,11 +50,19 @@ const UpcomingMovies: React.FC = () => {
return <div>{error}</div>;
}

const titles = data?.reduce(
let titles = (data ?? []).reduce(
(a, v) => [...a, ...v.results],
[] as MovieResult[]
);

if (settings.currentSettings.hideAvailable) {
titles = titles.filter(
(i) =>
i.mediaInfo?.status !== MediaStatus.AVAILABLE &&
i.mediaInfo?.status !== MediaStatus.PARTIALLY_AVAILABLE
);
}

const isEmpty = !isLoadingInitialData && titles?.length === 0;
const isReachingEnd =
isEmpty || (data && data[data.length - 1]?.results.length < 20);
Expand Down
36 changes: 29 additions & 7 deletions src/components/MediaSlider/index.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import Link from 'next/link';
import React, { useContext } from 'react';
import React, { useContext, useEffect } from 'react';
import { useSWRInfinite } from 'swr';
import { MediaStatus } from '../../../server/constants/media';
import type {
MovieResult,
PersonResult,
TvResult,
} from '../../../server/models/Search';
import { LanguageContext } from '../../context/LanguageContext';
import useSettings from '../../hooks/useSettings';
import PersonCard from '../PersonCard';
import Slider from '../Slider';
import TitleCard from '../TitleCard';
Expand Down Expand Up @@ -34,8 +36,9 @@ const MediaSlider: React.FC<MediaSliderProps> = ({
sliderKey,
hideWhenEmpty = false,
}) => {
const settings = useSettings();
const { locale } = useContext(LanguageContext);
const { data, error } = useSWRInfinite<MixedResult>(
const { data, error, setSize, size } = useSWRInfinite<MixedResult>(
(pageIndex: number, previousPageData: MixedResult | null) => {
if (previousPageData && pageIndex + 1 > previousPageData.totalPages) {
return null;
Expand All @@ -48,15 +51,34 @@ const MediaSlider: React.FC<MediaSliderProps> = ({
}
);

if (hideWhenEmpty && (data?.[0].results ?? []).length === 0) {
return null;
}

const titles = (data ?? []).reduce(
let titles = (data ?? []).reduce(
(a, v) => [...a, ...v.results],
[] as (MovieResult | TvResult | PersonResult)[]
);

if (settings.currentSettings.hideAvailable) {
titles = titles.filter(
(i) =>
(i.mediaType === 'movie' || i.mediaType === 'tv') &&
i.mediaInfo?.status !== MediaStatus.AVAILABLE &&
i.mediaInfo?.status !== MediaStatus.PARTIALLY_AVAILABLE
);
}

useEffect(() => {
if (
titles.length < 24 &&
size < 5 &&
(data?.[0]?.totalResults ?? 0) > size * 20
) {
setSize(size + 1);
}
}, [titles, setSize, size, data]);

if (hideWhenEmpty && (data?.[0].results ?? []).length === 0) {
return null;
}

const finalTitles = titles.slice(0, 20).map((title) => {
switch (title.mediaType) {
case 'movie':
Expand Down
13 changes: 12 additions & 1 deletion src/components/MovieDetails/MovieRecommendations.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import Header from '../Common/Header';
import type { MovieDetails } from '../../../server/models/Movie';
import { LanguageContext } from '../../context/LanguageContext';
import { defineMessages, useIntl, FormattedMessage } from 'react-intl';
import useSettings from '../../hooks/useSettings';
import { MediaStatus } from '../../../server/constants/media';

const messages = defineMessages({
recommendations: 'Recommendations',
Expand All @@ -21,6 +23,7 @@ interface SearchResult {
}

const MovieRecommendations: React.FC = () => {
const settings = useSettings();
const intl = useIntl();
const router = useRouter();
const { locale } = useContext(LanguageContext);
Expand Down Expand Up @@ -55,11 +58,19 @@ const MovieRecommendations: React.FC = () => {
return <div>{error}</div>;
}

const titles = data?.reduce(
let titles = (data ?? []).reduce(
(a, v) => [...a, ...v.results],
[] as MovieResult[]
);

if (settings.currentSettings.hideAvailable) {
titles = titles.filter(
(i) =>
i.mediaInfo?.status !== MediaStatus.AVAILABLE &&
i.mediaInfo?.status !== MediaStatus.PARTIALLY_AVAILABLE
);
}

const isEmpty = !isLoadingInitialData && titles?.length === 0;
const isReachingEnd =
isEmpty || (data && data[data.length - 1]?.results.length < 20);
Expand Down
13 changes: 12 additions & 1 deletion src/components/MovieDetails/MovieSimilar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import Header from '../Common/Header';
import { LanguageContext } from '../../context/LanguageContext';
import type { MovieDetails } from '../../../server/models/Movie';
import { defineMessages, useIntl, FormattedMessage } from 'react-intl';
import { MediaStatus } from '../../../server/constants/media';
import useSettings from '../../hooks/useSettings';

const messages = defineMessages({
similar: 'Similar Titles',
Expand All @@ -21,6 +23,7 @@ interface SearchResult {
}

const MovieSimilar: React.FC = () => {
const settings = useSettings();
const router = useRouter();
const intl = useIntl();
const { locale } = useContext(LanguageContext);
Expand Down Expand Up @@ -55,11 +58,19 @@ const MovieSimilar: React.FC = () => {
return <div>{error}</div>;
}

const titles = data?.reduce(
let titles = (data ?? []).reduce(
(a, v) => [...a, ...v.results],
[] as MovieResult[]
);

if (settings.currentSettings.hideAvailable) {
titles = titles.filter(
(i) =>
i.mediaInfo?.status !== MediaStatus.AVAILABLE &&
i.mediaInfo?.status !== MediaStatus.PARTIALLY_AVAILABLE
);
}

const isEmpty = !isLoadingInitialData && titles?.length === 0;
const isReachingEnd =
isEmpty || (data && data[data.length - 1]?.results.length < 20);
Expand Down
6 changes: 3 additions & 3 deletions src/components/RequestButton/index.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import axios from 'axios';
import React, { useContext, useState } from 'react';
import React, { useState } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import {
MediaRequestStatus,
MediaStatus,
} from '../../../server/constants/media';
import Media from '../../../server/entity/Media';
import { MediaRequest } from '../../../server/entity/MediaRequest';
import { SettingsContext } from '../../context/SettingsContext';
import useSettings from '../../hooks/useSettings';
import { Permission, useUser } from '../../hooks/useUser';
import ButtonWithDropdown from '../Common/ButtonWithDropdown';
import RequestModal from '../RequestModal';
Expand Down Expand Up @@ -58,7 +58,7 @@ const RequestButton: React.FC<RequestButtonProps> = ({
is4kShowComplete = false,
}) => {
const intl = useIntl();
const settings = useContext(SettingsContext);
const settings = useSettings();
const { hasPermission } = useUser();
const [showRequestModal, setShowRequestModal] = useState(false);
const [showRequest4kModal, setShowRequest4kModal] = useState(false);
Expand Down

0 comments on commit 6c1742e

Please sign in to comment.