From 63aa24c02aeab56f5cfa88b4ec8bf669802f433e Mon Sep 17 00:00:00 2001 From: Janne Koschinski <janne@kuschku.de> Date: Tue, 5 Jan 2021 21:06:35 +0100 Subject: [PATCH] Implement proper language selection for images --- src/api/models/Image.ts | 1 + src/routes/main/MainPage.tsx | 60 ++++++++++++++++++++++++----- src/routes/main/MediaEntry.tsx | 34 ++++++++++++++-- src/util/locale/Locale.ts | 2 +- src/util/locale/LocalizedContext.ts | 4 +- 5 files changed, 86 insertions(+), 15 deletions(-) diff --git a/src/api/models/Image.ts b/src/api/models/Image.ts index 14c8909..351160b 100644 --- a/src/api/models/Image.ts +++ b/src/api/models/Image.ts @@ -1,5 +1,6 @@ export interface Image { kind: string, mime: string, + language: string, src: string } diff --git a/src/routes/main/MainPage.tsx b/src/routes/main/MainPage.tsx index ef2804e..b77e4b6 100644 --- a/src/routes/main/MainPage.tsx +++ b/src/routes/main/MainPage.tsx @@ -1,23 +1,65 @@ import {Content, getLocalizedName} from "../../api/models/Content"; import {sortLexicallyAsc} from "../../util/sort/sortLexically"; import {MediaEntry} from "./MediaEntry"; -import {useLocale} from "../../util/locale/LocalizedContext"; +import {LocaleProvider} from "../../util/locale/LocalizedContext"; import {useAllContent} from "../../api/ApiHooks"; +import {Locale} from "../../util/locale/Locale"; +import {useState} from "react"; +import {createUseStyles} from "react-jss"; -export function MainPage() { - const locale = useLocale(); +const locales: { [key: string]: Locale } = { + "de-DE": { + language: "de", + region: "DE", + }, + "de-AT": { + language: "de", + region: "AT", + }, + "ja-JP": { + language: "ja", + region: "JP", + }, + "en-US": { + language: "en", + region: "US", + }, +} +export function MainPage() { + const classes = useStyles(); + const [locale, setLocale] = useState<Locale>(locales["en-US"]); const [media/*, isLoading, error*/] = useAllContent(); return ( <div> - {media - .sort(sortLexicallyAsc(item => getLocalizedName(item, locale)?.name || "")) - .map((item: Content) => ( - <MediaEntry - key={item.ids.uuid} - item={item}/> + <select + className={classes.languagePicker} + value={locale.language + "-" + locale.region} + onChange={(event) => + setLocale(locales[event.target.value])} + > + {Object.keys(locales).map(code => ( + <option key={code} value={code}>{code}</option> ))} + </select> + <LocaleProvider value={locale}> + {media + .sort(sortLexicallyAsc(item => getLocalizedName(item, locale)?.name || "")) + .map((item: Content) => ( + <MediaEntry + key={item.ids.uuid} + item={item}/> + ))} + </LocaleProvider> </div> ); } + +const useStyles = createUseStyles({ + languagePicker: { + position: "fixed", + right: 5, + top: 5, + }, +}); diff --git a/src/routes/main/MediaEntry.tsx b/src/routes/main/MediaEntry.tsx index 125472b..dfa2e08 100644 --- a/src/routes/main/MediaEntry.tsx +++ b/src/routes/main/MediaEntry.tsx @@ -1,15 +1,33 @@ import {Content, getLocalizedDescription, getLocalizedName, getLocalizedRating} from "../../api/models/Content"; -import {Fragment} from "react"; +import {Fragment, useMemo} from "react"; import {Link} from "react-router-dom"; import {createUseStyles} from "react-jss"; import {useLocale} from "../../util/locale/LocalizedContext"; import {useShowEpisodes} from "../../api/ApiHooks"; import {MediaEpisode} from "./MediaEpisode"; +import {Image} from "../../api/models/Image"; export interface Props { item: Content } +function findImage( + images: Image[], + type: string, + languages: (string | null)[] +): Image | null { + const imageList = images.filter(it => it.kind === type) + + for (let language of languages) { + const image = imageList.find(it => it.language === language); + if (image) { + return image; + } + } + + return null; +} + export function MediaEntry( {item}: Props ) { @@ -21,12 +39,22 @@ export function MediaEntry( const title = getLocalizedName(item, locale); const description = getLocalizedDescription(item, locale); const rating = getLocalizedRating(item, locale); - const poster = item.images.find(it => it.kind === "poster"); - const backdrop = item.images.find(it => it.kind === "backdrop"); + const [logo, poster, backdrop] = useMemo(() => [ + findImage(item.images, "logo", [locale.language]), + findImage(item.images, "poster", [locale.language, item.originalLanguage, null]), + findImage(item.images, "backdrop", [locale.language, item.originalLanguage, null]) + ], [item.images, item.originalLanguage, locale.language]); return ( <div className={classes.movie}> <h1>{title?.name}</h1> + {logo && ( + <img + className={classes.poster} + alt={`Movie logo for ${title?.name}`} + src={logo.src} + /> + )} <p><strong>{rating?.certification}</strong></p> <p><strong>{description?.tagline}</strong></p> <p>{description?.overview}</p> diff --git a/src/util/locale/Locale.ts b/src/util/locale/Locale.ts index cd3d7ca..2afc505 100644 --- a/src/util/locale/Locale.ts +++ b/src/util/locale/Locale.ts @@ -1,4 +1,4 @@ export interface Locale { language: string, - region: string + region: string, } diff --git a/src/util/locale/LocalizedContext.ts b/src/util/locale/LocalizedContext.ts index 6af244a..c8236cd 100644 --- a/src/util/locale/LocalizedContext.ts +++ b/src/util/locale/LocalizedContext.ts @@ -5,6 +5,6 @@ const LocalizedContext = createContext<Locale>({ language: "en", region: "US", }); -export const LocalizedProvider = LocalizedContext.Provider; -export const LocalizedConsumer = LocalizedContext.Consumer; +export const LocaleProvider = LocalizedContext.Provider; +export const LocaleConsumer = LocalizedContext.Consumer; export const useLocale = () => useContext(LocalizedContext); -- GitLab