diff --git a/src/common/CONSTANTS.js b/src/common/CONSTANTS.js index b9b30d312..104d24a44 100644 --- a/src/common/CONSTANTS.js +++ b/src/common/CONSTANTS.js @@ -2,6 +2,8 @@ const CHROMECAST_RECEIVER_APP_ID = '1634F54B'; const DEFAULT_STREAMING_SERVER_URL = 'http://127.0.0.1:11470/'; +const DEFAULT_SUBTITLES_LANGUAGE = 'eng'; +const LOCAL_SUBTITLES_LANGUAGE = 'local'; const SUBTITLES_SIZES = [75, 100, 125, 150, 175, 200, 250]; const SUBTITLES_FONTS = ['PlusJakartaSans', 'Arial', 'Halvetica', 'Times New Roman', 'Verdana', 'Courier', 'Lucida Console', 'sans-serif', 'serif', 'monospace']; const SEEK_TIME_DURATIONS = [3000, 5000, 10000, 15000, 20000, 30000]; @@ -121,6 +123,8 @@ const PROTOCOL = 'stremio:'; module.exports = { CHROMECAST_RECEIVER_APP_ID, DEFAULT_STREAMING_SERVER_URL, + DEFAULT_SUBTITLES_LANGUAGE, + LOCAL_SUBTITLES_LANGUAGE, SUBTITLES_SIZES, SUBTITLES_FONTS, SEEK_TIME_DURATIONS, diff --git a/src/common/comparatorWithPriorities.js b/src/common/comparatorWithPriorities.js deleted file mode 100644 index baa12b843..000000000 --- a/src/common/comparatorWithPriorities.js +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (C) 2017-2023 Smart code 203358507 - -const comparatorWithPriorities = (priorities) => { - return (a, b) => { - if (isNaN(priorities[a]) && isNaN(priorities[b])) { - return a.localeCompare(b); - } else if (isNaN(priorities[a])) { - if (priorities[b] === Number.NEGATIVE_INFINITY) { - return -1; - } else { - return 1; - } - } else if (isNaN(priorities[b])) { - if (priorities[a] === Number.NEGATIVE_INFINITY) { - return 1; - } else { - return -1; - } - } else { - return priorities[b] - priorities[a]; - } - }; -}; - -module.exports = comparatorWithPriorities; diff --git a/src/common/index.js b/src/common/index.js index 1b248c1ff..7b27517f6 100644 --- a/src/common/index.js +++ b/src/common/index.js @@ -5,7 +5,6 @@ const { PlatformProvider, usePlatform } = require('./Platform'); const { ToastProvider, useToast } = require('./Toast'); const { TooltipProvider, Tooltip } = require('./Tooltips'); const { ShortcutsProvider, useShortcuts, onShortcut } = require('./Shortcuts'); -const comparatorWithPriorities = require('./comparatorWithPriorities'); const CONSTANTS = require('./CONSTANTS'); const { withCoreSuspender, useCoreSuspender } = require('./CoreSuspender'); const getVisibleChildrenRange = require('./getVisibleChildrenRange'); @@ -43,7 +42,6 @@ module.exports = { useToast, TooltipProvider, Tooltip, - comparatorWithPriorities, CONSTANTS, withCoreSuspender, useCoreSuspender, diff --git a/src/routes/Player/Player.js b/src/routes/Player/Player.js index 98402ed1f..33d2650b9 100644 --- a/src/routes/Player/Player.js +++ b/src/routes/Player/Player.js @@ -1022,6 +1022,8 @@ const Player = ({ urlParams, queryParams }) => { subtitlesMenuOpen ? tracks.map((track) => ({ ...track, lang: languages.toCode(track.lang), })); +const sortByValues = (items, values) => items.sort((a, b) => { + const left = values.indexOf(a); + const right = values.indexOf(b); + if (left === -1 && right === -1) return 0; + if (left === -1) return 1; + if (right === -1) return -1; + return left - right; +}); + const SubtitlesMenu = React.memo((props) => { const subtitlesTracks = React.useMemo(() => { return normalizeTracksLang(Array.isArray(props.subtitlesTracks) ? props.subtitlesTracks : []); @@ -39,16 +44,12 @@ const SubtitlesMenu = React.memo((props) => { }, [subtitlesTracks, extraSubtitlesTracks]); const subtitlesLanguages = React.useMemo(() => { - return allSubtitles - .reduce((subtitlesLanguages, { lang }) => { - if (!subtitlesLanguages.includes(lang)) { - subtitlesLanguages.push(lang); - } - - return subtitlesLanguages; - }, []) - .sort(comparatorWithPriorities(LANGUAGE_PRIORITIES)); - }, [allSubtitles]); + const userLanguage = languages.toCode(props.subtitlesLanguage) ?? DEFAULT_SUBTITLES_LANGUAGE; + const interfaceLanguage = languages.toCode(props.interfaceLanguage) ?? DEFAULT_SUBTITLES_LANGUAGE; + const priorities = [LOCAL_SUBTITLES_LANGUAGE, userLanguage, interfaceLanguage]; + const langs = Object.keys(Object.groupBy(allSubtitles, ({ lang }) => lang)).sort((a, b) => a.localeCompare(b)); + return sortByValues(langs, priorities); + }, [allSubtitles, props.subtitlesLanguage, props.interfaceLanguage]); const selectedSubtitlesLanguage = React.useMemo(() => { return typeof props.selectedSubtitlesTrackId === 'string' ? @@ -74,18 +75,16 @@ const SubtitlesMenu = React.memo((props) => { null; }, [subtitlesTracks, extraSubtitlesTracks, props.selectedSubtitlesTrackId, props.selectedExtraSubtitlesTrackId]); const subtitlesTracksForLanguage = React.useMemo(() => { - return allSubtitles - .filter(({ lang }) => lang === selectedSubtitlesLanguage) - .sort((t1, t2) => comparatorWithPriorities(ORIGIN_PRIORITIES)(t1.origin, t2.origin)); + const tracks = allSubtitles.filter(({ lang }) => lang === selectedSubtitlesLanguage); + return sortByValues(tracks, ORIGIN_PRIORITIES); }, [allSubtitles, selectedSubtitlesLanguage]); const onMouseDown = React.useCallback((event) => { event.nativeEvent.subtitlesMenuClosePrevented = true; }, []); const subtitlesLanguageOnClick = React.useCallback((event) => { - const track = allSubtitles - .filter(({ lang }) => lang === event.currentTarget.dataset.lang) - .sort((t1, t2) => comparatorWithPriorities(ORIGIN_PRIORITIES)(t1.origin, t2.origin)) - .shift(); + const tracks = allSubtitles.filter(({ lang }) => lang === event.currentTarget.dataset.lang); + const track = sortByValues(tracks, ORIGIN_PRIORITIES).shift(); + if (!track) { if (typeof props.onSubtitlesTrackSelected === 'function') { props.onSubtitlesTrackSelected(null); @@ -262,6 +261,8 @@ SubtitlesMenu.displayName = 'MainNavBars'; SubtitlesMenu.propTypes = { className: PropTypes.string, + subtitlesLanguage: PropTypes.string, + interfaceLanguage: PropTypes.string, subtitlesTracks: PropTypes.arrayOf(PropTypes.shape({ id: PropTypes.string.isRequired, lang: PropTypes.string.isRequired,