From 0a56a2f6d48b13bd414b5e4a5327f41b7a0a11f8 Mon Sep 17 00:00:00 2001 From: schroda <50052685+schroda@users.noreply.github.com> Date: Fri, 21 Apr 2023 00:27:42 +0200 Subject: [PATCH] Extensions cleanup (#257) * [Cleanup] Add enums and types * Extract "default languages" from ISOLanguages The "default languages" will also be translated depending on which language the user selected --- src/components/SourceCard.tsx | 4 +- src/components/navbar/action/LangSelect.tsx | 4 +- src/i18n/locale/en.json | 8 +++- src/screens/Extensions.tsx | 49 +++++++++++++-------- src/screens/SearchAll.tsx | 5 ++- src/screens/Sources.tsx | 5 ++- src/screens/util/Extensions.ts | 44 ++++++++++++++++++ src/util/language.tsx | 24 +++++----- 8 files changed, 101 insertions(+), 42 deletions(-) create mode 100644 src/screens/util/Extensions.ts diff --git a/src/components/SourceCard.tsx b/src/components/SourceCard.tsx index b690cd4a..5c689d17 100644 --- a/src/components/SourceCard.tsx +++ b/src/components/SourceCard.tsx @@ -15,9 +15,9 @@ import { Box, styled } from '@mui/system'; import React from 'react'; import { useTranslation } from 'react-i18next'; import { Link, useHistory } from 'react-router-dom'; -import { langCodeToName } from 'util/language'; import useLocalStorage from 'util/useLocalStorage'; import { ISource } from 'typings'; +import { translateExtensionLanguage } from 'screens/util/Extensions'; const MobileWidthButtons = styled('div')(({ theme }) => ({ display: 'flex', @@ -99,7 +99,7 @@ const SourceCard: React.FC = (props: IProps) => { {id !== '0' && ( - {langCodeToName(lang)} + {translateExtensionLanguage(lang)} {isNsfw && ( {' 18+'} diff --git a/src/components/navbar/action/LangSelect.tsx b/src/components/navbar/action/LangSelect.tsx index 7b5b8176..ed4963fd 100644 --- a/src/components/navbar/action/LangSelect.tsx +++ b/src/components/navbar/action/LangSelect.tsx @@ -16,9 +16,9 @@ import IconButton from '@mui/material/IconButton'; import FilterListIcon from '@mui/icons-material/FilterList'; import { List, ListItemSecondaryAction, ListItemText } from '@mui/material'; import ListItem from '@mui/material/ListItem'; -import { langCodeToName } from 'util/language'; import cloneObject from 'util/cloneObject'; import { useTranslation } from 'react-i18next'; +import { translateExtensionLanguage } from 'screens/util/Extensions'; function removeAll(firstList: any[], secondList: any[]) { secondList.forEach((item) => { @@ -93,7 +93,7 @@ export default function LangSelect(props: IProps) { {allLangs.map((lang) => ( - + { if (sortedExtenions[extension.lang] === undefined) { sortedExtenions[extension.lang] = []; @@ -45,9 +54,9 @@ function groupExtensions(extensions: IExtension[]) { } if (extension.installed) { if (extension.hasUpdate) { - sortedExtenions['updates pending'].push(extension); + sortedExtenions[ExtensionState.UPDATE_PENDING].push(extension); } else { - sortedExtenions.installed.push(extension); + sortedExtenions[ExtensionState.INSTALLED].push(extension); } } else { sortedExtenions[extension.lang].push(extension); @@ -55,15 +64,17 @@ function groupExtensions(extensions: IExtension[]) { }); allLangs.sort(langSortCmp); - const result: [string, IExtension[]][] = [ - ['updates pending', sortedExtenions['updates pending']], - ['installed', sortedExtenions.installed], - ['all', sortedExtenions.all], + const result: GroupedExtensionsResult = [ + [ExtensionState.UPDATE_PENDING, sortedExtenions[ExtensionState.UPDATE_PENDING]], + [ExtensionState.INSTALLED, sortedExtenions[ExtensionState.INSTALLED]], + [DefaultLanguage.ALL, sortedExtenions[DefaultLanguage.ALL]], + [DefaultLanguage.OTHER, sortedExtenions[DefaultLanguage.OTHER]], + [DefaultLanguage.LOCAL_SOURCE, sortedExtenions[DefaultLanguage.LOCAL_SOURCE]], ]; - const langExt: [string, IExtension[]][] = allLangs.map((lang) => [lang, sortedExtenions[lang]]); + const langExt: GroupedExtensionsResult = allLangs.map((lang) => [lang, sortedExtenions[lang]]); - return result.concat(langExt); + return (result as GroupedExtensionsResult).concat(langExt); } export default function MangaExtensions() { @@ -106,7 +117,7 @@ export default function MangaExtensions() { () => groupExtensions(filteredExtensions) .filter((group) => group[EXTENSIONS].length > 0) - .filter((group) => ['installed', 'updates pending', 'all', ...shownLangs].includes(group[LANGUAGE])), + .filter((group) => isExtensionStateOrLanguage(group[LANGUAGE]) || shownLangs.includes(group[LANGUAGE])), [shownLangs, filteredExtensions], ); @@ -196,7 +207,7 @@ export default function MangaExtensions() { fontWeight: 'bold', }} > - {langCodeToName(item)} + {translateExtensionLanguage(item)} ); } diff --git a/src/screens/SearchAll.tsx b/src/screens/SearchAll.tsx index 4b9264a9..af59da13 100644 --- a/src/screens/SearchAll.tsx +++ b/src/screens/SearchAll.tsx @@ -16,10 +16,11 @@ import React, { useContext, useEffect, useState } from 'react'; import { Link } from 'react-router-dom'; import { StringParam, useQueryParam } from 'use-query-params'; import client from 'util/client'; -import { langCodeToName, langSortCmp, sourceDefualtLangs, sourceForcedDefaultLangs } from 'util/language'; +import { langSortCmp, sourceDefualtLangs, sourceForcedDefaultLangs } from 'util/language'; import useLocalStorage from 'util/useLocalStorage'; import { ISource } from 'typings'; import { useTranslation } from 'react-i18next'; +import { translateExtensionLanguage } from 'screens/util/Extensions'; function sourceToLangList(sources: ISource[]) { const result: string[] = []; @@ -202,7 +203,7 @@ const SearchAll: React.FC = () => { sx={{ p: 3 }} > {displayName} - {langCodeToName(lang)} + {translateExtensionLanguage(lang)}

- {langCodeToName(lang)} + {translateExtensionLanguage(lang)}

{(list as ISource[]) .filter((source) => showNsfw || !source.isNsfw) diff --git a/src/screens/util/Extensions.ts b/src/screens/util/Extensions.ts new file mode 100644 index 00000000..dd15a699 --- /dev/null +++ b/src/screens/util/Extensions.ts @@ -0,0 +1,44 @@ +import { IExtension, TranslationKey } from 'typings'; +import { DefaultLanguage, langCodeToName } from 'util/language'; +import { t } from 'i18next'; + +export enum ExtensionState { + INSTALLED = 'INSTALLED', + UPDATE_PENDING = 'UPDATE_PENDING', +} + +export type GroupedExtensionsResult = [KEY, IExtension[]][]; + +export type GroupedByExtensionState = { + [state in ExtensionState]: IExtension[]; +}; + +export type GroupedByLanguage = { + [language in DefaultLanguage]: IExtension[]; +} & { + [language: string]: IExtension[]; +}; + +export type GroupedExtensions = GroupedByExtensionState & GroupedByLanguage; + +export const extensionLanguageToTranslationKey: { [state in ExtensionState | DefaultLanguage]: TranslationKey } = { + [ExtensionState.INSTALLED]: 'extension.state.label.installed', + [ExtensionState.UPDATE_PENDING]: 'extension.state.label.update_pending', + [DefaultLanguage.ALL]: 'extension.language.all', + [DefaultLanguage.OTHER]: 'extension.language.other', + [DefaultLanguage.LOCAL_SOURCE]: 'source.local_source.title', +}; + +export const isExtensionStateOrLanguage = (languageCode: string): boolean => + [ + ExtensionState.INSTALLED, + ExtensionState.UPDATE_PENDING, + DefaultLanguage.ALL, + DefaultLanguage.OTHER, + DefaultLanguage.LOCAL_SOURCE, + ].includes(languageCode as ExtensionState | DefaultLanguage); + +export const translateExtensionLanguage = (languageCode: string): string => + isExtensionStateOrLanguage(languageCode) + ? (t(extensionLanguageToTranslationKey[languageCode as ExtensionState | DefaultLanguage]) as string) + : langCodeToName(languageCode); diff --git a/src/util/language.tsx b/src/util/language.tsx index 075c81ee..85ed7bc3 100644 --- a/src/util/language.tsx +++ b/src/util/language.tsx @@ -6,15 +6,13 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ import { t } from 'i18next'; +export enum DefaultLanguage { + ALL = 'all', + OTHER = 'other', + LOCAL_SOURCE = 'localsourcelang', +} + export const ISOLanguages = [ - { code: 'all', name: 'All', nativeName: 'All' }, - { code: 'installed', name: 'Installed', nativeName: 'Installed' }, - { code: 'updates pending', name: 'Updates pending', nativeName: 'Updates pending' }, - - { code: 'other', name: 'other langs?', nativeName: 'Other' }, - - { code: 'localsourcelang', name: 'Local source', nativeName: 'Local source' }, - // full list: https://github.com/meikidd/iso-639-1/blob/master/src/data.js { code: 'en', name: 'English', nativeName: 'English' }, { code: 'ca', name: 'Catalan; Valencian', nativeName: 'CatalĂ ' }, @@ -97,15 +95,15 @@ function defaultNativeLang() { } export function extensionDefaultLangs() { - return [defaultNativeLang(), 'all']; + return [defaultNativeLang(), DefaultLanguage.ALL]; } export function sourceDefualtLangs() { - return [defaultNativeLang(), 'localsourcelang']; + return [defaultNativeLang(), DefaultLanguage.LOCAL_SOURCE]; } export function sourceForcedDefaultLangs(): string[] { - return ['localsourcelang']; + return [DefaultLanguage.LOCAL_SOURCE]; } export const langSortCmp = (a: string, b: string) => { @@ -115,8 +113,8 @@ export const langSortCmp = (a: string, b: string) => { if (a === 'en') return -1; if (b === 'en') return 1; - if (a === 'localSourceLang') return 1; - if (b === 'localSourceLang') return -1; + if (a === DefaultLanguage.LOCAL_SOURCE) return 1; + if (b === DefaultLanguage.LOCAL_SOURCE) return -1; return aLang > bLang ? 1 : -1; };