Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions docs/using-seerr/settings/general.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,14 @@ When enabled, media that has been blocklisted will not appear on the "Discover"

This setting is **disabled** by default.

## Hide Requested Media

When enabled, media that has been requested (but not yet available) will not appear on the "Discover" home page, or in the "Recommended" or "Similar" categories or other links on media detail pages.

Requested media will still appear in search results, however, so it is possible to locate and view hidden items by searching for them by title.

This setting is **disabled** by default.

## Allow Partial Series Requests

When enabled, users will be able to submit requests for specific seasons of TV series. If disabled, users will only be able to submit requests for all unavailable seasons.
Expand Down
3 changes: 3 additions & 0 deletions seerr-api.yml
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,9 @@ components:
hideAvailable:
type: boolean
example: false
hideRequested:
type: boolean
example: false
partialRequestsEnabled:
type: boolean
example: false
Expand Down
34 changes: 31 additions & 3 deletions server/entity/Media.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import RadarrAPI from '@server/api/servarr/radarr';
import SonarrAPI from '@server/api/servarr/sonarr';
import { MediaStatus, MediaType } from '@server/constants/media';
import {
MediaRequestStatus,
MediaStatus,
MediaType,
} from '@server/constants/media';
import { MediaServerType } from '@server/constants/server';
import { getRepository } from '@server/datasource';
import { Blocklist } from '@server/entity/Blocklist';
Expand Down Expand Up @@ -49,13 +53,36 @@ class Media {
'watchlist',
'media.id= watchlist.media and watchlist.requestedBy = :userId',
{ userId: user?.id }
) //,
)
.where(' media.tmdbId in (:...finalIds)', { finalIds })
.getMany();

return media.filter((m) =>
const relatedMedia = media.filter((m) =>
items.some((i) => i.tmdbId === m.tmdbId && i.mediaType === m.mediaType)
);

if (getSettings().main.hideRequested && relatedMedia.length > 0) {
const activeRequestMediaIds = await mediaRepository
.createQueryBuilder('media')
.select('media.id', 'id')
.distinct(true)
.innerJoin('media.requests', 'request')
.where('media.id IN (:...mediaIds)', {
mediaIds: relatedMedia.map((m) => m.id),
})
.andWhere('request.status IN (:...statuses)', {
statuses: [MediaRequestStatus.PENDING, MediaRequestStatus.APPROVED],
})
.getRawMany<{ id: number }>();

const activeIds = new Set(activeRequestMediaIds.map((row) => row.id));

relatedMedia.forEach((m) => {
m.hasActiveRequest = activeIds.has(m.id);
});
}

return relatedMedia;
} catch (e) {
logger.error(e.message);
return [];
Expand Down Expand Up @@ -187,6 +214,7 @@ class Media {

public serviceUrl?: string;
public serviceUrl4k?: string;
public hasActiveRequest?: boolean;
public downloadStatus?: DownloadingItem[] = [];
public downloadStatus4k?: DownloadingItem[] = [];

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 @@ -31,6 +31,7 @@ export interface PublicSettingsResponse {
applicationUrl: string;
hideAvailable: boolean;
hideBlocklisted: boolean;
hideRequested: boolean;
localLogin: boolean;
mediaServerLogin: boolean;
movie4kEnabled: boolean;
Expand Down
4 changes: 4 additions & 0 deletions server/lib/settings/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ export interface MainSettings {
};
hideAvailable: boolean;
hideBlocklisted: boolean;
hideRequested: boolean;
localLogin: boolean;
mediaServerLogin: boolean;
newPlexLogin: boolean;
Expand Down Expand Up @@ -193,6 +194,7 @@ interface FullPublicSettings extends PublicSettings {
applicationUrl: string;
hideAvailable: boolean;
hideBlocklisted: boolean;
hideRequested: boolean;
localLogin: boolean;
mediaServerLogin: boolean;
movie4kEnabled: boolean;
Expand Down Expand Up @@ -414,6 +416,7 @@ class Settings {
},
hideAvailable: false,
hideBlocklisted: false,
hideRequested: false,
localLogin: true,
mediaServerLogin: true,
newPlexLogin: true,
Expand Down Expand Up @@ -709,6 +712,7 @@ class Settings {
applicationUrl: this.data.main.applicationUrl,
hideAvailable: this.data.main.hideAvailable,
hideBlocklisted: this.data.main.hideBlocklisted,
hideRequested: this.data.main.hideRequested,
localLogin: this.data.main.localLogin,
mediaServerLogin: this.data.main.mediaServerLogin,
jellyfinExternalHost: this.data.jellyfin.externalHostname,
Expand Down
10 changes: 10 additions & 0 deletions src/components/MediaSlider/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,16 @@ const MediaSlider = ({
);
}

if (settings.currentSettings.hideRequested) {
titles = titles.filter((i) => {
if (i.mediaType !== 'movie' && i.mediaType !== 'tv') {
return true;
}

return !i.mediaInfo?.hasActiveRequest;
});
}
Comment thread
0xSysR3ll marked this conversation as resolved.

useEffect(() => {
if (
titles.length < 24 &&
Expand Down
2 changes: 1 addition & 1 deletion src/components/Search/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const Search = () => {
{
query: router.query.query,
},
{ hideAvailable: false, hideBlocklisted: false }
{ hideAvailable: false, hideBlocklisted: false, hideRequested: false }
);

if (error) {
Expand Down
25 changes: 25 additions & 0 deletions src/components/Settings/SettingsMain/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ const messages = defineMessages('components.Settings.SettingsMain', {
hideAvailable: 'Hide Available Media',
hideAvailableTip:
'Hide available media from the discover pages but not search results',
hideRequested: 'Hide Requested Media',
hideRequestedTip:
'Hide media that has been requested from the discover pages but not search results',
cacheImages: 'Enable Image Caching',
cacheImagesTip:
'Cache externally sourced images (requires a significant amount of disk space)',
Expand Down Expand Up @@ -171,6 +174,7 @@ const SettingsMain = () => {
applicationUrl: data?.applicationUrl,
hideAvailable: data?.hideAvailable,
hideBlocklisted: data?.hideBlocklisted,
hideRequested: data?.hideRequested,
locale: data?.locale ?? 'en',
discoverRegion: data?.discoverRegion,
originalLanguage: data?.originalLanguage,
Expand All @@ -193,6 +197,7 @@ const SettingsMain = () => {
applicationUrl: values.applicationUrl,
hideAvailable: values.hideAvailable,
hideBlocklisted: values.hideBlocklisted,
hideRequested: values.hideRequested,
locale: values.locale,
discoverRegion: values.discoverRegion,
streamingRegion: values.streamingRegion,
Expand Down Expand Up @@ -538,6 +543,26 @@ const SettingsMain = () => {
/>
</div>
</div>
<div className="form-row">
<label htmlFor="hideRequested" className="checkbox-label">
<span className="mr-2">
{intl.formatMessage(messages.hideRequested)}
</span>
<span className="label-tip">
{intl.formatMessage(messages.hideRequestedTip)}
</span>
</label>
<div className="form-input-area">
<Field
type="checkbox"
id="hideRequested"
name="hideRequested"
onChange={() => {
setFieldValue('hideRequested', !values.hideRequested);
}}
/>
</div>
</div>
<div className="form-row">
<label
htmlFor="partialRequestsEnabled"
Expand Down
1 change: 1 addition & 0 deletions src/context/SettingsContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const defaultSettings = {
applicationUrl: '',
hideAvailable: false,
hideBlocklisted: false,
hideRequested: false,
localLogin: true,
mediaServerLogin: true,
movie4kEnabled: false,
Expand Down
13 changes: 12 additions & 1 deletion src/hooks/useDiscover.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ interface BaseMedia {
mediaType: string;
mediaInfo?: {
status: MediaStatus;
hasActiveRequest?: boolean;
};
}

Expand Down Expand Up @@ -58,7 +59,7 @@ const useDiscover = <
>(
endpoint: string,
options?: O,
{ hideAvailable = true, hideBlocklisted = true } = {}
{ hideAvailable = true, hideBlocklisted = true, hideRequested = true } = {}
): DiscoverResult<T, S> => {
const settings = useSettings();
const { hasPermission } = useUser();
Expand Down Expand Up @@ -142,6 +143,16 @@ const useDiscover = <
);
}

if (settings.currentSettings.hideRequested && hideRequested) {
titles = titles.filter((i) => {
if (i.mediaType !== 'movie' && i.mediaType !== 'tv') {
return true;
}

return !i.mediaInfo?.hasActiveRequest;
});
}

const isEmpty = !isLoadingInitialData && titles?.length === 0;
const isReachingEnd =
isEmpty ||
Expand Down
2 changes: 2 additions & 0 deletions src/i18n/locale/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1030,6 +1030,8 @@
"components.Settings.SettingsMain.hideAvailableTip": "Hide available media from the discover pages but not search results",
"components.Settings.SettingsMain.hideBlocklisted": "Hide Blocklisted Items",
"components.Settings.SettingsMain.hideBlocklistedTip": "Hide blocklisted items from discover pages for all users with the \"Manage Blocklist\" permission",
"components.Settings.SettingsMain.hideRequested": "Hide Requested Media",
"components.Settings.SettingsMain.hideRequestedTip": "Hide media that has been requested from the discover pages but not search results",
"components.Settings.SettingsMain.locale": "Display Language",
"components.Settings.SettingsMain.originallanguage": "Discover Language",
"components.Settings.SettingsMain.originallanguageTip": "Filter content by original language",
Expand Down
1 change: 1 addition & 0 deletions src/pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ CoreApp.getInitialProps = async (initialProps) => {
applicationUrl: '',
hideAvailable: false,
hideBlocklisted: false,
hideRequested: false,
movie4kEnabled: false,
series4kEnabled: false,
localLogin: true,
Expand Down
Loading