diff --git a/src/routes/Settings/SectionsList/SectionsList.js b/src/routes/Settings/SectionsList/SectionsList.js new file mode 100644 index 000000000..201ca4138 --- /dev/null +++ b/src/routes/Settings/SectionsList/SectionsList.js @@ -0,0 +1,103 @@ +const React = require('react'); +const { Button, Dropdown, Checkbox, ColorInput } = require('stremio/common'); +const Icon = require('stremio-icons/dom/Icon'); +const classnames = require('classnames'); +const styles = require('../styles'); + +const SectionsList = React.forwardRef(({className, sections, preferences, onPreferenceChanged, onScroll }, ref) => { + const scrollContainerRef = ref; + const toggleCheckbox = (id) => { + onPreferenceChanged(id, !preferences[id]); + }; + + const colorChanged = (id, color) => { + onPreferenceChanged(id, color); + }; + + const updateDropdown = (event) => { + var data = event.currentTarget.dataset; + onPreferenceChanged(data.name, data.value); + }; + + return ( +
+ {sections.map((section) => +
+
{section.id}
+ {(section.inputs || []) + .map((input) => { + if (input.type === 'user') { + return ( +
+ { + !preferences[input.id] + ? +
+ : +
+ } +
{!preferences[input.id] ? 'Anonymous user' : preferences[input.id].email}
+
+ ); + } else if (input.type === 'select') { + return ( +
+ {input.header ?
{input.header}
: null} + +
+ ); + } else if (input.type === 'link') { + return ( +
+ {input.header ?
{input.header}
: null} + +
+ ); + } else if (input.type === 'button') { + return ( +
+ {input.header ?
{input.header}
: null} + +
+ ); + } else if (input.type === 'checkbox') { + return ( +
+ {input.header ?
{input.header}
: null} + +
{input.label}
+
+
+ ); + } else if (input.type === 'static-text') { + return ( +
+ {input.header ?
{input.header}
: null} +
+ {input.icon ? : null} +
{input.label}
+
+
+ ); + } else if (input.type === 'color') { + return ( +
+ {input.header ?
{input.header}
: null} + + {/* */} +
+ ); + } + })} +
+ )} +
+ ); +}); + +module.exports = SectionsList; \ No newline at end of file diff --git a/src/routes/Settings/SectionsList/index.js b/src/routes/Settings/SectionsList/index.js new file mode 100644 index 000000000..ff7a9b4a0 --- /dev/null +++ b/src/routes/Settings/SectionsList/index.js @@ -0,0 +1,3 @@ +const SectionsList = require('./SectionsList'); + +module.exports = SectionsList; \ No newline at end of file diff --git a/src/routes/Settings/SectionsSelector/SectionsSelector.js b/src/routes/Settings/SectionsSelector/SectionsSelector.js new file mode 100644 index 000000000..2c1f44ced --- /dev/null +++ b/src/routes/Settings/SectionsSelector/SectionsSelector.js @@ -0,0 +1,18 @@ +const React = require('react'); +const { Button } = require('stremio/common'); +const classnames = require('classnames'); +const styles = require('../styles'); + +const SectionsSelector = ({ className, sections, selectedSectionId, onSelectedSection }) => { + return ( +
+ {sections.map((section) => + + )} +
+ ); +}; + +module.exports = SectionsSelector; \ No newline at end of file diff --git a/src/routes/Settings/SectionsSelector/index.js b/src/routes/Settings/SectionsSelector/index.js new file mode 100644 index 000000000..d873092a7 --- /dev/null +++ b/src/routes/Settings/SectionsSelector/index.js @@ -0,0 +1,3 @@ +const SectionsSelector = require('./SectionsSelector'); + +module.exports = SectionsSelector; diff --git a/src/routes/Settings/Settings.js b/src/routes/Settings/Settings.js index d5dd806a7..a892fac6b 100644 --- a/src/routes/Settings/Settings.js +++ b/src/routes/Settings/Settings.js @@ -1,128 +1,76 @@ const React = require('react'); -const classnames = require('classnames'); -const { Button, Dropdown, Checkbox, NavBar, ColorInput } = require('stremio/common'); -const Icon = require('stremio-icons/dom/Icon'); +const { NavBar } = require('stremio/common'); const styles = require('./styles'); +const SectionsSelector = require('./SectionsSelector'); +const SectionsList = require('./SectionsList'); +const { settingsSections, SECTIONS_ORDER } = require('./constants'); -const settingsData = [ - { section: 'General', label: 'Username', type: 'user', avatar: '', email: '' }, - { section: 'General', label: 'LOG OUT', type: 'button' }, - { section: 'General', label: 'Change password', type: 'link', href: '' }, - { section: 'General', label: 'Import options', type: 'static-text' }, - { section: 'General', label: 'Import from Facebook', type: 'link', href: '' }, - { section: 'General', label: 'Export user data', type: 'link', href: '' }, - { section: 'General', label: 'Subscribe to calendar', type: 'link', href: '' }, - { section: 'General', label: 'Contact support', type: 'link', href: 'https://stremio.zendesk.com/' }, - { section: 'General', label: 'Request account deletion', type: 'link', href: 'https://docs.google.com/forms/d/e/1FAIpQLScubrlTpDMIPUUBlhZ5lwcXl3HxzKfunIMCX5Jnp-cDyglWjQ/viewform?usp=sf_link' }, - { section: 'General', header: 'Trakt Scrobbling', label: 'AUTHENTICATE', type: 'button', icon: 'ic_trackt' }, - { section: 'General', header: 'UI Language', label: 'UI Language', type: 'select', options: ['Български език', 'English', 'Deutsch', 'Español', 'Italiano'], value: 'English' }, - { section: 'Player', label: 'ADD-ONS', type: 'button', icon: 'ic_addons' }, - { section: 'Player', header: 'Default Subtitles Language', label: 'Default Subtitles Language', type: 'select', options: ['English', 'Nederlands', 'Avesta', 'Български език', 'Deutsch', 'Español', 'Italiano'], value: 'English' }, - { section: 'Player', header: 'Default Subtitles Size', label: 'Default Subtitles Size', type: 'select', options: ['72%', '80%', '100%', '120%', '140%', '160%', '180%'], value: '100%' }, - { section: 'Player', header: 'Subtitles Background', label: 'Subtitles background', type: 'select', options: ['None', 'Solid', 'Transparent'], value: 'None' }, - { section: 'Player', header: 'Subtitles color', label: 'Subtitles color', type: 'color', color: '#FFFFFF' }, - { section: 'Player', header: 'Subtitles outline color', label: 'Subtitles outline color', type: 'color', color: '#000000' }, - { section: 'Player', label: 'Auto-play next episode', type: 'checkbox', value: true }, - { section: 'Player', label: 'Pause playback when minimized', type: 'checkbox', value: false }, - { section: 'Player', label: 'Hardware-accelerated decoding', type: 'checkbox', value: true }, - { section: 'Player', label: 'Launch player in a separate window (advanced)', type: 'checkbox', value: true }, - { section: 'Streaming', header: 'Caching', label: 'Caching', type: 'select', options: ['No Caching', '2GB', '5GB', '10GB'], value: '2GB' }, - { section: 'Streaming', header: 'Torrent Profile', label: 'Torrent Profile', type: 'select', options: ['Default', 'Soft', 'Fast'], value: 'Default' }, - { section: 'Streaming', header: 'Streaming server URL: http://127.0.0.1:11470', label: 'Streaming server is available.', type: 'static-text', icon: 'ic_check' } -]; - -const SECTIONS_ORDER = { - 'General': 1, - 'Player': 2, - 'Streaming': 3 +const settingsValues = { + "user": null, + "ui_language": "eng", + "default_subtitles_language": "", + "default_subtitles_size": "100%", + "subtitles_background": "", + "subtitles_color": "#ffffff", + "subtitles_outline_color": "#000", + "auto-play_next_episode": true, + "pause_playback_when_minimized": false, + "hardware-accelerated_decoding": true, + "launch_player_in_a_separate_window_(advanced)": true, + "caching": "2048", + "torrent_profile": "profile-default", + "streaming_server_is_available.": true, }; const Settings = () => { - const [selectedSectionId, setSelectedSectionId] = React.useState(null); - const [sections, setSections] = React.useState([]); - const [inputs, setInputs] = React.useState([]); + const sections = Object.keys(settingsSections) + .sort(function(a, b) { + const valueA = SECTIONS_ORDER[a]; + const valueB = SECTIONS_ORDER[b]; + if (!isNaN(valueA) && !isNaN(valueB)) return valueA - valueB; + if (!isNaN(valueA)) return -1; + if (!isNaN(valueB)) return 1; + return a - b; + }) + .map((section) => ({ + id: section, + inputs: settingsSections[section].inputs, + ref: React.createRef() + })); + const [selectedSectionId, setSelectedSectionId] = React.useState(sections[0].id); + const [preferences, setPreferences] = React.useState(settingsValues); const scrollContainerRef = React.useRef(null); - React.useEffect(() => { - const theSections = settingsData.map(({ section }) => section) - .filter((section, index, sections) => sections.indexOf(section) === index) - .sort(function(a, b) { - const valueA = SECTIONS_ORDER[a]; - const valueB = SECTIONS_ORDER[b]; - if (!isNaN(valueA) && !isNaN(valueB)) return valueA - valueB; - if (!isNaN(valueA)) return -1; - if (!isNaN(valueB)) return 1; - return a - b; - }) - .map((section) => ({ - id: section, - ref: React.createRef() - })); - setSections(theSections); - - if (theSections.length > 0 && (selectedSectionId === null || !theSections.find(({ id }) => id === selectedSectionId))) { - setSelectedSectionId(theSections[0].id); - } - - setInputs(settingsData.map((setting) => ({ - ...setting, - id: setting.label, - ref: React.createRef(), - active: !!(inputs.find(({ id }) => id === setting.label) || {}).active - }))); - }, []); - ///////////////// - const toggleCheckbox = (id) => { - setInputs(inputs.map((input) => ({ - ...input, - value: id === input.id ? !input.value : input.value - }))); - }; - - const colorChanged = (id, color) => { - setInputs(inputs.map((input) => ({ - ...input, - value: id === input.id ? color : input.value - }))); - }; - - const updateDropdown = (event) => { - var data = event.currentTarget.dataset; - setInputs(inputs.map((input) => ({ - ...input, - value: data.name === input.id ? data.value : input.value, - }))); - }; + const updatePreference = (option, value) => { + const newPrefs = { ...preferences }; + newPrefs[option] = value; + setPreferences(newPrefs); + } const changeSection = (event) => { const currentSectionId = event.currentTarget.dataset.section; const section = sections.find((section) => section.id === currentSectionId); - setSelectedSectionId(currentSectionId); + //setSelectedSectionId(currentSectionId); scrollContainerRef.current.scrollTo({ top: section.ref.current.offsetTop, behavior: 'smooth' }); }; - - const onScroll = (event) => { - const current = event.currentTarget; - if (sections.length <= 0) { - return; - } - - if (current.scrollTop + current.clientHeight === current.scrollHeight) { + const updateSection = React.useCallback((event) => { + const scrollContainer = event.currentTarget; + if (scrollContainer.scrollTop + scrollContainer.clientHeight === scrollContainer.scrollHeight) { setSelectedSectionId(sections[sections.length - 1].id); } else { for (let i = sections.length - 1;i >= 0;i--) { - if (sections[i].ref.current.offsetTop <= current.scrollTop) { + if (sections[i].ref.current.offsetTop <= scrollContainer.scrollTop) { setSelectedSectionId(sections[i].id); break; } } } - }; + }); return (
@@ -133,91 +81,8 @@ const Settings = () => { fullscreenButton={true} navMenu={true} />
-
- {sections.map((section) => - - )} -
-
- {sections.map((section) => -
-
{section.id}
- {inputs.filter((input) => input.section === section.id) - .map((input) => { - if (input.type === 'user') { - return ( -
- { - input.email.length === 0 - ? -
- : -
- } -
{input.email.length === 0 ? 'Anonymous user' : input.email}
-
- ); - } else if (input.type === 'select') { - return ( -
- {input.header ?
{input.header}
: null} - {/* TODO: provide proper data instead of mapping the options */} - ({ value: o, label: o }))} selected={[input.value]} name={input.id} key={input.id} className={styles['dropdown']} onSelect={updateDropdown} /> -
- ); - } else if (input.type === 'link') { - return ( -
- {input.header ?
{input.header}
: null} - -
- ); - } else if (input.type === 'button') { - return ( -
- {input.header ?
{input.header}
: null} - -
- ); - } else if (input.type === 'checkbox') { - return ( -
- {input.header ?
{input.header}
: null} - -
{input.label}
-
-
- ); - } else if (input.type === 'static-text') { - return ( -
- {input.header ?
{input.header}
: null} -
- {input.icon ? : null} -
{input.label}
-
-
- ); - } else if (input.type === 'color') { - return ( -
- {input.header ?
{input.header}
: null} - - {/* */} -
- ); - } - })} -
- )} -
+ +
);