mirror of
https://github.com/sct/overseerr.git
synced 2025-09-17 17:24:35 +02:00
feat: dynamically fetch login screen backdrop images (#2206)
* feat: dynamically fetch login screen backdrop images * fix: remove media check from backdrops endpoint * fix: remove mapping and work with TMDb data directly
This commit is contained in:
@@ -5167,6 +5167,22 @@ paths:
|
|||||||
name:
|
name:
|
||||||
type: string
|
type: string
|
||||||
example: Drama
|
example: Drama
|
||||||
|
/backdrops:
|
||||||
|
get:
|
||||||
|
summary: Get backdrops of trending items
|
||||||
|
description: Returns a list of backdrop image paths in a JSON array.
|
||||||
|
security: []
|
||||||
|
tags:
|
||||||
|
- tmdb
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Results
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
|
||||||
security:
|
security:
|
||||||
- cookieAuth: []
|
- cookieAuth: []
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 134 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.0 MiB |
Binary file not shown.
Before Width: | Height: | Size: 372 KiB |
Binary file not shown.
Before Width: | Height: | Size: 407 KiB |
Binary file not shown.
Before Width: | Height: | Size: 384 KiB |
Binary file not shown.
Before Width: | Height: | Size: 421 KiB |
@@ -12,7 +12,7 @@ import { mapMovieResult, mapPersonResult, mapTvResult } from '../models/Search';
|
|||||||
import { mapNetwork } from '../models/Tv';
|
import { mapNetwork } from '../models/Tv';
|
||||||
import { isMovie, isPerson } from '../utils/typeHelpers';
|
import { isMovie, isPerson } from '../utils/typeHelpers';
|
||||||
|
|
||||||
const createTmdbWithRegionLanaguage = (user?: User): TheMovieDb => {
|
export const createTmdbWithRegionLanguage = (user?: User): TheMovieDb => {
|
||||||
const settings = getSettings();
|
const settings = getSettings();
|
||||||
|
|
||||||
const region =
|
const region =
|
||||||
@@ -38,7 +38,7 @@ const createTmdbWithRegionLanaguage = (user?: User): TheMovieDb => {
|
|||||||
const discoverRoutes = Router();
|
const discoverRoutes = Router();
|
||||||
|
|
||||||
discoverRoutes.get('/movies', async (req, res) => {
|
discoverRoutes.get('/movies', async (req, res) => {
|
||||||
const tmdb = createTmdbWithRegionLanaguage(req.user);
|
const tmdb = createTmdbWithRegionLanguage(req.user);
|
||||||
|
|
||||||
const data = await tmdb.getDiscoverMovies({
|
const data = await tmdb.getDiscoverMovies({
|
||||||
page: Number(req.query.page),
|
page: Number(req.query.page),
|
||||||
@@ -69,7 +69,7 @@ discoverRoutes.get('/movies', async (req, res) => {
|
|||||||
discoverRoutes.get<{ language: string }>(
|
discoverRoutes.get<{ language: string }>(
|
||||||
'/movies/language/:language',
|
'/movies/language/:language',
|
||||||
async (req, res, next) => {
|
async (req, res, next) => {
|
||||||
const tmdb = createTmdbWithRegionLanaguage(req.user);
|
const tmdb = createTmdbWithRegionLanguage(req.user);
|
||||||
|
|
||||||
const languages = await tmdb.getLanguages();
|
const languages = await tmdb.getLanguages();
|
||||||
|
|
||||||
@@ -112,7 +112,7 @@ discoverRoutes.get<{ language: string }>(
|
|||||||
discoverRoutes.get<{ genreId: string }>(
|
discoverRoutes.get<{ genreId: string }>(
|
||||||
'/movies/genre/:genreId',
|
'/movies/genre/:genreId',
|
||||||
async (req, res, next) => {
|
async (req, res, next) => {
|
||||||
const tmdb = createTmdbWithRegionLanaguage(req.user);
|
const tmdb = createTmdbWithRegionLanguage(req.user);
|
||||||
|
|
||||||
const genres = await tmdb.getMovieGenres({
|
const genres = await tmdb.getMovieGenres({
|
||||||
language: req.locale ?? (req.query.language as string),
|
language: req.locale ?? (req.query.language as string),
|
||||||
@@ -194,7 +194,7 @@ discoverRoutes.get<{ studioId: string }>(
|
|||||||
);
|
);
|
||||||
|
|
||||||
discoverRoutes.get('/movies/upcoming', async (req, res) => {
|
discoverRoutes.get('/movies/upcoming', async (req, res) => {
|
||||||
const tmdb = createTmdbWithRegionLanaguage(req.user);
|
const tmdb = createTmdbWithRegionLanguage(req.user);
|
||||||
|
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const offset = now.getTimezoneOffset();
|
const offset = now.getTimezoneOffset();
|
||||||
@@ -228,7 +228,7 @@ discoverRoutes.get('/movies/upcoming', async (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
discoverRoutes.get('/tv', async (req, res) => {
|
discoverRoutes.get('/tv', async (req, res) => {
|
||||||
const tmdb = createTmdbWithRegionLanaguage(req.user);
|
const tmdb = createTmdbWithRegionLanguage(req.user);
|
||||||
|
|
||||||
const data = await tmdb.getDiscoverTv({
|
const data = await tmdb.getDiscoverTv({
|
||||||
page: Number(req.query.page),
|
page: Number(req.query.page),
|
||||||
@@ -259,7 +259,7 @@ discoverRoutes.get('/tv', async (req, res) => {
|
|||||||
discoverRoutes.get<{ language: string }>(
|
discoverRoutes.get<{ language: string }>(
|
||||||
'/tv/language/:language',
|
'/tv/language/:language',
|
||||||
async (req, res, next) => {
|
async (req, res, next) => {
|
||||||
const tmdb = createTmdbWithRegionLanaguage(req.user);
|
const tmdb = createTmdbWithRegionLanguage(req.user);
|
||||||
|
|
||||||
const languages = await tmdb.getLanguages();
|
const languages = await tmdb.getLanguages();
|
||||||
|
|
||||||
@@ -301,7 +301,7 @@ discoverRoutes.get<{ language: string }>(
|
|||||||
discoverRoutes.get<{ genreId: string }>(
|
discoverRoutes.get<{ genreId: string }>(
|
||||||
'/tv/genre/:genreId',
|
'/tv/genre/:genreId',
|
||||||
async (req, res, next) => {
|
async (req, res, next) => {
|
||||||
const tmdb = createTmdbWithRegionLanaguage(req.user);
|
const tmdb = createTmdbWithRegionLanguage(req.user);
|
||||||
|
|
||||||
const genres = await tmdb.getTvGenres({
|
const genres = await tmdb.getTvGenres({
|
||||||
language: req.locale ?? (req.query.language as string),
|
language: req.locale ?? (req.query.language as string),
|
||||||
@@ -382,7 +382,7 @@ discoverRoutes.get<{ networkId: string }>(
|
|||||||
);
|
);
|
||||||
|
|
||||||
discoverRoutes.get('/tv/upcoming', async (req, res) => {
|
discoverRoutes.get('/tv/upcoming', async (req, res) => {
|
||||||
const tmdb = createTmdbWithRegionLanaguage(req.user);
|
const tmdb = createTmdbWithRegionLanguage(req.user);
|
||||||
|
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const offset = now.getTimezoneOffset();
|
const offset = now.getTimezoneOffset();
|
||||||
@@ -416,7 +416,7 @@ discoverRoutes.get('/tv/upcoming', async (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
discoverRoutes.get('/trending', async (req, res) => {
|
discoverRoutes.get('/trending', async (req, res) => {
|
||||||
const tmdb = createTmdbWithRegionLanaguage(req.user);
|
const tmdb = createTmdbWithRegionLanguage(req.user);
|
||||||
|
|
||||||
const data = await tmdb.getAllTrending({
|
const data = await tmdb.getAllTrending({
|
||||||
page: Number(req.query.page),
|
page: Number(req.query.page),
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
import { Router } from 'express';
|
import { Router } from 'express';
|
||||||
import GithubAPI from '../api/github';
|
import GithubAPI from '../api/github';
|
||||||
import TheMovieDb from '../api/themoviedb';
|
import TheMovieDb from '../api/themoviedb';
|
||||||
|
import { TmdbMovieResult, TmdbTvResult } from '../api/themoviedb/interfaces';
|
||||||
import { StatusResponse } from '../interfaces/api/settingsInterfaces';
|
import { StatusResponse } from '../interfaces/api/settingsInterfaces';
|
||||||
import { Permission } from '../lib/permissions';
|
import { Permission } from '../lib/permissions';
|
||||||
import { getSettings } from '../lib/settings';
|
import { getSettings } from '../lib/settings';
|
||||||
@@ -9,9 +10,10 @@ import { mapProductionCompany } from '../models/Movie';
|
|||||||
import { mapNetwork } from '../models/Tv';
|
import { mapNetwork } from '../models/Tv';
|
||||||
import { appDataPath, appDataStatus } from '../utils/appDataVolume';
|
import { appDataPath, appDataStatus } from '../utils/appDataVolume';
|
||||||
import { getAppVersion, getCommitTag } from '../utils/appVersion';
|
import { getAppVersion, getCommitTag } from '../utils/appVersion';
|
||||||
|
import { isPerson } from '../utils/typeHelpers';
|
||||||
import authRoutes from './auth';
|
import authRoutes from './auth';
|
||||||
import collectionRoutes from './collection';
|
import collectionRoutes from './collection';
|
||||||
import discoverRoutes from './discover';
|
import discoverRoutes, { createTmdbWithRegionLanguage } from './discover';
|
||||||
import mediaRoutes from './media';
|
import mediaRoutes from './media';
|
||||||
import movieRoutes from './movie';
|
import movieRoutes from './movie';
|
||||||
import personRoutes from './person';
|
import personRoutes from './person';
|
||||||
@@ -160,6 +162,28 @@ router.get('/genres/tv', isAuthenticated(), async (req, res) => {
|
|||||||
return res.status(200).json(genres);
|
return res.status(200).json(genres);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
router.get('/backdrops', async (req, res) => {
|
||||||
|
const tmdb = createTmdbWithRegionLanguage();
|
||||||
|
|
||||||
|
const data = (
|
||||||
|
await tmdb.getAllTrending({
|
||||||
|
page: 1,
|
||||||
|
timeWindow: 'week',
|
||||||
|
})
|
||||||
|
).results.filter((result) => !isPerson(result)) as (
|
||||||
|
| TmdbMovieResult
|
||||||
|
| TmdbTvResult
|
||||||
|
)[];
|
||||||
|
|
||||||
|
return res
|
||||||
|
.status(200)
|
||||||
|
.json(
|
||||||
|
data
|
||||||
|
.map((result) => result.backdrop_path)
|
||||||
|
.filter((backdropPath) => !!backdropPath)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
router.get('/', (_req, res) => {
|
router.get('/', (_req, res) => {
|
||||||
return res.status(200).json({
|
return res.status(200).json({
|
||||||
api: 'Overseerr API',
|
api: 'Overseerr API',
|
||||||
|
@@ -3,6 +3,7 @@ import axios from 'axios';
|
|||||||
import { useRouter } from 'next/dist/client/router';
|
import { useRouter } from 'next/dist/client/router';
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { defineMessages, useIntl } from 'react-intl';
|
import { defineMessages, useIntl } from 'react-intl';
|
||||||
|
import useSWR from 'swr';
|
||||||
import useSettings from '../../hooks/useSettings';
|
import useSettings from '../../hooks/useSettings';
|
||||||
import { useUser } from '../../hooks/useUser';
|
import { useUser } from '../../hooks/useUser';
|
||||||
import Accordion from '../Common/Accordion';
|
import Accordion from '../Common/Accordion';
|
||||||
@@ -60,19 +61,21 @@ const Login: React.FC = () => {
|
|||||||
}
|
}
|
||||||
}, [user, router]);
|
}, [user, router]);
|
||||||
|
|
||||||
|
const { data: backdrops } = useSWR<string[]>('/api/v1/backdrops', {
|
||||||
|
refreshInterval: 0,
|
||||||
|
refreshWhenHidden: false,
|
||||||
|
revalidateOnFocus: false,
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative flex flex-col min-h-screen bg-gray-900 py-14">
|
<div className="relative flex flex-col min-h-screen bg-gray-900 py-14">
|
||||||
<PageTitle title={intl.formatMessage(messages.signin)} />
|
<PageTitle title={intl.formatMessage(messages.signin)} />
|
||||||
<ImageFader
|
<ImageFader
|
||||||
forceOptimize
|
backgroundImages={
|
||||||
backgroundImages={[
|
backdrops?.map(
|
||||||
'/images/rotate1.jpg',
|
(backdrop) => `https://www.themoviedb.org/t/p/original${backdrop}`
|
||||||
'/images/rotate2.jpg',
|
) ?? []
|
||||||
'/images/rotate3.jpg',
|
}
|
||||||
'/images/rotate4.jpg',
|
|
||||||
'/images/rotate5.jpg',
|
|
||||||
'/images/rotate6.jpg',
|
|
||||||
]}
|
|
||||||
/>
|
/>
|
||||||
<div className="absolute z-50 top-4 right-4">
|
<div className="absolute z-50 top-4 right-4">
|
||||||
<LanguagePicker />
|
<LanguagePicker />
|
||||||
|
Reference in New Issue
Block a user