From cf02a0fb24ea198c69c18a8287e472e4ba6a9b9a Mon Sep 17 00:00:00 2001
From: Janne Koschinski <janne@kuschku.de>
Date: Sat, 26 Sep 2020 15:21:49 +0200
Subject: [PATCH] Improve locale/regional selection

---
 src/App.tsx                        | 86 +++++++++++++++---------------
 src/api/models/LocalizedData.ts    |  5 --
 src/api/models/Rating.ts           |  2 +-
 src/api/models/Title.ts            | 13 +++++
 src/api/models/TitleDescription.ts |  2 +-
 src/api/models/TitleName.ts        |  2 +-
 src/locale/Locale.ts               |  4 ++
 src/locale/LocalePriority.ts       |  4 ++
 src/locale/LocalizedData.ts        |  6 +++
 src/locale/RegionalData.ts         |  3 ++
 src/locale/selectLocaleData.ts     | 31 ++++-------
 src/locale/selectRegionalData.ts   | 11 ++++
 12 files changed, 99 insertions(+), 70 deletions(-)
 delete mode 100644 src/api/models/LocalizedData.ts
 create mode 100644 src/locale/Locale.ts
 create mode 100644 src/locale/LocalePriority.ts
 create mode 100644 src/locale/LocalizedData.ts
 create mode 100644 src/locale/RegionalData.ts
 create mode 100644 src/locale/selectRegionalData.ts

diff --git a/src/App.tsx b/src/App.tsx
index 1859c58..14fdcf3 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -1,8 +1,8 @@
 import React, {useEffect, useState} from 'react';
 import {createUseStyles} from "react-jss";
 import {useApiClient} from "./api/ApiClientContext";
-import {Title} from "./api/models/Title";
-import {Locale, LocalePriority, selectLocaleVersion} from "./locale/selectLocaleData";
+import {getLocalizedDescription, getLocalizedName, getLocalizedRating, Title} from "./api/models/Title";
+import {Locale} from "./locale/Locale";
 import {usePlayabilityRating} from "./mime/usePlayabilityRating";
 import {sortLexicallyAsc} from "./util/sortLexically";
 import {sortNumericallyDesc} from "./util/sortNumerically";
@@ -23,48 +23,50 @@ export default function App() {
 
     return (
         <div>
-            {data?.sort(sortLexicallyAsc(item =>
-                selectLocaleVersion(locale, LocalePriority.REGION_BEFORE_LOCALE, item.titles)?.name || ""))
+            {data?.sort(sortLexicallyAsc(item => getLocalizedName(item, locale)?.name || ""))
                 .map((item: Title) => {
-                const title = selectLocaleVersion(locale, LocalePriority.REGION_BEFORE_LOCALE, item.titles);
-                const description = selectLocaleVersion(locale, LocalePriority.LOCALE_BEFORE_REGION, item.descriptions);
-                const rating = selectLocaleVersion(locale, LocalePriority.REGION_ONLY, item.ratings);
-                const poster = item.images.find(it => it.kind === "poster");
-                const backdrop = item.images.find(it => it.kind === "backdrop");
-                const mediaList = item.media.map(it => {
-                    return {
-                        item: it,
-                        value: playabilityRating(it),
-                    };
-                }).sort(sortNumericallyDesc(it => it.value));
-                const media = mediaList[0]?.item;
+                    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 mediaList = item.media.map(it => {
+                        return {
+                            item: it,
+                            value: playabilityRating(it),
+                        };
+                    }).sort(sortNumericallyDesc(it => it.value));
+                    const media = mediaList[0]?.item;
 
-                return (
-                    <div key={item.ids.uuid} className={classes.movie}>
-                        <h1>{title?.name}</h1>
-                        <p><strong>{description?.tagline}</strong></p>
-                        <p>{description?.overview}</p>
-                        <p><strong>{rating?.certification}</strong></p>
-                        {poster && (
-                            <img
-                                className={classes.poster}
-                                alt={`Movie poster for ${title?.name}`}
-                                src={poster.src}
-                            />
-                        )}
-                        {backdrop && (
-                            <img
-                                className={classes.poster}
-                                alt={`Movie backdrop for ${title?.name}`}
-                                src={backdrop.src}
-                            />
-                        )}
-                        {media && media.src}
-                        <pre>{JSON.stringify(item.subtitles, null, 2)}</pre>
-                        <pre>{JSON.stringify(item.preview, null, 2)}</pre>
-                    </div>
-                )
-            })}
+                    return (
+                        <div key={item.ids.uuid} className={classes.movie}>
+                            <h1>{title?.name}</h1>
+                            <p><strong>{description?.tagline}</strong></p>
+                            <p>{description?.overview}</p>
+                            <p><strong>{rating?.certification}</strong></p>
+                            {poster && (
+                                <img
+                                    className={classes.poster}
+                                    alt={`Movie poster for ${title?.name}`}
+                                    src={poster.src}
+                                />
+                            )}
+                            {backdrop && (
+                                <img
+                                    className={classes.poster}
+                                    alt={`Movie backdrop for ${title?.name}`}
+                                    src={backdrop.src}
+                                />
+                            )}
+                            {media && (
+                                <p><a href={media.src}>{media.src}</a></p>
+                            )}
+                            {item.preview && (
+                                <p><a href={item.preview}>{item.preview}</a></p>
+                            )}
+                        </div>
+                    )
+                })}
         </div>
     );
 }
diff --git a/src/api/models/LocalizedData.ts b/src/api/models/LocalizedData.ts
deleted file mode 100644
index 71b27d2..0000000
--- a/src/api/models/LocalizedData.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-export interface LocalizedData {
-    region: string | null,
-    languages?: string[],
-    kind?: string,
-}
diff --git a/src/api/models/Rating.ts b/src/api/models/Rating.ts
index e4b85e7..898cfa1 100644
--- a/src/api/models/Rating.ts
+++ b/src/api/models/Rating.ts
@@ -1,4 +1,4 @@
-import {LocalizedData} from "./LocalizedData";
+import {LocalizedData} from "../../locale/LocalizedData";
 
 export interface Rating extends LocalizedData {
     region: string | null,
diff --git a/src/api/models/Title.ts b/src/api/models/Title.ts
index 5c60c51..0b0fb82 100644
--- a/src/api/models/Title.ts
+++ b/src/api/models/Title.ts
@@ -1,3 +1,7 @@
+import {Locale} from "../../locale/Locale";
+import {LocalePriority} from "../../locale/LocalePriority";
+import {selectLocaleVersion} from "../../locale/selectLocaleData";
+import {selectRegionalVersion} from "../../locale/selectRegionalData";
 import {Cast} from "./Cast";
 import {Genre} from "./Genre";
 import {Image} from "./Image";
@@ -28,3 +32,12 @@ export interface Title {
     createdAt: string,
     updatedAt: string
 }
+
+export const getLocalizedName = (title: Title, locale: Locale): TitleName | null =>
+    selectLocaleVersion(locale, LocalePriority.REGION, title.titles)
+
+export const getLocalizedDescription = (title: Title, locale: Locale): TitleDescription | null =>
+    selectLocaleVersion(locale, LocalePriority.LOCALE, title.descriptions)
+
+export const getLocalizedRating = (title: Title, locale: Locale): Rating | null =>
+    selectRegionalVersion(locale, title.ratings)
diff --git a/src/api/models/TitleDescription.ts b/src/api/models/TitleDescription.ts
index cc2b03a..a9c5665 100644
--- a/src/api/models/TitleDescription.ts
+++ b/src/api/models/TitleDescription.ts
@@ -1,4 +1,4 @@
-import {LocalizedData} from "./LocalizedData";
+import {LocalizedData} from "../../locale/LocalizedData";
 
 export interface TitleDescription extends LocalizedData {
     overview: string,
diff --git a/src/api/models/TitleName.ts b/src/api/models/TitleName.ts
index b21be8e..9299eaf 100644
--- a/src/api/models/TitleName.ts
+++ b/src/api/models/TitleName.ts
@@ -1,4 +1,4 @@
-import {LocalizedData} from "./LocalizedData";
+import {LocalizedData} from "../../locale/LocalizedData";
 
 export interface TitleName extends LocalizedData {
     name: string,
diff --git a/src/locale/Locale.ts b/src/locale/Locale.ts
new file mode 100644
index 0000000..cd3d7ca
--- /dev/null
+++ b/src/locale/Locale.ts
@@ -0,0 +1,4 @@
+export interface Locale {
+    language: string,
+    region: string
+}
diff --git a/src/locale/LocalePriority.ts b/src/locale/LocalePriority.ts
new file mode 100644
index 0000000..bf62cc6
--- /dev/null
+++ b/src/locale/LocalePriority.ts
@@ -0,0 +1,4 @@
+export enum LocalePriority {
+    REGION,
+    LOCALE
+}
diff --git a/src/locale/LocalizedData.ts b/src/locale/LocalizedData.ts
new file mode 100644
index 0000000..8451a72
--- /dev/null
+++ b/src/locale/LocalizedData.ts
@@ -0,0 +1,6 @@
+import {RegionalData} from "./RegionalData";
+
+export interface LocalizedData extends RegionalData {
+    languages: string[],
+    kind: string,
+}
diff --git a/src/locale/RegionalData.ts b/src/locale/RegionalData.ts
new file mode 100644
index 0000000..32aa616
--- /dev/null
+++ b/src/locale/RegionalData.ts
@@ -0,0 +1,3 @@
+export interface RegionalData {
+    region: string | null,
+}
diff --git a/src/locale/selectLocaleData.ts b/src/locale/selectLocaleData.ts
index f2d49a4..37e61fc 100644
--- a/src/locale/selectLocaleData.ts
+++ b/src/locale/selectLocaleData.ts
@@ -1,15 +1,6 @@
-import {LocalizedData} from "../api/models/LocalizedData";
-
-export interface Locale {
-    language: string,
-    region: string
-}
-
-export enum LocalePriority {
-    REGION_ONLY,
-    REGION_BEFORE_LOCALE,
-    LOCALE_BEFORE_REGION
-}
+import {Locale} from "./Locale";
+import {LocalePriority} from "./LocalePriority";
+import {LocalizedData} from "./LocalizedData";
 
 function filterVersions<T extends LocalizedData>(
     locale: Locale,
@@ -17,20 +8,20 @@ function filterVersions<T extends LocalizedData>(
     data: T[]
 ): T | undefined {
     switch (method) {
-        case LocalePriority.REGION_ONLY:
-            return data.find((el) => {
-                return (el.region === locale.region);
-            });
-        case LocalePriority.REGION_BEFORE_LOCALE:
+        case LocalePriority.REGION:
             return data.sort((a, b) =>
                 +(b.languages?.includes(locale.language) || false) -
                 +(a.languages?.includes(locale.language) || false)
-            ).find((el) => el.region === locale.region);
-        case LocalePriority.LOCALE_BEFORE_REGION:
+            ).find((el) =>
+                el.region === locale.region
+                || el.region === null);
+        case LocalePriority.LOCALE:
             return data.sort((a, b) =>
                 +(b.region === locale.region) -
                 +(a.region === locale.region)
-            ).find((el) => el.languages?.includes(locale.language));
+            ).find((el) =>
+                el.languages?.includes(locale.language)
+                || el.languages.length === 0);
 
     }
 }
diff --git a/src/locale/selectRegionalData.ts b/src/locale/selectRegionalData.ts
new file mode 100644
index 0000000..a4a48ac
--- /dev/null
+++ b/src/locale/selectRegionalData.ts
@@ -0,0 +1,11 @@
+import {Locale} from "./Locale";
+import {RegionalData} from "./RegionalData";
+
+export function selectRegionalVersion<T extends RegionalData>(
+    locale: Locale,
+    data: T[]
+): T | null {
+    return data.find((el) => {
+        return (el.region === locale.region);
+    }) || null;
+}
-- 
GitLab