From 0ca3d4374942b54b59a19d017ab4ae14ba7019c1 Mon Sep 17 00:00:00 2001 From: sct Date: Thu, 18 Mar 2021 21:37:25 +0900 Subject: [PATCH] feat: add option to cache images locally (#1213) --- next.config.js | 3 + server/interfaces/api/settingsInterfaces.ts | 1 + server/lib/settings.ts | 4 ++ src/components/CollectionDetails/index.tsx | 39 +++++++++-- src/components/Common/CachedImage/index.tsx | 18 +++++ src/components/Common/ImageFader/index.tsx | 47 +++++++------ .../Discover/MovieGenreList/index.tsx | 2 +- .../Discover/MovieGenreSlider/index.tsx | 2 +- src/components/Discover/TvGenreList/index.tsx | 2 +- .../Discover/TvGenreSlider/index.tsx | 2 +- src/components/GenreCard/index.tsx | 5 +- src/components/Login/index.tsx | 2 +- src/components/MovieDetails/index.tsx | 67 ++++++++++++++----- src/components/PersonCard/index.tsx | 14 ++-- src/components/PersonDetails/index.tsx | 17 +++-- src/components/RequestCard/index.tsx | 37 +++++++--- .../RequestList/RequestItem/index.tsx | 37 ++++++---- src/components/Settings/SettingsMain.tsx | 25 +++++++ src/components/TitleCard/index.tsx | 17 +++-- src/components/TvDetails/index.tsx | 43 +++++++++--- .../UserProfile/ProfileHeader/index.tsx | 2 +- src/components/UserProfile/index.tsx | 2 +- src/context/SettingsContext.tsx | 1 + src/i18n/locale/en.json | 2 + src/pages/_app.tsx | 1 + src/styles/globals.css | 9 ++- 26 files changed, 293 insertions(+), 108 deletions(-) create mode 100644 src/components/Common/CachedImage/index.tsx diff --git a/next.config.js b/next.config.js index 8c1766af8..d3c0a4e6b 100644 --- a/next.config.js +++ b/next.config.js @@ -2,6 +2,9 @@ module.exports = { env: { commitTag: process.env.COMMIT_TAG || 'local', }, + images: { + domains: ['image.tmdb.org'], + }, webpack(config) { config.module.rules.push({ test: /\.svg$/, diff --git a/server/interfaces/api/settingsInterfaces.ts b/server/interfaces/api/settingsInterfaces.ts index 67925bb32..412ed638b 100644 --- a/server/interfaces/api/settingsInterfaces.ts +++ b/server/interfaces/api/settingsInterfaces.ts @@ -28,6 +28,7 @@ export interface PublicSettingsResponse { region: string; originalLanguage: string; partialRequestsEnabled: boolean; + cacheImages: boolean; } export interface CacheItem { diff --git a/server/lib/settings.ts b/server/lib/settings.ts index 1b4321187..706ed19eb 100644 --- a/server/lib/settings.ts +++ b/server/lib/settings.ts @@ -66,6 +66,7 @@ export interface MainSettings { applicationTitle: string; applicationUrl: string; csrfProtection: boolean; + cacheImages: boolean; defaultPermissions: number; hideAvailable: boolean; localLogin: boolean; @@ -88,6 +89,7 @@ interface FullPublicSettings extends PublicSettings { region: string; originalLanguage: string; partialRequestsEnabled: boolean; + cacheImages: boolean; } export interface NotificationAgentConfig { @@ -195,6 +197,7 @@ class Settings { applicationTitle: 'Overseerr', applicationUrl: '', csrfProtection: false, + cacheImages: false, defaultPermissions: Permission.REQUEST, hideAvailable: false, localLogin: true, @@ -349,6 +352,7 @@ class Settings { region: this.data.main.region, originalLanguage: this.data.main.originalLanguage, partialRequestsEnabled: this.data.main.partialRequestsEnabled, + cacheImages: this.data.main.cacheImages, }; } diff --git a/src/components/CollectionDetails/index.tsx b/src/components/CollectionDetails/index.tsx index 5f7cbceeb..251d8d953 100644 --- a/src/components/CollectionDetails/index.tsx +++ b/src/components/CollectionDetails/index.tsx @@ -21,6 +21,7 @@ import { useUser, Permission } from '../../hooks/useUser'; import useSettings from '../../hooks/useSettings'; import Link from 'next/link'; import { uniq } from 'lodash'; +import CachedImage from '../Common/CachedImage'; const messages = defineMessages({ overviewunavailable: 'Overview unavailable.', @@ -203,9 +204,26 @@ const CollectionDetails: React.FC = ({ className="media-page" style={{ height: 493, - backgroundImage: `linear-gradient(180deg, rgba(17, 24, 39, 0.47) 0%, rgba(17, 24, 39, 1) 100%), url(//image.tmdb.org/t/p/w1920_and_h800_multi_faces/${data.backdropPath})`, }} > + {data.backdropPath && ( +
+ +
+
+ )} = ({
- +
+ +
= (props) => { + const { currentSettings } = useSettings(); + + return ; +}; + +export default CachedImage; diff --git a/src/components/Common/ImageFader/index.tsx b/src/components/Common/ImageFader/index.tsx index d6ad868cd..eed8475fa 100644 --- a/src/components/Common/ImageFader/index.tsx +++ b/src/components/Common/ImageFader/index.tsx @@ -4,13 +4,13 @@ import React, { HTMLAttributes, ForwardRefRenderFunction, } from 'react'; -import Image from 'next/image'; +import CachedImage from '../CachedImage'; interface ImageFaderProps extends HTMLAttributes { backgroundImages: string[]; rotationSpeed?: number; isDarker?: boolean; - useImage?: boolean; + forceOptimize?: boolean; } const DEFAULT_ROTATION_SPEED = 6000; @@ -20,7 +20,7 @@ const ImageFader: ForwardRefRenderFunction = ( backgroundImages, rotationSpeed = DEFAULT_ROTATION_SPEED, isDarker, - useImage, + forceOptimize, ...props }, ref @@ -46,6 +46,14 @@ const ImageFader: ForwardRefRenderFunction = ( 'linear-gradient(180deg, rgba(17, 24, 39, 0.47) 0%, rgba(17, 24, 39, 1) 100%)'; } + let overrides = {}; + + if (forceOptimize) { + overrides = { + unoptimized: false, + }; + } + return (
{backgroundImages.map((imageUrl, i) => ( @@ -54,29 +62,20 @@ const ImageFader: ForwardRefRenderFunction = ( className={`absolute inset-0 bg-cover bg-center transition-opacity duration-300 ease-in ${ i === activeIndex ? 'opacity-100' : 'opacity-0' }`} - style={{ - backgroundImage: !useImage - ? `${gradient}, url(${imageUrl})` - : undefined, - }} {...props} > - {useImage && ( - <> - -
- - )} + +
))}
diff --git a/src/components/Discover/MovieGenreList/index.tsx b/src/components/Discover/MovieGenreList/index.tsx index 0abd53c4c..e7b124160 100644 --- a/src/components/Discover/MovieGenreList/index.tsx +++ b/src/components/Discover/MovieGenreList/index.tsx @@ -40,7 +40,7 @@ const MovieGenreList: React.FC = () => {
  • { {
  • { = ({ ? 'bg-gray-700 scale-105 ring-gray-500 bg-opacity-100' : 'bg-gray-800 scale-100 ring-gray-700 bg-opacity-80' } rounded-xl bg-cover bg-center overflow-hidden`} - style={{ - backgroundImage: `url("${image}")`, - }} onMouseEnter={() => { setHovered(true); }} @@ -42,6 +40,7 @@ const GenreCard: React.FC = ({ role="link" tabIndex={0} > +
    {
    = ({ movie }) => { className="media-page" style={{ height: 493, - backgroundImage: `linear-gradient(180deg, rgba(17, 24, 39, 0.47) 0%, rgba(17, 24, 39, 1) 100%), url(//image.tmdb.org/t/p/w1920_and_h800_multi_faces/${data.backdropPath})`, }} > + {data.backdropPath && ( +
    + +
    +
    + )} = ({ movie }) => { )}
    - +
    + +
    = ({ movie }) => {
    -
    -
    +
    +
    + +
    +
    +
    {data.collection.name}