From aac36eff1d15c7d7e587e311ee92d6c456b49030 Mon Sep 17 00:00:00 2001 From: Daniel Shleifman Date: Tue, 29 Jun 2021 20:34:27 +0300 Subject: [PATCH 01/13] settings dialog content separated from sidebar button --- web/src/components/Settings.jsx | 411 ++++++++++++++++---------------- 1 file changed, 207 insertions(+), 204 deletions(-) diff --git a/web/src/components/Settings.jsx b/web/src/components/Settings.jsx index 55d4c91..5a84228 100644 --- a/web/src/components/Settings.jsx +++ b/web/src/components/Settings.jsx @@ -13,26 +13,13 @@ import Button from '@material-ui/core/Button' import { FormControlLabel, InputLabel, Select, Switch } from '@material-ui/core' import { settingsHost, setTorrServerHost, getTorrServerHost } from 'utils/Hosts' import { useTranslation } from 'react-i18next' -import { ThemeProvider } from '@material-ui/core/styles' -import { lightTheme } from '../style/materialUISetup' - -export default function SettingsDialog() { +const SettingsDialog = ({ handleClose }) => { const { t } = useTranslation() - const [open, setOpen] = useState(false) + const [settings, setSets] = useState({}) const [show, setShow] = useState(false) const [tsHost, setTSHost] = useState(getTorrServerHost()) - - const handleClickOpen = () => setOpen(true) - const handleClose = () => setOpen(false) - const handleSave = () => { - setOpen(false) - const sets = JSON.parse(JSON.stringify(settings)) - sets.CacheSize *= 1024 * 1024 - axios.post(settingsHost(), { action: 'set', sets }) - } - useEffect(() => { axios .post(settingsHost(), { action: 'get' }) @@ -43,6 +30,12 @@ export default function SettingsDialog() { .catch(() => setShow(false)) }, [tsHost]) + const handleSave = () => { + handleClose() + const sets = JSON.parse(JSON.stringify(settings)) + sets.CacheSize *= 1024 * 1024 + axios.post(settingsHost(), { action: 'set', sets }) + } const onInputHost = ({ target: { value } }) => { const host = value.replace(/\/$/gi, '') setTorrServerHost(host) @@ -94,6 +87,204 @@ export default function SettingsDialog() { RemoveCacheOnDrop, } = settings + return ( + + {t('Settings')} + + + {show && ( + <> + +
+ +
+ } + label={t('PreloadBuffer')} + /> +
+ } + label={t('UseDisk')} + /> +
+ {t('UseDiskDesc')} +
+ + } + label={t('RemoveCacheOnDrop')} + /> +
+ {t('RemoveCacheOnDropDesc')} +
+ +
+ } + label={t('EnableIPv6')} + /> +
+ } + label={t('TCP')} + /> +
+ } + label={t('UTP')} + /> +
+ } + label={t('PEX')} + /> +
+ } + label={t('ForceEncrypt')} + /> +
+ +
+ +
+ } + label={t('DHT')} + /> +
+ +
+ +
+ } + label={t('Upload')} + /> +
+ +
+ +
+ } + label={t('UPNP')} + /> +
+ {t('RetrackersMode')} + +
+ + )} +
+ + + + + + +
+ ) +} + +export default function Settings() { + const { t } = useTranslation() + const [open, setOpen] = useState(false) + + const handleClickOpen = () => setOpen(true) + const handleClose = () => setOpen(false) + return (
@@ -103,195 +294,7 @@ export default function SettingsDialog() { - - - {t('Settings')} - - - {show && ( - <> - -
- -
- } - label={t('PreloadBuffer')} - /> -
- } - label={t('UseDisk')} - /> -
- {t('UseDiskDesc')} -
- - } - label={t('RemoveCacheOnDrop')} - /> -
- {t('RemoveCacheOnDropDesc')} -
- -
- } - label={t('EnableIPv6')} - /> -
- } - label={t('TCP')} - /> -
- } - label={t('UTP')} - /> -
- } - label={t('PEX')} - /> -
- } - label={t('ForceEncrypt')} - /> -
- -
- -
- } - label={t('DHT')} - /> -
- -
- -
- } - label={t('Upload')} - /> -
- -
- -
- } - label={t('UPNP')} - /> -
- {t('RetrackersMode')} - -
- - )} -
- - - - - - -
-
+ {open && }
) } From fd331f0728c9ad68aab74c6b248ea51982f797be Mon Sep 17 00:00:00 2001 From: Daniel Shleifman Date: Tue, 29 Jun 2021 20:41:16 +0300 Subject: [PATCH 02/13] refactor --- web/src/components/Add/index.jsx | 2 +- .../SettingsDialog.jsx} | 29 ++----------------- web/src/components/Settings/index.jsx | 29 +++++++++++++++++++ 3 files changed, 32 insertions(+), 28 deletions(-) rename web/src/components/{Settings.jsx => Settings/SettingsDialog.jsx} (91%) create mode 100644 web/src/components/Settings/index.jsx diff --git a/web/src/components/Add/index.jsx b/web/src/components/Add/index.jsx index 892d185..7c2d027 100644 --- a/web/src/components/Add/index.jsx +++ b/web/src/components/Add/index.jsx @@ -15,7 +15,7 @@ export default function AddDialogButton({ isOffline, isLoading }) { return (
- + diff --git a/web/src/components/Settings.jsx b/web/src/components/Settings/SettingsDialog.jsx similarity index 91% rename from web/src/components/Settings.jsx rename to web/src/components/Settings/SettingsDialog.jsx index 5a84228..fc7e8d4 100644 --- a/web/src/components/Settings.jsx +++ b/web/src/components/Settings/SettingsDialog.jsx @@ -1,9 +1,4 @@ import axios from 'axios' -import ListItem from '@material-ui/core/ListItem' -import ListItemIcon from '@material-ui/core/ListItemIcon' -import ListItemText from '@material-ui/core/ListItemText' -import { useEffect, useState } from 'react' -import SettingsIcon from '@material-ui/icons/Settings' import Dialog from '@material-ui/core/Dialog' import DialogTitle from '@material-ui/core/DialogTitle' import DialogContent from '@material-ui/core/DialogContent' @@ -12,9 +7,10 @@ import DialogActions from '@material-ui/core/DialogActions' import Button from '@material-ui/core/Button' import { FormControlLabel, InputLabel, Select, Switch } from '@material-ui/core' import { settingsHost, setTorrServerHost, getTorrServerHost } from 'utils/Hosts' +import { useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' -const SettingsDialog = ({ handleClose }) => { +export default function SettingsDialog({ handleClose }) { const { t } = useTranslation() const [settings, setSets] = useState({}) @@ -277,24 +273,3 @@ const SettingsDialog = ({ handleClose }) => { ) } - -export default function Settings() { - const { t } = useTranslation() - const [open, setOpen] = useState(false) - - const handleClickOpen = () => setOpen(true) - const handleClose = () => setOpen(false) - - return ( -
- - - - - - - - {open && } -
- ) -} diff --git a/web/src/components/Settings/index.jsx b/web/src/components/Settings/index.jsx new file mode 100644 index 0000000..be19058 --- /dev/null +++ b/web/src/components/Settings/index.jsx @@ -0,0 +1,29 @@ +import ListItem from '@material-ui/core/ListItem' +import ListItemIcon from '@material-ui/core/ListItemIcon' +import ListItemText from '@material-ui/core/ListItemText' +import { useState } from 'react' +import SettingsIcon from '@material-ui/icons/Settings' +import { useTranslation } from 'react-i18next' + +import SettingsDialog from './SettingsDialog' + +export default function SettingsDialogButton() { + const { t } = useTranslation() + const [isDialogOpen, setIsDialogOpen] = useState(false) + + const handleClickOpen = () => setIsDialogOpen(true) + const handleClose = () => setIsDialogOpen(false) + + return ( +
+ + + + + + + + {isDialogOpen && } +
+ ) +} From bc717647ea169bf3bd81fc1e65a02b0c81682b4e Mon Sep 17 00:00:00 2001 From: Daniel Shleifman Date: Thu, 1 Jul 2021 18:32:50 +0300 Subject: [PATCH 03/13] added new design to settings dialog --- web/package.json | 1 + web/src/components/Add/AddDialog.jsx | 12 +- web/src/components/Add/style.js | 23 - .../components/Settings/SettingsDialog.jsx | 548 +++++++++++++++++- web/src/icons/index.jsx | 110 ++++ web/src/style/DialogStyles.js | 24 + web/yarn.lock | 73 ++- 7 files changed, 753 insertions(+), 38 deletions(-) create mode 100644 web/src/style/DialogStyles.js diff --git a/web/package.json b/web/package.json index 67a8c88..83794af 100644 --- a/web/package.json +++ b/web/package.json @@ -23,6 +23,7 @@ "react-measure": "^2.5.2", "react-query": "^3.17.0", "react-scripts": "4.0.3", + "react-swipeable-views": "^0.14.0", "styled-components": "^5.3.0", "uuid": "^8.3.2" }, diff --git a/web/src/components/Add/AddDialog.jsx b/web/src/components/Add/AddDialog.jsx index 69431d9..fd67730 100644 --- a/web/src/components/Add/AddDialog.jsx +++ b/web/src/components/Add/AddDialog.jsx @@ -12,9 +12,10 @@ import usePreviousState from 'utils/usePreviousState' import { useQuery } from 'react-query' import { getTorrents } from 'utils/Utils' import parseTorrent from 'parse-torrent' +import { ButtonWrapper, Header } from 'style/DialogStyles' import { checkImageURL, getMoviePosters, chechTorrentSource, parseTorrentTitle } from './helpers' -import { ButtonWrapper, Content, Header } from './style' +import { Content } from './style' import RightSideComponent from './RightSideComponent' import LeftSideComponent from './LeftSideComponent' @@ -219,14 +220,7 @@ export default function AddDialog({ } return ( - +
{t(isEditMode ? 'EditTorrent' : 'AddNewTorrent')}
diff --git a/web/src/components/Add/style.js b/web/src/components/Add/style.js index d29809e..76fdbc1 100644 --- a/web/src/components/Add/style.js +++ b/web/src/components/Add/style.js @@ -1,19 +1,6 @@ import { Button } from '@material-ui/core' import styled, { css } from 'styled-components' -export const Header = styled.div` - ${({ theme: { primary } }) => css` - background: ${primary}; - color: rgba(0, 0, 0, 0.87); - font-size: 20px; - color: #fff; - font-weight: 600; - box-shadow: 0px 2px 4px -1px rgb(0 0 0 / 20%), 0px 4px 5px 0px rgb(0 0 0 / 14%), 0px 1px 10px 0px rgb(0 0 0 / 12%); - padding: 15px 24px; - position: relative; - `} -` - export const Content = styled.div` ${({ isEditMode, @@ -349,13 +336,3 @@ export const PosterLanguageSwitch = styled.div` } `} ` - -export const ButtonWrapper = styled.div` - padding: 20px; - display: flex; - justify-content: flex-end; - - > :not(:last-child) { - margin-right: 10px; - } -` diff --git a/web/src/components/Settings/SettingsDialog.jsx b/web/src/components/Settings/SettingsDialog.jsx index fc7e8d4..457d7d1 100644 --- a/web/src/components/Settings/SettingsDialog.jsx +++ b/web/src/components/Settings/SettingsDialog.jsx @@ -5,14 +5,200 @@ import DialogContent from '@material-ui/core/DialogContent' import TextField from '@material-ui/core/TextField' import DialogActions from '@material-ui/core/DialogActions' import Button from '@material-ui/core/Button' -import { FormControlLabel, InputLabel, Select, Switch } from '@material-ui/core' +import Checkbox from '@material-ui/core/Checkbox' +import { + ButtonGroup, + FormControlLabel, + Grid, + Input, + InputLabel, + Select, + Slider, + Switch, + useMediaQuery, + useTheme, +} from '@material-ui/core' import { settingsHost, setTorrServerHost, getTorrServerHost } from 'utils/Hosts' import { useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' +import { Header } from 'style/DialogStyles' +import AppBar from '@material-ui/core/AppBar' +import Tabs from '@material-ui/core/Tabs' +import Tab from '@material-ui/core/Tab' +import SwipeableViews from 'react-swipeable-views' +import styled, { css } from 'styled-components' +import { USBIcon, RAMIcon } from 'icons' + +const FooterSection = styled.div` + padding: 20px; + display: flex; + align-items: center; + justify-content: space-between; + background: #e8e5eb; + + > :last-child > :not(:last-child) { + margin-right: 10px; + } +` +const Divider = styled.div` + height: 1px; + background-color: rgba(0, 0, 0, 0.12); + margin: 30px 0; +` + +const PreloadCachePercentage = styled.div.attrs( + ({ + value, + // theme: { + // dialogTorrentDetailsContent: { gradientEndColor }, + // }, + }) => { + const gradientStartColor = 'lightblue' + const gradientEndColor = 'orangered' + + return { + // this block is here according to styled-components recomendation about fast changable components + style: { + background: `linear-gradient(to right, ${gradientEndColor} 0%, ${gradientEndColor} ${value}%, ${gradientStartColor} ${value}%, ${gradientStartColor} 100%)`, + }, + } + }, +)` + ${({ label, isPreloadEnabled }) => css` + border: 1px solid; + padding: 10px 20px; + border-radius: 5px; + color: #000; + margin-bottom: 10px; + position: relative; + + :before { + content: '${label}'; + display: grid; + place-items: center; + font-size: 20px; + } + + ${isPreloadEnabled && + css` + :after { + content: ''; + width: 100%; + height: 3px; + background: green; + position: absolute; + bottom: 0; + left: 0; + } + `} + `} +` + +const PreloadCacheValue = styled.div` + ${({ color }) => css` + display: grid; + grid-template-columns: max-content 100px 1fr; + gap: 10px; + align-items: center; + + :not(:last-child) { + margin-bottom: 5px; + } + + :before { + content: ''; + background: ${color}; + width: 15px; + height: 15px; + border-radius: 50%; + } + `} +` + +const a11yProps = index => ({ + id: `full-width-tab-${index}`, + 'aria-controls': `full-width-tabpanel-${index}`, +}) + +const TabPanel = ({ children, value, index, ...other }) => ( + +) + +const MainSettingsContent = styled.div` + min-height: 500px; + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 40px; + padding: 20px; + + @media (max-width: 930px) { + grid-template-columns: 1fr; + } +` +const SecondarySettingsContent = styled.div` + min-height: 500px; + padding: 20px; +` + +const StorageButton = styled.div` + display: grid; + place-items: center; + gap: 10px; +` + +const StorageIconWrapper = styled.div` + ${({ selected }) => css` + width: 150px; + height: 150px; + border-radius: 50%; + background: ${selected ? 'blue' : 'lightgray'}; + transition: 0.2s; + + ${!selected && + css` + cursor: pointer; + + :hover { + background: orangered; + } + `} + + svg { + transform: rotate(-45deg) scale(0.75); + } + `} +` + +const CacheSizeSettings = styled.div`` +const CacheStorageSelector = styled.div` + display: grid; + grid-template-rows: max-content 1fr; + grid-template-columns: 1fr 1fr; + grid-template-areas: 'label label'; + place-items: center; + + @media (max-width: 930px) { + grid-template-columns: repeat(2, max-content); + column-gap: 30px; + } +` + +const CacheStorageSettings = styled.div`` + +const SettingSection = styled.section`` +const SettingLabel = styled.div`` +const SettingSectionLabel = styled.div` + font-size: 25px; + padding-bottom: 20px; +` export default function SettingsDialog({ handleClose }) { const { t } = useTranslation() + const fullScreen = useMediaQuery('@media (max-width:930px)') + const [settings, setSets] = useState({}) const [show, setShow] = useState(false) const [tsHost, setTSHost] = useState(getTorrServerHost()) @@ -83,9 +269,337 @@ export default function SettingsDialog({ handleClose }) { RemoveCacheOnDrop, } = settings + const { direction } = useTheme() + const [selectedTab, setSelectedTab] = useState(0) + + const handleChange = (_, newValue) => setSelectedTab(newValue) + + const handleChangeIndex = index => setSelectedTab(index) + + const [cacheSize, setCacheSize] = useState(96) + const [cachePercentage, setCachePercentage] = useState(95) + const [isProMode, setIsProMode] = useState(JSON.parse(localStorage.getItem('isProMode')) || false) + const [isRamSelected, setIsRamSelected] = useState(true) + + const handleSliderChange = (_, newValue) => { + setCacheSize(newValue) + } + + const handleBlur = ({ target: { value } }) => { + if (value < 32) return setCacheSize(32) + if (value > 20000) return setCacheSize(20000) + + setCacheSize(Math.round(value / 8) * 8) + } + + const handleInputChange = ({ target: { value } }) => { + setCacheSize(value === '' ? '' : Number(value)) + } + return ( - - {t('Settings')} + +
{t('Settings')}
+ + <> + + + + + + + + + + + + + Настройки кеша + + + + +
+ {100 - cachePercentage}% ({Math.round((cacheSize / 100) * (100 - cachePercentage))} МБ) +
+
От кеша будет оставаться позади воспроизводимого блока
+
+ + +
+ {cachePercentage}% ({Math.round((cacheSize / 100) * cachePercentage)} МБ) +
+
От кеша будет спереди от воспроизводимого блока
+
+ + + + + Размер кеша + + + + + + + {isProMode && ( + + + + )} + + + + + Кеш предзагрузки + + + + setCachePercentage(newValue)} + /> + + + {isProMode && ( + + setCachePercentage(value === '' ? '' : Number(value))} + onBlur={({ target: { value } }) => { + if (value < 0) return setCachePercentage(0) + if (value > 100) return setCachePercentage(100) + }} + style={{ width: '65px' }} + inputProps={{ + min: 0, + max: 100, + type: 'number', + }} + /> + + )} + + + + + } + label={t('PreloadBuffer')} + /> + +
+ + {isRamSelected ? ( + + + Место хранения кеша + + + + + + +
Оперативная память
+
+ + + setIsRamSelected(false)}> + + +
Диск
+
+
+ ) : ( + + Место хранения кеша + + + + + + + + + } + label={t('RemoveCacheOnDrop')} + /> + {t('RemoveCacheOnDropDesc')} + + + )} +
+
+ + + + Дополнительные настройки + + } + label={t('EnableIPv6')} + /> +
+ } + label={t('TCP')} + /> +
+ } + label={t('UTP')} + /> +
+ } + label={t('PEX')} + /> +
+ } + label={t('ForceEncrypt')} + /> +
+ +
+ +
+ } + label={t('DHT')} + /> +
+ +
+ +
+ } + label={t('Upload')} + /> +
+ +
+ +
+ } + label={t('UPNP')} + /> +
+ {t('RetrackersMode')} + +
+
+
+
+ + {/* {t('Settings')} {t('Save')} - + */} + + { + setIsProMode(checked) + localStorage.setItem('isProMode', checked) + if (!checked) setSelectedTab(0) + }} + color='primary' + /> + } + label='Pro mode' + /> + +
+ + + +
+
) } diff --git a/web/src/icons/index.jsx b/web/src/icons/index.jsx index 914e109..79caaea 100644 --- a/web/src/icons/index.jsx +++ b/web/src/icons/index.jsx @@ -52,6 +52,116 @@ export const AddItemIcon = () => { ) } +export const USBIcon = ({ color, width }) => { + const primary = useTheme().palette.primary.main + + return ( + + + + + + + ) +} + +export const RAMIcon = ({ color, width }) => { + const primary = useTheme().palette.primary.main + + return ( + + + + + + + + + + + + + + + ) +} + export const TorrentIcon = () => { const primary = useTheme().palette.primary.main const secondaryColor = primary === '#00a572' ? '#74c39c' : '#4a5255' diff --git a/web/src/style/DialogStyles.js b/web/src/style/DialogStyles.js new file mode 100644 index 0000000..6491812 --- /dev/null +++ b/web/src/style/DialogStyles.js @@ -0,0 +1,24 @@ +import styled, { css } from 'styled-components' + +export const Header = styled.div` + ${({ theme: { primary } }) => css` + background: ${primary}; + color: rgba(0, 0, 0, 0.87); + font-size: 20px; + color: #fff; + font-weight: 600; + box-shadow: 0px 2px 4px -1px rgb(0 0 0 / 20%), 0px 4px 5px 0px rgb(0 0 0 / 14%), 0px 1px 10px 0px rgb(0 0 0 / 12%); + padding: 15px 24px; + position: relative; + `} +` + +export const ButtonWrapper = styled.div` + padding: 20px; + display: flex; + justify-content: flex-end; + + > :not(:last-child) { + margin-right: 10px; + } +` diff --git a/web/yarn.lock b/web/yarn.lock index 0fa0ddd..12bc69a 100644 --- a/web/yarn.lock +++ b/web/yarn.lock @@ -1167,6 +1167,13 @@ core-js-pure "^3.0.0" regenerator-runtime "^0.13.4" +"@babel/runtime@7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.0.0.tgz#adeb78fedfc855aa05bc041640f3f6f98e85424c" + integrity sha512-7hGhzlcmg01CvH1EHdSPVXYX1aJ8KCEyz6I9xYIi/asDtzBPMyMhVibhM/K6g/5qnKBwjZtp10bNZIEFTRW1MA== + dependencies: + regenerator-runtime "^0.12.0" + "@babel/runtime@7.12.1": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.1.tgz#b4116a6b6711d010b2dad3b7b6e43bf1b9954740" @@ -7894,6 +7901,11 @@ just-debounce@^1.0.0: resolved "https://registry.yarnpkg.com/just-debounce/-/just-debounce-1.1.0.tgz#2f81a3ad4121a76bc7cb45dbf704c0d76a8e5ddf" integrity sha512-qpcRocdkUmf+UTNBYx5w6dexX5J31AKK1OmPwH630a83DdVVUIngk55RSAiIGpQyoH0dlr872VHfPjnQnK1qDQ== +keycode@^2.1.7: + version "2.2.0" + resolved "https://registry.yarnpkg.com/keycode/-/keycode-2.2.0.tgz#3d0af56dc7b8b8e5cba8d0a97f107204eec22b04" + integrity sha1-PQr1bce4uOXLqNCpfxByBO7CKwQ= + killable@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892" @@ -8158,7 +8170,7 @@ loglevel@^1.6.8: resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.7.1.tgz#005fde2f5e6e47068f935ff28573e125ef72f197" integrity sha512-Hesni4s5UkWkwCGJMQGAh71PaLUmKFM60dHvq0zi/vDhhrzuk+4GgNbTXJ12YYQJn6ZKBDNIjYcuQGKudvqrIw== -loose-envify@^1.1.0, loose-envify@^1.4.0: +loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== @@ -10207,7 +10219,7 @@ prompts@^2.0.1: kleur "^3.0.3" sisteransi "^1.0.5" -prop-types@^15.5.8, prop-types@^15.6.2, prop-types@^15.7.2: +prop-types@^15.5.4, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2: version "15.7.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== @@ -10451,6 +10463,15 @@ react-error-overlay@^6.0.9: resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.9.tgz#3c743010c9359608c375ecd6bc76f35d93995b0a" integrity sha512-nQTTcUu+ATDbrSD1BZHr5kgSD4oF8OFjxun8uAaL8RwPBacGBNPf/yAuVVdx17N8XNzRDMrZ9XcKZHCjPW+9ew== +react-event-listener@^0.6.0: + version "0.6.6" + resolved "https://registry.yarnpkg.com/react-event-listener/-/react-event-listener-0.6.6.tgz#758f7b991cad9086dd39fd29fad72127e1d8962a" + integrity sha512-+hCNqfy7o9wvO6UgjqFmBzARJS7qrNoda0VqzvOuioEpoEXKutiKuv92dSz6kP7rYLmyHPyYNLesi5t/aH1gfw== + dependencies: + "@babel/runtime" "^7.2.0" + prop-types "^15.6.0" + warning "^4.0.1" + react-i18next@^11.10.0: version "11.10.0" resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-11.10.0.tgz#f34257447e18e710e36d8fd3f721dd7d37c7004f" @@ -10559,6 +10580,37 @@ react-scripts@4.0.3: optionalDependencies: fsevents "^2.1.3" +react-swipeable-views-core@^0.14.0: + version "0.14.0" + resolved "https://registry.yarnpkg.com/react-swipeable-views-core/-/react-swipeable-views-core-0.14.0.tgz#6ac443a7cc7bc5ea022fbd549292bb5fff361cce" + integrity sha512-0W/e9uPweNEOSPjmYtuKSC/SvKKg1sfo+WtPdnxeLF3t2L82h7jjszuOHz9C23fzkvLfdgkaOmcbAxE9w2GEjA== + dependencies: + "@babel/runtime" "7.0.0" + warning "^4.0.1" + +react-swipeable-views-utils@^0.14.0: + version "0.14.0" + resolved "https://registry.yarnpkg.com/react-swipeable-views-utils/-/react-swipeable-views-utils-0.14.0.tgz#6b76e251906747482730c22002fe47ab1014ba32" + integrity sha512-W+fXBOsDqgFK1/g7MzRMVcDurp3LqO3ksC8UgInh2P/tKgb5DusuuB1geKHFc6o1wKl+4oyER4Zh3Lxmr8xbXA== + dependencies: + "@babel/runtime" "7.0.0" + keycode "^2.1.7" + prop-types "^15.6.0" + react-event-listener "^0.6.0" + react-swipeable-views-core "^0.14.0" + shallow-equal "^1.2.1" + +react-swipeable-views@^0.14.0: + version "0.14.0" + resolved "https://registry.yarnpkg.com/react-swipeable-views/-/react-swipeable-views-0.14.0.tgz#149c0df3d92220cc89e3f6d5c04a78dfe46f9b54" + integrity sha512-wrTT6bi2nC3JbmyNAsPXffUXLn0DVT9SbbcFr36gKpbaCgEp7rX/OFxsu5hPc/NBsUhHyoSRGvwqJNNrWTwCww== + dependencies: + "@babel/runtime" "7.0.0" + prop-types "^15.5.4" + react-swipeable-views-core "^0.14.0" + react-swipeable-views-utils "^0.14.0" + warning "^4.0.1" + react-transition-group@^4.4.0: version "4.4.1" resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.1.tgz#63868f9325a38ea5ee9535d828327f85773345c9" @@ -10699,6 +10751,11 @@ regenerator-runtime@^0.11.0: resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== +regenerator-runtime@^0.12.0: + version "0.12.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz#fa1a71544764c036f8c49b13a08b2594c9f8a0de" + integrity sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg== + regenerator-runtime@^0.13.4, regenerator-runtime@^0.13.7: version "0.13.7" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55" @@ -11315,6 +11372,11 @@ sha.js@^2.4.0, sha.js@^2.4.8: inherits "^2.0.1" safe-buffer "^5.0.1" +shallow-equal@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/shallow-equal/-/shallow-equal-1.2.1.tgz#4c16abfa56043aa20d050324efa68940b0da79da" + integrity sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA== + shallowequal@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8" @@ -12751,6 +12813,13 @@ walker@^1.0.7, walker@~1.0.5: dependencies: makeerror "1.0.x" +warning@^4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3" + integrity sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w== + dependencies: + loose-envify "^1.0.0" + watchpack-chokidar2@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz#38500072ee6ece66f3769936950ea1771be1c957" From dbfc1db5d28abd3b7f97ab9c2358ae705de13714 Mon Sep 17 00:00:00 2001 From: Daniel Shleifman Date: Fri, 2 Jul 2021 17:56:32 +0300 Subject: [PATCH 04/13] refactor --- web/src/components/App/Sidebar.jsx | 2 +- .../components/Settings/SettingsDialog.jsx | 825 ++++++++---------- web/src/components/Settings/index.jsx | 4 +- web/src/components/Settings/style.js | 161 ++++ 4 files changed, 533 insertions(+), 459 deletions(-) create mode 100644 web/src/components/Settings/style.js diff --git a/web/src/components/App/Sidebar.jsx b/web/src/components/App/Sidebar.jsx index 344bcaf..9158381 100644 --- a/web/src/components/App/Sidebar.jsx +++ b/web/src/components/App/Sidebar.jsx @@ -28,7 +28,7 @@ const Sidebar = ({ isDrawerOpen, setIsDonationDialogOpen, isOffline, isLoading } - + diff --git a/web/src/components/Settings/SettingsDialog.jsx b/web/src/components/Settings/SettingsDialog.jsx index 457d7d1..c235341 100644 --- a/web/src/components/Settings/SettingsDialog.jsx +++ b/web/src/components/Settings/SettingsDialog.jsx @@ -18,7 +18,7 @@ import { useMediaQuery, useTheme, } from '@material-ui/core' -import { settingsHost, setTorrServerHost, getTorrServerHost } from 'utils/Hosts' +import { settingsHost } from 'utils/Hosts' import { useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' import { Header } from 'style/DialogStyles' @@ -26,94 +26,26 @@ import AppBar from '@material-ui/core/AppBar' import Tabs from '@material-ui/core/Tabs' import Tab from '@material-ui/core/Tab' import SwipeableViews from 'react-swipeable-views' -import styled, { css } from 'styled-components' import { USBIcon, RAMIcon } from 'icons' -const FooterSection = styled.div` - padding: 20px; - display: flex; - align-items: center; - justify-content: space-between; - background: #e8e5eb; - - > :last-child > :not(:last-child) { - margin-right: 10px; - } -` -const Divider = styled.div` - height: 1px; - background-color: rgba(0, 0, 0, 0.12); - margin: 30px 0; -` - -const PreloadCachePercentage = styled.div.attrs( - ({ - value, - // theme: { - // dialogTorrentDetailsContent: { gradientEndColor }, - // }, - }) => { - const gradientStartColor = 'lightblue' - const gradientEndColor = 'orangered' - - return { - // this block is here according to styled-components recomendation about fast changable components - style: { - background: `linear-gradient(to right, ${gradientEndColor} 0%, ${gradientEndColor} ${value}%, ${gradientStartColor} ${value}%, ${gradientStartColor} 100%)`, - }, - } - }, -)` - ${({ label, isPreloadEnabled }) => css` - border: 1px solid; - padding: 10px 20px; - border-radius: 5px; - color: #000; - margin-bottom: 10px; - position: relative; - - :before { - content: '${label}'; - display: grid; - place-items: center; - font-size: 20px; - } - - ${isPreloadEnabled && - css` - :after { - content: ''; - width: 100%; - height: 3px; - background: green; - position: absolute; - bottom: 0; - left: 0; - } - `} - `} -` - -const PreloadCacheValue = styled.div` - ${({ color }) => css` - display: grid; - grid-template-columns: max-content 100px 1fr; - gap: 10px; - align-items: center; - - :not(:last-child) { - margin-bottom: 5px; - } - - :before { - content: ''; - background: ${color}; - width: 15px; - height: 15px; - border-radius: 50%; - } - `} -` +import { + FooterSection, + Divider, + PreloadCacheValue, + MainSettingsContent, + SecondarySettingsContent, + StorageButton, + StorageIconWrapper, + CacheSizeSettings, + CacheStorageSelector, + CacheStorageSettings, + SettingSection, + SettingLabel, + SettingSectionLabel, + PreloadCachePercentage, + cacheBeforeReaderColor, + cacheAfterReaderColor, +} from './style' const a11yProps = index => ({ id: `full-width-tab-${index}`, @@ -126,103 +58,57 @@ const TabPanel = ({ children, value, index, ...other }) => (
) -const MainSettingsContent = styled.div` - min-height: 500px; - display: grid; - grid-template-columns: repeat(2, 1fr); - gap: 40px; - padding: 20px; - - @media (max-width: 930px) { - grid-template-columns: 1fr; - } -` -const SecondarySettingsContent = styled.div` - min-height: 500px; - padding: 20px; -` - -const StorageButton = styled.div` - display: grid; - place-items: center; - gap: 10px; -` - -const StorageIconWrapper = styled.div` - ${({ selected }) => css` - width: 150px; - height: 150px; - border-radius: 50%; - background: ${selected ? 'blue' : 'lightgray'}; - transition: 0.2s; - - ${!selected && - css` - cursor: pointer; - - :hover { - background: orangered; - } - `} - - svg { - transform: rotate(-45deg) scale(0.75); - } - `} -` - -const CacheSizeSettings = styled.div`` -const CacheStorageSelector = styled.div` - display: grid; - grid-template-rows: max-content 1fr; - grid-template-columns: 1fr 1fr; - grid-template-areas: 'label label'; - place-items: center; - - @media (max-width: 930px) { - grid-template-columns: repeat(2, max-content); - column-gap: 30px; - } -` - -const CacheStorageSettings = styled.div`` - -const SettingSection = styled.section`` -const SettingLabel = styled.div`` -const SettingSectionLabel = styled.div` - font-size: 25px; - padding-bottom: 20px; -` +const defaultSettings = { + CacheSize: 96, + ReaderReadAHead: 95, + UseDisk: false, + UploadRateLimit: 0, + TorrentsSavePath: '', + ConnectionsLimit: 23, + DhtConnectionLimit: 500, + DisableDHT: false, + DisablePEX: false, + DisableTCP: false, + DisableUPNP: false, + DisableUTP: true, + DisableUpload: false, + DownloadRateLimit: 0, + EnableDebug: false, + EnableIPv6: false, + ForceEncrypt: false, + PeersListenPort: 0, + PreloadBuffer: false, + RemoveCacheOnDrop: false, + RetrackersMode: 1, + Strategy: 0, + TorrentDisconnectTimeout: 30, +} export default function SettingsDialog({ handleClose }) { const { t } = useTranslation() const fullScreen = useMediaQuery('@media (max-width:930px)') - const [settings, setSets] = useState({}) + const [settings, setSettings] = useState() const [show, setShow] = useState(false) - const [tsHost, setTSHost] = useState(getTorrServerHost()) + useEffect(() => { axios .post(settingsHost(), { action: 'get' }) .then(({ data }) => { - setSets({ ...data, CacheSize: data.CacheSize / (1024 * 1024) }) + setSettings({ ...data, CacheSize: data.CacheSize / (1024 * 1024) }) setShow(true) }) .catch(() => setShow(false)) - }, [tsHost]) + }, []) const handleSave = () => { handleClose() const sets = JSON.parse(JSON.stringify(settings)) - sets.CacheSize *= 1024 * 1024 + sets.CacheSize = cacheSize * 1024 * 1024 + sets.ReaderReadAHead = cachePercentage axios.post(settingsHost(), { action: 'set', sets }) } - const onInputHost = ({ target: { value } }) => { - const host = value.replace(/\/$/gi, '') - setTorrServerHost(host) - setTSHost(host) - } const inputForm = ({ target: { type, value, checked, id } }) => { const sets = JSON.parse(JSON.stringify(settings)) @@ -242,7 +128,7 @@ export default function SettingsDialog({ handleClose }) { } else if (type === 'url') { sets[id] = value } - setSets(sets) + setSettings(sets) } const { @@ -267,7 +153,9 @@ export default function SettingsDialog({ handleClose }) { UseDisk, TorrentsSavePath, RemoveCacheOnDrop, - } = settings + } = settings || {} + + const updateSettings = newProps => setSettings({ ...settings, ...newProps }) const { direction } = useTheme() const [selectedTab, setSelectedTab] = useState(0) @@ -276,14 +164,16 @@ export default function SettingsDialog({ handleClose }) { const handleChangeIndex = index => setSelectedTab(index) - const [cacheSize, setCacheSize] = useState(96) - const [cachePercentage, setCachePercentage] = useState(95) + const [cacheSize, setCacheSize] = useState(32) + const [cachePercentage, setCachePercentage] = useState(40) const [isProMode, setIsProMode] = useState(JSON.parse(localStorage.getItem('isProMode')) || false) - const [isRamSelected, setIsRamSelected] = useState(true) - const handleSliderChange = (_, newValue) => { - setCacheSize(newValue) - } + useEffect(() => { + if (!CacheSize || !ReaderReadAHead) return + + setCacheSize(CacheSize) + setCachePercentage(ReaderReadAHead) + }, [CacheSize, ReaderReadAHead]) const handleBlur = ({ target: { value } }) => { if (value < 32) return setCacheSize(32) @@ -300,305 +190,316 @@ export default function SettingsDialog({ handleClose }) {
{t('Settings')}
- <> - - + + + + + + + + + - + + + + Настройки кеша - - - - - - - - - Настройки кеша - - - - -
- {100 - cachePercentage}% ({Math.round((cacheSize / 100) * (100 - cachePercentage))} МБ) -
-
От кеша будет оставаться позади воспроизводимого блока
-
- - -
- {cachePercentage}% ({Math.round((cacheSize / 100) * cachePercentage)} МБ) -
-
От кеша будет спереди от воспроизводимого блока
-
- - - - - Размер кеша - - - - - - - {isProMode && ( - - - - )} - - - - - Кеш предзагрузки - - - - setCachePercentage(newValue)} - /> - - - {isProMode && ( - - setCachePercentage(value === '' ? '' : Number(value))} - onBlur={({ target: { value } }) => { - if (value < 0) return setCachePercentage(0) - if (value > 100) return setCachePercentage(100) - }} - style={{ width: '65px' }} - inputProps={{ - min: 0, - max: 100, - type: 'number', - }} - /> - - )} - - - - - } - label={t('PreloadBuffer')} + - -
- {isRamSelected ? ( - - - Место хранения кеша - + +
+ {100 - cachePercentage}% ({Math.round((cacheSize / 100) * (100 - cachePercentage))} МБ) +
+
От кеша будет оставаться позади воспроизводимого блока
+
- - - - -
Оперативная память
-
+ +
+ {cachePercentage}% ({Math.round((cacheSize / 100) * cachePercentage)} МБ) +
+
От кеша будет спереди от воспроизводимого блока
+
- - setIsRamSelected(false)}> - - -
Диск
-
-
- ) : ( - - Место хранения кеша + - - + + Размер кеша - - + + + setCacheSize(newValue)} + step={8} + /> + + + {isProMode && ( + + + + )} + + + + + Кеш предзагрузки + + + + setCachePercentage(newValue)} + /> + + + {isProMode && ( + + setCachePercentage(value === '' ? '' : Number(value))} + onBlur={({ target: { value } }) => { + if (value < 0) return setCachePercentage(0) + if (value > 100) return setCachePercentage(100) + }} + style={{ width: '65px' }} + inputProps={{ min: 0, max: 100, type: 'number' }} + /> + + )} + + + } - label={t('RemoveCacheOnDrop')} + label={t('PreloadBuffer')} /> - {t('RemoveCacheOnDropDesc')} - - - )} -
-
+ - - - Дополнительные настройки + {UseDisk ? ( + + Место хранения кеша - } - label={t('EnableIPv6')} - /> -
- } - label={t('TCP')} - /> -
- } - label={t('UTP')} - /> -
- } - label={t('PEX')} - /> -
- } - label={t('ForceEncrypt')} - /> -
- -
- -
- } - label={t('DHT')} - /> -
- -
- -
- } - label={t('Upload')} - /> -
- -
- -
- } - label={t('UPNP')} - /> -
- {t('RetrackersMode')} - -
-
-
-
- +
+ updateSettings({ UseDisk: false })}> + + + + +
Оперативная память
+
+ + + + + + +
Диск
+
+
+ + + } + label={t('RemoveCacheOnDrop')} + /> + {t('RemoveCacheOnDropDesc')} + + + + ) : ( + + + Место хранения кеша + + + + + + + +
Оперативная память
+
+ + updateSettings({ UseDisk: true })}> + + + + +
Диск
+
+
+ )} + + + + + + Дополнительные настройки + + } + label={t('EnableIPv6')} + /> +
+ } + label={t('TCP')} + /> +
+ } + label={t('UTP')} + /> +
+ } + label={t('PEX')} + /> +
+ } + label={t('ForceEncrypt')} + /> +
+ +
+ +
+ } + label={t('DHT')} + /> +
+ +
+ +
+ } + label={t('Upload')} + /> +
+ +
+ +
+ } + label={t('UPNP')} + /> +
+ {t('RetrackersMode')} + +
+
+
+ + + ) : ( + 'loading...' + )} {/* {t('Settings')} + + diff --git a/web/src/components/Settings/index.jsx b/web/src/components/Settings/index.jsx index be19058..6c38026 100644 --- a/web/src/components/Settings/index.jsx +++ b/web/src/components/Settings/index.jsx @@ -7,7 +7,7 @@ import { useTranslation } from 'react-i18next' import SettingsDialog from './SettingsDialog' -export default function SettingsDialogButton() { +export default function SettingsDialogButton({ isOffline, isLoading }) { const { t } = useTranslation() const [isDialogOpen, setIsDialogOpen] = useState(false) @@ -16,7 +16,7 @@ export default function SettingsDialogButton() { return (
- + diff --git a/web/src/components/Settings/style.js b/web/src/components/Settings/style.js new file mode 100644 index 0000000..24177da --- /dev/null +++ b/web/src/components/Settings/style.js @@ -0,0 +1,161 @@ +import styled, { css } from 'styled-components' +import { mainColors } from 'style/colors' + +export const cacheBeforeReaderColor = '#b3dfc9' +export const cacheAfterReaderColor = mainColors.light.primary + +export const FooterSection = styled.div` + padding: 20px; + display: flex; + align-items: center; + justify-content: space-between; + background: #e8e5eb; + + > :last-child > :not(:last-child) { + margin-right: 10px; + } +` +export const Divider = styled.div` + height: 1px; + background-color: rgba(0, 0, 0, 0.12); + margin: 30px 0; +` + +export const PreloadCacheValue = styled.div` + ${({ color }) => css` + display: grid; + grid-template-columns: max-content 100px 1fr; + gap: 10px; + align-items: center; + + :not(:last-child) { + margin-bottom: 5px; + } + + :before { + content: ''; + background: ${color}; + width: 15px; + height: 15px; + border-radius: 50%; + } + `} +` + +export const MainSettingsContent = styled.div` + min-height: 500px; + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 40px; + padding: 20px; + + @media (max-width: 930px) { + grid-template-columns: 1fr; + } +` +export const SecondarySettingsContent = styled.div` + min-height: 500px; + padding: 20px; +` + +export const StorageButton = styled.div` + ${({ small, selected }) => css` + transition: 0.2s; + cursor: default; + + ${!selected && + css` + cursor: pointer; + + :hover { + filter: brightness(0.8); + } + `} + + ${small + ? css` + display: grid; + grid-template-columns: max-content 1fr; + gap: 20px; + align-items: center; + margin-bottom: 20px; + ` + : css` + display: grid; + place-items: center; + gap: 10px; + `} + `} +` + +export const StorageIconWrapper = styled.div` + ${({ selected, small }) => css` + width: ${small ? '60px' : '150px'}; + height: ${small ? '60px' : '150px'}; + border-radius: 50%; + background: ${selected ? '#323637' : '#dee3e5'}; + + svg { + transform: rotate(-45deg) scale(0.75); + } + `} +` + +export const CacheSizeSettings = styled.div`` +export const CacheStorageSelector = styled.div` + display: grid; + grid-template-rows: max-content 1fr; + grid-template-columns: 1fr 1fr; + grid-template-areas: 'label label'; + place-items: center; + + @media (max-width: 930px) { + grid-template-columns: repeat(2, max-content); + column-gap: 30px; + } +` + +export const CacheStorageSettings = styled.div`` + +export const SettingSection = styled.section`` +export const SettingLabel = styled.div`` +export const SettingSectionLabel = styled.div` + font-size: 25px; + padding-bottom: 20px; +` + +export const PreloadCachePercentage = styled.div.attrs(({ value }) => ({ + // this block is here according to styled-components recomendation about fast changable components + style: { + background: `linear-gradient(to right, ${cacheBeforeReaderColor} 0%, ${cacheBeforeReaderColor} ${value}%, ${cacheAfterReaderColor} ${value}%, ${cacheAfterReaderColor} 100%)`, + }, +}))` + ${({ label, isPreloadEnabled }) => css` + border: 1px solid #323637; + padding: 10px 20px; + border-radius: 5px; + color: #000; + margin-bottom: 10px; + position: relative; + + :before { + content: '${label}'; + display: grid; + place-items: center; + font-size: 20px; + } + + ${isPreloadEnabled && + css` + :after { + content: ''; + width: 100%; + height: 2px; + background: #323637; + position: absolute; + bottom: 0; + left: 0; + } + `} + `} +` From 28c64e9307a63c50333f7063eb2ab39bf5e1da17 Mon Sep 17 00:00:00 2001 From: Daniel Shleifman Date: Fri, 2 Jul 2021 20:10:15 +0300 Subject: [PATCH 05/13] refactor --- .../components/Settings/SettingsDialog.jsx | 651 ++++++++---------- .../components/Settings/defaultSettings.js | 25 + web/src/components/Settings/style.js | 20 +- web/src/components/Settings/tabComponents.jsx | 10 + 4 files changed, 350 insertions(+), 356 deletions(-) create mode 100644 web/src/components/Settings/defaultSettings.js create mode 100644 web/src/components/Settings/tabComponents.jsx diff --git a/web/src/components/Settings/SettingsDialog.jsx b/web/src/components/Settings/SettingsDialog.jsx index c235341..5ed27c9 100644 --- a/web/src/components/Settings/SettingsDialog.jsx +++ b/web/src/components/Settings/SettingsDialog.jsx @@ -1,13 +1,9 @@ import axios from 'axios' import Dialog from '@material-ui/core/Dialog' -import DialogTitle from '@material-ui/core/DialogTitle' -import DialogContent from '@material-ui/core/DialogContent' import TextField from '@material-ui/core/TextField' -import DialogActions from '@material-ui/core/DialogActions' import Button from '@material-ui/core/Button' import Checkbox from '@material-ui/core/Checkbox' import { - ButtonGroup, FormControlLabel, Grid, Input, @@ -27,6 +23,7 @@ import Tabs from '@material-ui/core/Tabs' import Tab from '@material-ui/core/Tab' import SwipeableViews from 'react-swipeable-views' import { USBIcon, RAMIcon } from 'icons' +import CircularProgress from '@material-ui/core/CircularProgress' import { FooterSection, @@ -36,70 +33,31 @@ import { SecondarySettingsContent, StorageButton, StorageIconWrapper, - CacheSizeSettings, CacheStorageSelector, - CacheStorageSettings, - SettingSection, - SettingLabel, SettingSectionLabel, PreloadCachePercentage, cacheBeforeReaderColor, cacheAfterReaderColor, + Content, } from './style' - -const a11yProps = index => ({ - id: `full-width-tab-${index}`, - 'aria-controls': `full-width-tabpanel-${index}`, -}) - -const TabPanel = ({ children, value, index, ...other }) => ( - -) - -const defaultSettings = { - CacheSize: 96, - ReaderReadAHead: 95, - UseDisk: false, - UploadRateLimit: 0, - TorrentsSavePath: '', - ConnectionsLimit: 23, - DhtConnectionLimit: 500, - DisableDHT: false, - DisablePEX: false, - DisableTCP: false, - DisableUPNP: false, - DisableUTP: true, - DisableUpload: false, - DownloadRateLimit: 0, - EnableDebug: false, - EnableIPv6: false, - ForceEncrypt: false, - PeersListenPort: 0, - PreloadBuffer: false, - RemoveCacheOnDrop: false, - RetrackersMode: 1, - Strategy: 0, - TorrentDisconnectTimeout: 30, -} +import defaultSettings from './defaultSettings' +import { a11yProps, TabPanel } from './tabComponents' export default function SettingsDialog({ handleClose }) { const { t } = useTranslation() - const fullScreen = useMediaQuery('@media (max-width:930px)') + const { direction } = useTheme() const [settings, setSettings] = useState() - const [show, setShow] = useState(false) + const [selectedTab, setSelectedTab] = useState(0) + const [cacheSize, setCacheSize] = useState(32) + const [cachePercentage, setCachePercentage] = useState(40) + const [isProMode, setIsProMode] = useState(JSON.parse(localStorage.getItem('isProMode')) || false) useEffect(() => { - axios - .post(settingsHost(), { action: 'get' }) - .then(({ data }) => { - setSettings({ ...data, CacheSize: data.CacheSize / (1024 * 1024) }) - setShow(true) - }) - .catch(() => setShow(false)) + axios.post(settingsHost(), { action: 'get' }).then(({ data }) => { + setSettings({ ...data, CacheSize: data.CacheSize / (1024 * 1024) }) + }) }, []) const handleSave = () => { @@ -155,19 +113,6 @@ export default function SettingsDialog({ handleClose }) { RemoveCacheOnDrop, } = settings || {} - const updateSettings = newProps => setSettings({ ...settings, ...newProps }) - - const { direction } = useTheme() - const [selectedTab, setSelectedTab] = useState(0) - - const handleChange = (_, newValue) => setSelectedTab(newValue) - - const handleChangeIndex = index => setSelectedTab(index) - - const [cacheSize, setCacheSize] = useState(32) - const [cachePercentage, setCachePercentage] = useState(40) - const [isProMode, setIsProMode] = useState(JSON.parse(localStorage.getItem('isProMode')) || false) - useEffect(() => { if (!CacheSize || !ReaderReadAHead) return @@ -175,331 +120,339 @@ export default function SettingsDialog({ handleClose }) { setCachePercentage(ReaderReadAHead) }, [CacheSize, ReaderReadAHead]) + const updateSettings = newProps => setSettings({ ...settings, ...newProps }) + const handleChange = (_, newValue) => setSelectedTab(newValue) + const handleChangeIndex = index => setSelectedTab(index) const handleBlur = ({ target: { value } }) => { if (value < 32) return setCacheSize(32) if (value > 20000) return setCacheSize(20000) setCacheSize(Math.round(value / 8) * 8) } - - const handleInputChange = ({ target: { value } }) => { - setCacheSize(value === '' ? '' : Number(value)) - } + const handleInputChange = ({ target: { value } }) => setCacheSize(value === '' ? '' : Number(value)) return (
{t('Settings')}
- {settings ? ( - <> - - + {settings ? ( + <> + + + + + + + + + - + + +
+ Настройки кеша - - - + - - - - - Настройки кеша + +
+ {100 - cachePercentage}% ({Math.round((cacheSize / 100) * (100 - cachePercentage))} МБ) +
- +
От кеша будет оставаться позади воспроизводимого блока
+
- -
- {100 - cachePercentage}% ({Math.round((cacheSize / 100) * (100 - cachePercentage))} МБ) -
-
От кеша будет оставаться позади воспроизводимого блока
-
+ +
+ {cachePercentage}% ({Math.round((cacheSize / 100) * cachePercentage)} МБ) +
- -
- {cachePercentage}% ({Math.round((cacheSize / 100) * cachePercentage)} МБ) -
-
От кеша будет спереди от воспроизводимого блока
-
+
От кеша будет спереди от воспроизводимого блока
+
- + - - Размер кеша +
+
Размер кеша
- - - setCacheSize(newValue)} - step={8} - /> - - - {isProMode && ( - - + + setCacheSize(newValue)} + step={8} /> - )} - - - - Кеш предзагрузки - - - - setCachePercentage(newValue)} - /> + {isProMode && ( + + + + )} +
- {isProMode && ( - - +
Кеш предзагрузки
+ + + + setCachePercentage(value === '' ? '' : Number(value))} - onBlur={({ target: { value } }) => { - if (value < 0) return setCachePercentage(0) - if (value > 100) return setCachePercentage(100) - }} - style={{ width: '65px' }} - inputProps={{ min: 0, max: 100, type: 'number' }} + onChange={(_, newValue) => setCachePercentage(newValue)} /> - )} - -
- - } - label={t('PreloadBuffer')} - /> -
+ {isProMode && ( + + + setCachePercentage(value === '' ? '' : Number(value)) + } + onBlur={({ target: { value } }) => { + if (value < 0) return setCachePercentage(0) + if (value > 100) return setCachePercentage(100) + }} + style={{ width: '65px' }} + inputProps={{ min: 0, max: 100, type: 'number' }} + /> + + )} + + - {UseDisk ? ( - - Место хранения кеша + + } + label={t('PreloadBuffer')} + /> +
-
- updateSettings({ UseDisk: false })}> - - + {UseDisk ? ( +
+ Место хранения кеша + +
+ updateSettings({ UseDisk: false })}> + + + + +
Оперативная память
+
+ + + + + + +
Диск
+
+
+ + + } + label={t('RemoveCacheOnDrop')} + /> + {t('RemoveCacheOnDropDesc')} + + +
+ ) : ( + + + Место хранения кеша + + + + +
Оперативная память
- - - + updateSettings({ UseDisk: true })}> + +
Диск
-
+ + )} +
+
- - } - label={t('RemoveCacheOnDrop')} - /> - {t('RemoveCacheOnDropDesc')} + + + Дополнительные настройки - - - ) : ( - - - Место хранения кеша - - - - - - - -
Оперативная память
-
- - updateSettings({ UseDisk: true })}> - - - - -
Диск
-
-
- )} - -
- - - - Дополнительные настройки - - } - label={t('EnableIPv6')} - /> -
- } - label={t('TCP')} - /> -
- } - label={t('UTP')} - /> -
- } - label={t('PEX')} - /> -
- } - label={t('ForceEncrypt')} - /> -
- -
- -
- } - label={t('DHT')} - /> -
- -
- -
- } - label={t('Upload')} - /> -
- -
- -
- } - label={t('UPNP')} - /> -
- {t('RetrackersMode')} - -
-
-
-
- - ) : ( - 'loading...' - )} + } + label={t('EnableIPv6')} + /> +
+ } + label={t('TCP')} + /> +
+ } + label={t('UTP')} + /> +
+ } + label={t('PEX')} + /> +
+ } + label={t('ForceEncrypt')} + /> +
+ +
+ +
+ } + label={t('DHT')} + /> +
+ +
+ +
+ + } + label={t('Upload')} + /> +
+ +
+ +
+ } + label={t('UPNP')} + /> +
+ {t('RetrackersMode')} + +
+ + + + + ) : ( + + )} + {/* {t('Settings')} css` + background: #f1eff3; + min-height: 500px; + + ${isLoading && + css` + display: grid; + place-items: center; + `} + `} +` + export const PreloadCacheValue = styled.div` ${({ color }) => css` display: grid; @@ -43,7 +56,6 @@ export const PreloadCacheValue = styled.div` ` export const MainSettingsContent = styled.div` - min-height: 500px; display: grid; grid-template-columns: repeat(2, 1fr); gap: 40px; @@ -54,7 +66,6 @@ export const MainSettingsContent = styled.div` } ` export const SecondarySettingsContent = styled.div` - min-height: 500px; padding: 20px; ` @@ -101,7 +112,6 @@ export const StorageIconWrapper = styled.div` `} ` -export const CacheSizeSettings = styled.div`` export const CacheStorageSelector = styled.div` display: grid; grid-template-rows: max-content 1fr; @@ -115,10 +125,6 @@ export const CacheStorageSelector = styled.div` } ` -export const CacheStorageSettings = styled.div`` - -export const SettingSection = styled.section`` -export const SettingLabel = styled.div`` export const SettingSectionLabel = styled.div` font-size: 25px; padding-bottom: 20px; diff --git a/web/src/components/Settings/tabComponents.jsx b/web/src/components/Settings/tabComponents.jsx new file mode 100644 index 0000000..7bdff3c --- /dev/null +++ b/web/src/components/Settings/tabComponents.jsx @@ -0,0 +1,10 @@ +export const a11yProps = index => ({ + id: `full-width-tab-${index}`, + 'aria-controls': `full-width-tabpanel-${index}`, +}) + +export const TabPanel = ({ children, value, index, ...other }) => ( + +) From 3ac2aec6e3d6639936400f309aba55b547957c9f Mon Sep 17 00:00:00 2001 From: Daniel Shleifman Date: Fri, 2 Jul 2021 20:34:29 +0300 Subject: [PATCH 06/13] refactor --- .../components/Settings/SettingsDialog.jsx | 137 +++++++++--------- 1 file changed, 70 insertions(+), 67 deletions(-) diff --git a/web/src/components/Settings/SettingsDialog.jsx b/web/src/components/Settings/SettingsDialog.jsx index 5ed27c9..b2247cb 100644 --- a/web/src/components/Settings/SettingsDialog.jsx +++ b/web/src/components/Settings/SettingsDialog.jsx @@ -43,6 +43,54 @@ import { import defaultSettings from './defaultSettings' import { a11yProps, TabPanel } from './tabComponents' +const SliderInput = ({ + isProMode, + title, + value, + setValue, + sliderMin, + sliderMax, + inputMin, + inputMax, + step = 1, + onBlurCallback, +}) => { + const onBlur = ({ target: { value } }) => { + if (value < inputMin) return setValue(inputMin) + if (value > inputMax) return setValue(inputMax) + + onBlurCallback && onBlurCallback(value) + } + + const onInputChange = ({ target: { value } }) => setValue(value === '' ? '' : Number(value)) + const onSliderChange = (_, newValue) => setValue(newValue) + + return ( + <> +
{title}
+ + + + + + + {isProMode && ( + + + + )} + + + ) +} + export default function SettingsDialog({ handleClose }) { const { t } = useTranslation() const fullScreen = useMediaQuery('@media (max-width:930px)') @@ -123,13 +171,6 @@ export default function SettingsDialog({ handleClose }) { const updateSettings = newProps => setSettings({ ...settings, ...newProps }) const handleChange = (_, newValue) => setSelectedTab(newValue) const handleChangeIndex = index => setSelectedTab(index) - const handleBlur = ({ target: { value } }) => { - if (value < 32) return setCacheSize(32) - if (value > 20000) return setCacheSize(20000) - - setCacheSize(Math.round(value / 8) * 8) - } - const handleInputChange = ({ target: { value } }) => setCacheSize(value === '' ? '' : Number(value)) return ( @@ -190,67 +231,29 @@ export default function SettingsDialog({ handleClose }) { -
-
Размер кеша
+ setCacheSize(Math.round(value / 8) * 8)} + /> - - - setCacheSize(newValue)} - step={8} - /> - - - {isProMode && ( - - - - )} - -
- -
-
Кеш предзагрузки
- - - - setCachePercentage(newValue)} - /> - - - {isProMode && ( - - - setCachePercentage(value === '' ? '' : Number(value)) - } - onBlur={({ target: { value } }) => { - if (value < 0) return setCachePercentage(0) - if (value > 100) return setCachePercentage(100) - }} - style={{ width: '65px' }} - inputProps={{ min: 0, max: 100, type: 'number' }} - /> - - )} - -
+ Date: Sat, 3 Jul 2021 00:55:26 +0300 Subject: [PATCH 07/13] added new translations --- .../components/Settings/SettingsDialog.jsx | 282 ++++-------------- web/src/components/Settings/style.js | 1 + web/src/locales/en/translation.json | 61 ++-- web/src/locales/ru/translation.json | 61 ++-- 4 files changed, 118 insertions(+), 287 deletions(-) diff --git a/web/src/components/Settings/SettingsDialog.jsx b/web/src/components/Settings/SettingsDialog.jsx index b2247cb..4605911 100644 --- a/web/src/components/Settings/SettingsDialog.jsx +++ b/web/src/components/Settings/SettingsDialog.jsx @@ -43,6 +43,9 @@ import { import defaultSettings from './defaultSettings' import { a11yProps, TabPanel } from './tabComponents' +// {t('UseDisk')} +// {t('UseDiskDesc')} + const SliderInput = ({ isProMode, title, @@ -118,6 +121,7 @@ export default function SettingsDialog({ handleClose }) { const inputForm = ({ target: { type, value, checked, id } }) => { const sets = JSON.parse(JSON.stringify(settings)) + if (type === 'number' || type === 'select-one') { sets[id] = Number(value) } else if (type === 'checkbox') { @@ -174,29 +178,29 @@ export default function SettingsDialog({ handleClose }) { return ( -
{t('Settings')}
+
{t('SettingsDialog.Settings')}
+ + + + + + + + {settings ? ( <> - - - - - - - -
- Настройки кеша + {t('SettingsDialog.CacheSettings')} @@ -233,7 +237,7 @@ export default function SettingsDialog({ handleClose }) { } - label={t('PreloadBuffer')} + label={t('SettingsDialog.PreloadBuffer')} />
@@ -294,15 +298,15 @@ export default function SettingsDialog({ handleClose }) { color='primary' /> } - label={t('RemoveCacheOnDrop')} + label={t('SettingsDialog.RemoveCacheOnDrop')} /> - {t('RemoveCacheOnDropDesc')} + {t('SettingsDialog.RemoveCacheOnDropDesc')} } - label={t('EnableIPv6')} + label='IPv6' />
} - label={t('TCP')} + label='TCP (Transmission Control Protocol)' />
} - label={t('UTP')} + label='μTP (Micro Transport Protocol)' />
} - label={t('PEX')} + label='PEX (Peer Exchange)' />
} - label={t('ForceEncrypt')} + label={t('SettingsDialog.ForceEncrypt')} />
} - label={t('DHT')} + label={t('SettingsDialog.DHT')} />
} - label={t('Upload')} + label={t('SettingsDialog.Upload')} />
} - label={t('UPNP')} + label='UPnP (Universal Plug and Play)' />
- {t('RetrackersMode')} + {t('SettingsDialog.RetrackersMode')}
@@ -456,191 +460,7 @@ export default function SettingsDialog({ handleClose }) { )}
- {/* {t('Settings')} - - - {show && ( - <> - -
- -
- } - label={t('PreloadBuffer')} - /> -
- } - label={t('UseDisk')} - /> -
- {t('UseDiskDesc')} -
- - } - label={t('RemoveCacheOnDrop')} - /> -
- {t('RemoveCacheOnDropDesc')} -
- -
- } - label={t('EnableIPv6')} - /> -
- } - label={t('TCP')} - /> -
- } - label={t('UTP')} - /> -
- } - label={t('PEX')} - /> -
- } - label={t('ForceEncrypt')} - /> -
- -
- -
- } - label={t('DHT')} - /> -
- -
- -
- } - label={t('Upload')} - /> -
- -
- -
- } - label={t('UPNP')} - /> -
- {t('RetrackersMode')} - -
- - )} -
- - - - - */} } - label='Pro mode' + label={t('SettingsDialog.ProMode')} />
diff --git a/web/src/components/Settings/style.js b/web/src/components/Settings/style.js index d9f9df5..1609dd8 100644 --- a/web/src/components/Settings/style.js +++ b/web/src/components/Settings/style.js @@ -25,6 +25,7 @@ export const Content = styled.div` ${({ isLoading }) => css` background: #f1eff3; min-height: 500px; + overflow: auto; ${isLoading && css` diff --git a/web/src/locales/en/translation.json b/web/src/locales/en/translation.json index b5262f0..da45444 100644 --- a/web/src/locales/en/translation.json +++ b/web/src/locales/en/translation.json @@ -20,17 +20,14 @@ }, "AddFromLink": "Add from Link", "AddNewTorrent": "Add new torrent", - "AddRetrackers": "Add retrackers", "Buffer": "Preload Buffer / Cache", "BufferNote": "Enable “Preload Buffer” in settings to see cache loading progress", "Cache": "Cache", - "CacheSize": "Cache Size (Megabytes)", "Cancel": "Cancel", "Clear": "Clear", "Close": "Close", "CloseServer?": "Do you want to turn off server?", "CloseServer": "Turn Off", - "ConnectionsLimit": "Connections Limit", "CopyHash": "Copy Hash", "CopyLink": "Copy link", "Data": "Data", @@ -42,21 +39,15 @@ "header": "$t(DetailedCacheView.button)" }, "Details": "Details", - "DHT": "DHT (Distributed Hash Table)", - "DhtConnectionLimit": "DHT Connection Limit", "Donate?": "Want to donate?", "Donate": "Donate", - "DontAddRetrackers": "Don`t add retrackers", "DownloadPlaylist": "Download Playlist", - "DownloadRateLimit": "Download Rate Limit (Kilobytes)", "DownloadSpeed": "Download speed", "Drop": "Drop", "DropTorrent": "Reset Torrent", "Edit": "Edit", "EditTorrent": "Edit torrent", - "EnableIPv6": "IPv6", "Episode": "Episode", - "ForceEncrypt": "Force Encrypt Headers", "FromLatestFile": "From Latest File", "Full": "Full", "Host": "Host", @@ -69,55 +60,69 @@ "OK": "OK", "OpenLink": "Open link", "Peers": "Peers", - "PeersListenPort": "Peers Listen Port", - "PEX": "PEX (Peer Exchange)", "PiecesCount": "Pieces count", "PiecesLength": "Pieces length", "Preload": "Preload", - "PreloadBuffer": "Preload Buffer", "ProjectSource": "Project page", - "ReaderReadAHead": "Reader Read Ahead (5-100%)", "Releases": "Releases", "RemoveAll": "Remove All", - "RemoveCacheOnDrop": "Remove Cache from Disk on Drop Torrent", - "RemoveCacheOnDropDesc": "If disabled, remove cache on delete torrent.", - "RemoveRetrackers": "Remove retrackers", "RemoveViews": "Remove View States", - "ReplaceRetrackers": "Replace retrackers", "Resolution": "Resolution", - "RetrackersMode": "Retrackers Mode", "Save": "Save", "ScrollDown": "scroll down", "Season": "Season", "SelectSeason": "Select Season", - "Settings": "Settings", + "SettingsDialog": { + "AddRetrackers": "Add retrackers", + "CacheSize": "Cache Size", + "CacheSizeLabel": "Cache {{cacheSize}} MB", + "CacheSettings": "Cache Settings", + "ConnectionsLimit": "Connections Limit", + "DHT": "DHT (Distributed Hash Table)", + "DhtConnectionLimit": "DHT Connection Limit", + "DontAddRetrackers": "Don`t add retrackers", + "DownloadRateLimit": "Download Rate Limit (Kilobytes)", + "ForceEncrypt": "Force Encrypt Headers", + "PeersListenPort": "Peers Listen Port", + "PreloadBuffer": "Preload Buffer", + "ProMode": "PRO mode", + "ReaderReadAHead": "Reader Read Ahead (5-100%)", + "RemoveCacheOnDrop": "Remove Cache from Disk on Drop Torrent", + "RemoveCacheOnDropDesc": "If disabled, remove cache on delete torrent.", + "RemoveRetrackers": "Remove retrackers", + "ReplaceRetrackers": "Replace retrackers", + "RetrackersMode": "Retrackers Mode", + "Settings": "Settings", + "TorrentDisconnectTimeout": "Torrent Disconnect Timeout", + "TorrentsSavePath": "Torrents Save Path", + "Upload": "Upload (not recommended to disable)", + "UploadRateLimit": "Upload Rate Limit (Kilobytes)", + "UseDisk": "Use Disk for Cache", + "UseDiskDesc": "Better use external media on flash-based devices", + "Tabs": { + "Main": "Main", + "Additional": "Additional", + "AdditionalDisabled": "Additional (enable PRO mode)" + } + }, "Size": "Size", "SpecialThanks": "Special Thanks", "Speed": "Speed", "Support": "Support", - "TCP": "TCP (Transmission Control Protocol)", "ThanksToEveryone": "Thanks to everyone who tested and helped.", "TorrentAdded": "Added", "TorrentClosed": "Сlosed", "TorrentContent": "Torrent Content", "TorrentDetails": "Torrent Details", - "TorrentDisconnectTimeout": "Torrent Disconnect Timeout", "TorrentGettingInfo": "Getting Info", "TorrentInDb": "In DB", "TorrentPreload": "Preload", "TorrentSize": "Torrent size", - "TorrentsSavePath": "Torrents Save Path", "TorrentState": "Torrent State", "TorrentStatus": "Torrent Status", "TorrentWorking": "Active", "TurnOff": "Turn Off", - "Upload": "Upload (not recommended to disable)", "UploadFile": "Upload File", - "UploadRateLimit": "Upload Rate Limit (Kilobytes)", "UploadSpeed": "Upload speed", - "UPNP": "UPnP (Universal Plug and Play)", - "UseDisk": "Use Disk for Cache", - "UseDiskDesc": "Better use external media on flash-based devices", - "UTP": "μTP (Micro Transport Protocol)", "Viewed": "Viewed" } \ No newline at end of file diff --git a/web/src/locales/ru/translation.json b/web/src/locales/ru/translation.json index ee465bf..7c69941 100644 --- a/web/src/locales/ru/translation.json +++ b/web/src/locales/ru/translation.json @@ -20,17 +20,14 @@ }, "AddFromLink": "Добавить", "AddNewTorrent": "Добавить новый торрент", - "AddRetrackers": "Добавлять", "Buffer": "Предзагрузка / Кеш", "BufferNote": "Включите «Наполнять кеш перед началом воспроизведения» в настройках для показа заполнения кеша", "Cache": "Кеш", - "CacheSize": "Размер кеша (Мегабайты)", "Cancel": "Отмена", "Clear": "Очистить", "Close": "Закрыть", "CloseServer?": "Хотите выключить сервер?", "CloseServer": "Выкл. сервер", - "ConnectionsLimit": "Торрент-соединения (рек. 20-25)", "CopyHash": "Скопировать хеш", "CopyLink": "Копировать", "Data": "Данные", @@ -42,21 +39,15 @@ "header": "Заполнение кеша" }, "Details": "Инфо", - "DHT": "DHT (Distributed Hash Table)", - "DhtConnectionLimit": "Лимит подключений DHT", "Donate?": "Хотите поддержать проект?", "Donate": "Поддержка", - "DontAddRetrackers": "Ничего не делать", "DownloadPlaylist": "Скачать плейлист", - "DownloadRateLimit": "Ограничение скорости загрузки (Килобайты)", "DownloadSpeed": "Скорость загрузки", "Drop": "Сброс", "DropTorrent": "Сбросить торрент", "Edit": "Изменить", "EditTorrent": "Изменить торрент", - "EnableIPv6": "IPv6", "Episode": "Серия", - "ForceEncrypt": "Принудительное шифрование заголовков", "FromLatestFile": "C последнего файла", "Full": "Полный", "Host": "Хост", @@ -69,55 +60,69 @@ "OK": "OK", "OpenLink": "Открыть", "Peers": "Пиры", - "PeersListenPort": "Порт для входящих подключений", - "PEX": "PEX (Peer Exchange)", "PiecesCount": "Кол-во блоков", "PiecesLength": "Размер блока", "Preload": "Предзагр.", - "PreloadBuffer": "Наполнять кеш перед началом воспроизведения", "ProjectSource": "Сайт проекта", - "ReaderReadAHead": "Кеш предзагрузки (5-100%, рек. 95%)", "Releases": "Релизы", "RemoveAll": "Удалить все", - "RemoveCacheOnDrop": "Очищать кеш на диске при отключении торрента", - "RemoveCacheOnDropDesc": "Если отключено, кэш очищается при удалении торрента.", - "RemoveRetrackers": "Удалять", "RemoveViews": "Очистить просмотры", - "ReplaceRetrackers": "Заменять", "Resolution": "Разреш.", - "RetrackersMode": "Ретрекеры", "Save": "Сохранить", "ScrollDown": "прокрутить вниз", "Season": "Сезон", "SelectSeason": "Выбор сезона", - "Settings": "Настройки", + "SettingsDialog": { + "AddRetrackers": "Добавлять", + "CacheSize": "Размер кеша", + "CacheSizeLabel": "Кеш {{cacheSize}} МБ", + "CacheSettings": "Настройки кеша", + "ConnectionsLimit": "Торрент-соединения (рек. 20-25)", + "DHT": "DHT (Distributed Hash Table)", + "DhtConnectionLimit": "Лимит подключений DHT", + "DontAddRetrackers": "Ничего не делать", + "DownloadRateLimit": "Ограничение скорости загрузки (Килобайты)", + "ForceEncrypt": "Принудительное шифрование заголовков", + "PeersListenPort": "Порт для входящих подключений", + "PreloadBuffer": "Наполнять кеш перед началом воспроизведения", + "ProMode": "ПРО режим", + "ReaderReadAHead": "Кеш предзагрузки (5-100%, рек. 95%)", + "RemoveCacheOnDrop": "Очищать кеш на диске при отключении торрента", + "RemoveCacheOnDropDesc": "Если отключено, кэш очищается при удалении торрента.", + "RemoveRetrackers": "Удалять", + "ReplaceRetrackers": "Заменять", + "RetrackersMode": "Ретрекеры", + "Settings": "Настройки", + "TorrentDisconnectTimeout": "Тайм-аут отключения торрента (секунды)", + "TorrentsSavePath": "Путь хранения кеша", + "Upload": "Отдача (не рекомендуется отключать)", + "UploadRateLimit": "Ограничение скорости отдачи (Килобайты)", + "UseDisk": "Использовать диск для кеша", + "UseDiskDesc": "Рекомендуется использовать внешние носители на устройствах с flash-памятью", + "Tabs": { + "Main": "Основные", + "Additional": "Дополнительные", + "AdditionalDisabled": "Дополнительные (включите ПРО режим)" + } + }, "Size": "Размер", "SpecialThanks": "Отдельное спасибо", "Speed": "Скорость", "Support": "Поддержать", - "TCP": "TCP (Transmission Control Protocol)", "ThanksToEveryone": "Спасибо всем, кто тестировал и помогал!", "TorrentAdded": "Добавлен", "TorrentClosed": "Закрыт", "TorrentContent": "Содержимое торрента", "TorrentDetails": "Информация о торренте", - "TorrentDisconnectTimeout": "Тайм-аут отключения торрента (секунды)", "TorrentGettingInfo": "Получение инфо", "TorrentInDb": "Торрент в БД", "TorrentPreload": "Предзагрузка", "TorrentSize": "Размер торрента", - "TorrentsSavePath": "Путь хранения кеша", "TorrentState": "Данные торрента", "TorrentStatus": "Состояние торрента", "TorrentWorking": "Активен", "TurnOff": "Выключить", - "Upload": "Отдача (не рекомендуется отключать)", "UploadFile": "Загрузить файл", - "UploadRateLimit": "Ограничение скорости отдачи (Килобайты)", "UploadSpeed": "Скорость отдачи", - "UPNP": "UPnP (Universal Plug and Play)", - "UseDisk": "Использовать диск для кеша", - "UseDiskDesc": "Рекомендуется использовать внешние носители на устройствах с flash-памятью", - "UTP": "μTP (Micro Transport Protocol)", "Viewed": "Просм." } \ No newline at end of file From 7440e2ebd15bf7c278ffa9faa28ebf4ef4158d02 Mon Sep 17 00:00:00 2001 From: Daniel Shleifman Date: Mon, 5 Jul 2021 22:30:20 +0300 Subject: [PATCH 08/13] fixed cors problem when fetching posters --- web/src/components/Add/helpers.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/components/Add/helpers.js b/web/src/components/Add/helpers.js index f319786..c150d3f 100644 --- a/web/src/components/Add/helpers.js +++ b/web/src/components/Add/helpers.js @@ -24,7 +24,7 @@ export const checkImageURL = async url => { if (!url || !url.match(/.(jpg|jpeg|png|gif)$/i)) return false try { - await fetch(url) + await fetch(url, { mode: 'no-cors' }) return true } catch (e) { return false From 4a352059ecd6d5ce1593baf2e06e0d29022e8d9f Mon Sep 17 00:00:00 2001 From: Daniel Shleifman Date: Mon, 5 Jul 2021 23:47:04 +0300 Subject: [PATCH 09/13] translations updated --- .../components/Settings/SettingsDialog.jsx | 42 +++++++++++-------- web/src/components/Settings/style.js | 5 +++ web/src/locales/en/translation.json | 8 +++- web/src/locales/ru/translation.json | 8 +++- 4 files changed, 42 insertions(+), 21 deletions(-) diff --git a/web/src/components/Settings/SettingsDialog.jsx b/web/src/components/Settings/SettingsDialog.jsx index 4605911..b467880 100644 --- a/web/src/components/Settings/SettingsDialog.jsx +++ b/web/src/components/Settings/SettingsDialog.jsx @@ -43,8 +43,16 @@ import { import defaultSettings from './defaultSettings' import { a11yProps, TabPanel } from './tabComponents' -// {t('UseDisk')} -// {t('UseDiskDesc')} +const CacheStorageLocationLabel = ({ style }) => { + const { t } = useTranslation() + + return ( + + {t('SettingsDialog.CacheStorageLocation')} + {t('SettingsDialog.UseDiskDesc')} + + ) +} const SliderInput = ({ isProMode, @@ -213,24 +221,24 @@ export default function SettingsDialog({ handleClose }) {
- {100 - cachePercentage}% ({Math.round((cacheSize / 100) * (100 - cachePercentage))} МБ) + {100 - cachePercentage}% ({Math.round((cacheSize / 100) * (100 - cachePercentage))} MB)
-
От кеша будет оставаться позади воспроизводимого блока
+
{t('SettingsDialog.CacheBeforeReaderDesc')}
- {cachePercentage}% ({Math.round((cacheSize / 100) * cachePercentage)} МБ) + {cachePercentage}% ({Math.round((cacheSize / 100) * cachePercentage)} MB)
-
От кеша будет спереди от воспроизводимого блока
+
{t('SettingsDialog.CacheAfterReaderDesc')}
@@ -269,7 +277,7 @@ export default function SettingsDialog({ handleClose }) { {UseDisk ? (
- Место хранения кеша +
updateSettings({ UseDisk: false })}> @@ -277,7 +285,7 @@ export default function SettingsDialog({ handleClose }) { -
Оперативная память
+
{t('SettingsDialog.RAM')}
@@ -285,7 +293,7 @@ export default function SettingsDialog({ handleClose }) { -
Диск
+
{t('SettingsDialog.Disk')}
@@ -300,7 +308,9 @@ export default function SettingsDialog({ handleClose }) { } label={t('SettingsDialog.RemoveCacheOnDrop')} /> - {t('SettingsDialog.RemoveCacheOnDropDesc')} +
+ {t('SettingsDialog.RemoveCacheOnDropDesc')} +
) : ( - - Место хранения кеша - + -
Оперативная память
+
{t('SettingsDialog.RAM')}
updateSettings({ UseDisk: true })}> @@ -331,7 +339,7 @@ export default function SettingsDialog({ handleClose }) { -
Диск
+
{t('SettingsDialog.Disk')}
)} @@ -340,7 +348,7 @@ export default function SettingsDialog({ handleClose }) { - Дополнительные настройки + {t('SettingsDialog.AdditionalSettings')} } diff --git a/web/src/components/Settings/style.js b/web/src/components/Settings/style.js index 1609dd8..d305534 100644 --- a/web/src/components/Settings/style.js +++ b/web/src/components/Settings/style.js @@ -129,6 +129,11 @@ export const CacheStorageSelector = styled.div` export const SettingSectionLabel = styled.div` font-size: 25px; padding-bottom: 20px; + + small { + display: block; + font-size: 11px; + } ` export const PreloadCachePercentage = styled.div.attrs(({ value }) => ({ diff --git a/web/src/locales/en/translation.json b/web/src/locales/en/translation.json index da45444..7a8b82b 100644 --- a/web/src/locales/en/translation.json +++ b/web/src/locales/en/translation.json @@ -74,18 +74,23 @@ "SelectSeason": "Select Season", "SettingsDialog": { "AddRetrackers": "Add retrackers", + "AdditionalSettings": "Additional Settings", + "CacheBeforeReaderDesc": "From cache will be saved before currently played frame", + "CacheAfterReaderDesc": "From cache will be loaded after currently played frame", "CacheSize": "Cache Size", - "CacheSizeLabel": "Cache {{cacheSize}} MB", "CacheSettings": "Cache Settings", + "CacheStorageLocation": "Cache Storage Location", "ConnectionsLimit": "Connections Limit", "DHT": "DHT (Distributed Hash Table)", "DhtConnectionLimit": "DHT Connection Limit", + "Disk": "Disk", "DontAddRetrackers": "Don`t add retrackers", "DownloadRateLimit": "Download Rate Limit (Kilobytes)", "ForceEncrypt": "Force Encrypt Headers", "PeersListenPort": "Peers Listen Port", "PreloadBuffer": "Preload Buffer", "ProMode": "PRO mode", + "RAM": "RAM", "ReaderReadAHead": "Reader Read Ahead (5-100%)", "RemoveCacheOnDrop": "Remove Cache from Disk on Drop Torrent", "RemoveCacheOnDropDesc": "If disabled, remove cache on delete torrent.", @@ -97,7 +102,6 @@ "TorrentsSavePath": "Torrents Save Path", "Upload": "Upload (not recommended to disable)", "UploadRateLimit": "Upload Rate Limit (Kilobytes)", - "UseDisk": "Use Disk for Cache", "UseDiskDesc": "Better use external media on flash-based devices", "Tabs": { "Main": "Main", diff --git a/web/src/locales/ru/translation.json b/web/src/locales/ru/translation.json index 7c69941..040b3ec 100644 --- a/web/src/locales/ru/translation.json +++ b/web/src/locales/ru/translation.json @@ -74,18 +74,23 @@ "SelectSeason": "Выбор сезона", "SettingsDialog": { "AddRetrackers": "Добавлять", + "AdditionalSettings": "Дополнительные настройки", + "CacheBeforeReaderDesc": "От кеша будет оставаться позади воспроизводимого кадра", + "CacheAfterReaderDesc": "От кеша будет спереди от воспроизводимого кадра", "CacheSize": "Размер кеша", - "CacheSizeLabel": "Кеш {{cacheSize}} МБ", "CacheSettings": "Настройки кеша", + "CacheStorageLocation": "Место хранения кеша", "ConnectionsLimit": "Торрент-соединения (рек. 20-25)", "DHT": "DHT (Distributed Hash Table)", "DhtConnectionLimit": "Лимит подключений DHT", + "Disk": "Диск", "DontAddRetrackers": "Ничего не делать", "DownloadRateLimit": "Ограничение скорости загрузки (Килобайты)", "ForceEncrypt": "Принудительное шифрование заголовков", "PeersListenPort": "Порт для входящих подключений", "PreloadBuffer": "Наполнять кеш перед началом воспроизведения", "ProMode": "ПРО режим", + "RAM": "Оперативная память", "ReaderReadAHead": "Кеш предзагрузки (5-100%, рек. 95%)", "RemoveCacheOnDrop": "Очищать кеш на диске при отключении торрента", "RemoveCacheOnDropDesc": "Если отключено, кэш очищается при удалении торрента.", @@ -97,7 +102,6 @@ "TorrentsSavePath": "Путь хранения кеша", "Upload": "Отдача (не рекомендуется отключать)", "UploadRateLimit": "Ограничение скорости отдачи (Килобайты)", - "UseDisk": "Использовать диск для кеша", "UseDiskDesc": "Рекомендуется использовать внешние носители на устройствах с flash-памятью", "Tabs": { "Main": "Основные", From 59d0331c25b42a75efd198f3c8de1b6d92fe2f1f Mon Sep 17 00:00:00 2001 From: Daniel Shleifman Date: Tue, 6 Jul 2021 00:31:13 +0300 Subject: [PATCH 10/13] refactor --- .../Settings/PrimarySettingsComponent.jsx | 166 ++++++++ .../Settings/SecondarySettingsComponent.jsx | 142 +++++++ .../components/Settings/SettingsDialog.jsx | 369 +----------------- web/src/components/Settings/SliderInput.jsx | 49 +++ 4 files changed, 373 insertions(+), 353 deletions(-) create mode 100644 web/src/components/Settings/PrimarySettingsComponent.jsx create mode 100644 web/src/components/Settings/SecondarySettingsComponent.jsx create mode 100644 web/src/components/Settings/SliderInput.jsx diff --git a/web/src/components/Settings/PrimarySettingsComponent.jsx b/web/src/components/Settings/PrimarySettingsComponent.jsx new file mode 100644 index 0000000..4c51482 --- /dev/null +++ b/web/src/components/Settings/PrimarySettingsComponent.jsx @@ -0,0 +1,166 @@ +import { useTranslation } from 'react-i18next' +import { USBIcon, RAMIcon } from 'icons' +import { FormControlLabel, Switch } from '@material-ui/core' +import TextField from '@material-ui/core/TextField' + +import { + Divider, + PreloadCacheValue, + MainSettingsContent, + StorageButton, + StorageIconWrapper, + CacheStorageSelector, + SettingSectionLabel, + PreloadCachePercentage, + cacheBeforeReaderColor, + cacheAfterReaderColor, +} from './style' +import SliderInput from './SliderInput' + +const CacheStorageLocationLabel = ({ style }) => { + const { t } = useTranslation() + + return ( + + {t('SettingsDialog.CacheStorageLocation')} + {t('SettingsDialog.UseDiskDesc')} + + ) +} + +export default function PrimarySettingsComponent({ + settings, + inputForm, + cachePercentage, + cacheSize, + isProMode, + setCacheSize, + setCachePercentage, + updateSettings, +}) { + const { t } = useTranslation() + const { PreloadBuffer, UseDisk, TorrentsSavePath, RemoveCacheOnDrop } = settings || {} + + return ( + +
+ {t('SettingsDialog.CacheSettings')} + + + + +
+ {100 - cachePercentage}% ({Math.round((cacheSize / 100) * (100 - cachePercentage))} MB) +
+ +
{t('SettingsDialog.CacheBeforeReaderDesc')}
+
+ + +
+ {cachePercentage}% ({Math.round((cacheSize / 100) * cachePercentage)} MB) +
+ +
{t('SettingsDialog.CacheAfterReaderDesc')}
+
+ + + + setCacheSize(Math.round(value / 8) * 8)} + /> + + + + } + label={t('SettingsDialog.PreloadBuffer')} + /> +
+ + {UseDisk ? ( +
+ + +
+ updateSettings({ UseDisk: false })}> + + + + +
{t('SettingsDialog.RAM')}
+
+ + + + + + +
{t('SettingsDialog.Disk')}
+
+
+ + } + label={t('SettingsDialog.RemoveCacheOnDrop')} + /> +
+ {t('SettingsDialog.RemoveCacheOnDropDesc')} +
+ + +
+ ) : ( + + + + + + + + +
{t('SettingsDialog.RAM')}
+
+ + updateSettings({ UseDisk: true })}> + + + + +
{t('SettingsDialog.Disk')}
+
+
+ )} +
+ ) +} diff --git a/web/src/components/Settings/SecondarySettingsComponent.jsx b/web/src/components/Settings/SecondarySettingsComponent.jsx new file mode 100644 index 0000000..0d1fcd6 --- /dev/null +++ b/web/src/components/Settings/SecondarySettingsComponent.jsx @@ -0,0 +1,142 @@ +import { useTranslation } from 'react-i18next' +import TextField from '@material-ui/core/TextField' +import { FormControlLabel, InputLabel, Select, Switch } from '@material-ui/core' + +import { SecondarySettingsContent, SettingSectionLabel } from './style' + +export default function SecondarySettingsComponent({ settings, inputForm }) { + const { t } = useTranslation() + + const { + RetrackersMode, + TorrentDisconnectTimeout, + EnableIPv6, + ForceEncrypt, + DisableTCP, + DisableUTP, + DisableUPNP, + DisableDHT, + DisablePEX, + DisableUpload, + DownloadRateLimit, + UploadRateLimit, + ConnectionsLimit, + DhtConnectionLimit, + PeersListenPort, + } = settings || {} + + return ( + + {t('SettingsDialog.AdditionalSettings')} + + } + label='IPv6' + /> +
+ } + label='TCP (Transmission Control Protocol)' + /> +
+ } + label='μTP (Micro Transport Protocol)' + /> +
+ } + label='PEX (Peer Exchange)' + /> +
+ } + label={t('SettingsDialog.ForceEncrypt')} + /> +
+ +
+ +
+ } + label={t('SettingsDialog.DHT')} + /> +
+ +
+ +
+ } + label={t('SettingsDialog.Upload')} + /> +
+ +
+ +
+ } + label='UPnP (Universal Plug and Play)' + /> +
+ {t('SettingsDialog.RetrackersMode')} + +
+
+ ) +} diff --git a/web/src/components/Settings/SettingsDialog.jsx b/web/src/components/Settings/SettingsDialog.jsx index b467880..fdbcbe2 100644 --- a/web/src/components/Settings/SettingsDialog.jsx +++ b/web/src/components/Settings/SettingsDialog.jsx @@ -1,19 +1,8 @@ import axios from 'axios' import Dialog from '@material-ui/core/Dialog' -import TextField from '@material-ui/core/TextField' import Button from '@material-ui/core/Button' import Checkbox from '@material-ui/core/Checkbox' -import { - FormControlLabel, - Grid, - Input, - InputLabel, - Select, - Slider, - Switch, - useMediaQuery, - useTheme, -} from '@material-ui/core' +import { FormControlLabel, useMediaQuery, useTheme } from '@material-ui/core' import { settingsHost } from 'utils/Hosts' import { useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' @@ -22,85 +11,13 @@ import AppBar from '@material-ui/core/AppBar' import Tabs from '@material-ui/core/Tabs' import Tab from '@material-ui/core/Tab' import SwipeableViews from 'react-swipeable-views' -import { USBIcon, RAMIcon } from 'icons' import CircularProgress from '@material-ui/core/CircularProgress' -import { - FooterSection, - Divider, - PreloadCacheValue, - MainSettingsContent, - SecondarySettingsContent, - StorageButton, - StorageIconWrapper, - CacheStorageSelector, - SettingSectionLabel, - PreloadCachePercentage, - cacheBeforeReaderColor, - cacheAfterReaderColor, - Content, -} from './style' +import { FooterSection, Content } from './style' import defaultSettings from './defaultSettings' import { a11yProps, TabPanel } from './tabComponents' - -const CacheStorageLocationLabel = ({ style }) => { - const { t } = useTranslation() - - return ( - - {t('SettingsDialog.CacheStorageLocation')} - {t('SettingsDialog.UseDiskDesc')} - - ) -} - -const SliderInput = ({ - isProMode, - title, - value, - setValue, - sliderMin, - sliderMax, - inputMin, - inputMax, - step = 1, - onBlurCallback, -}) => { - const onBlur = ({ target: { value } }) => { - if (value < inputMin) return setValue(inputMin) - if (value > inputMax) return setValue(inputMax) - - onBlurCallback && onBlurCallback(value) - } - - const onInputChange = ({ target: { value } }) => setValue(value === '' ? '' : Number(value)) - const onSliderChange = (_, newValue) => setValue(newValue) - - return ( - <> -
{title}
- - - - - - - {isProMode && ( - - - - )} - - - ) -} +import PrimarySettingsComponent from './PrimarySettingsComponent' +import SecondarySettingsComponent from './SecondarySettingsComponent' export default function SettingsDialog({ handleClose }) { const { t } = useTranslation() @@ -149,29 +66,7 @@ export default function SettingsDialog({ handleClose }) { setSettings(sets) } - const { - CacheSize, - PreloadBuffer, - ReaderReadAHead, - RetrackersMode, - TorrentDisconnectTimeout, - EnableIPv6, - ForceEncrypt, - DisableTCP, - DisableUTP, - DisableUPNP, - DisableDHT, - DisablePEX, - DisableUpload, - DownloadRateLimit, - UploadRateLimit, - ConnectionsLimit, - DhtConnectionLimit, - PeersListenPort, - UseDisk, - TorrentsSavePath, - RemoveCacheOnDrop, - } = settings || {} + const { CacheSize, ReaderReadAHead } = settings || {} useEffect(() => { if (!CacheSize || !ReaderReadAHead) return @@ -215,252 +110,20 @@ export default function SettingsDialog({ handleClose }) { onChangeIndex={handleChangeIndex} > - -
- {t('SettingsDialog.CacheSettings')} - - - - -
- {100 - cachePercentage}% ({Math.round((cacheSize / 100) * (100 - cachePercentage))} MB) -
- -
{t('SettingsDialog.CacheBeforeReaderDesc')}
-
- - -
- {cachePercentage}% ({Math.round((cacheSize / 100) * cachePercentage)} MB) -
- -
{t('SettingsDialog.CacheAfterReaderDesc')}
-
- - - - setCacheSize(Math.round(value / 8) * 8)} - /> - - - - - } - label={t('SettingsDialog.PreloadBuffer')} - /> -
- - {UseDisk ? ( -
- - -
- updateSettings({ UseDisk: false })}> - - - - -
{t('SettingsDialog.RAM')}
-
- - - - - - -
{t('SettingsDialog.Disk')}
-
-
- - - } - label={t('SettingsDialog.RemoveCacheOnDrop')} - /> -
- {t('SettingsDialog.RemoveCacheOnDropDesc')} -
- - -
- ) : ( - - - - - - - - -
{t('SettingsDialog.RAM')}
-
- - updateSettings({ UseDisk: true })}> - - - - -
{t('SettingsDialog.Disk')}
-
-
- )} -
+
- - {t('SettingsDialog.AdditionalSettings')} - - } - label='IPv6' - /> -
- } - label='TCP (Transmission Control Protocol)' - /> -
- } - label='μTP (Micro Transport Protocol)' - /> -
- } - label='PEX (Peer Exchange)' - /> -
- } - label={t('SettingsDialog.ForceEncrypt')} - /> -
- -
- -
- } - label={t('SettingsDialog.DHT')} - /> -
- -
- -
- - } - label={t('SettingsDialog.Upload')} - /> -
- -
- -
- } - label='UPnP (Universal Plug and Play)' - /> -
- {t('SettingsDialog.RetrackersMode')} - -
-
+
diff --git a/web/src/components/Settings/SliderInput.jsx b/web/src/components/Settings/SliderInput.jsx new file mode 100644 index 0000000..a4d987e --- /dev/null +++ b/web/src/components/Settings/SliderInput.jsx @@ -0,0 +1,49 @@ +import { Grid, Input, Slider } from '@material-ui/core' + +export default function SliderInput({ + isProMode, + title, + value, + setValue, + sliderMin, + sliderMax, + inputMin, + inputMax, + step = 1, + onBlurCallback, +}) { + const onBlur = ({ target: { value } }) => { + if (value < inputMin) return setValue(inputMin) + if (value > inputMax) return setValue(inputMax) + + onBlurCallback && onBlurCallback(value) + } + + const onInputChange = ({ target: { value } }) => setValue(value === '' ? '' : Number(value)) + const onSliderChange = (_, newValue) => setValue(newValue) + + return ( + <> +
{title}
+ + + + + + + {isProMode && ( + + + + )} + + + ) +} From b683d627f291f5551241a99649535192afd51207 Mon Sep 17 00:00:00 2001 From: Daniel Shleifman Date: Tue, 6 Jul 2021 14:23:19 +0300 Subject: [PATCH 11/13] adaptive design added --- .../components/Settings/SettingsDialog.jsx | 72 +++++++++---------- web/src/components/Settings/style.js | 37 +++++++--- web/src/locales/en/translation.json | 1 + web/src/locales/ru/translation.json | 1 + 4 files changed, 66 insertions(+), 45 deletions(-) diff --git a/web/src/components/Settings/SettingsDialog.jsx b/web/src/components/Settings/SettingsDialog.jsx index fdbcbe2..0b4bd97 100644 --- a/web/src/components/Settings/SettingsDialog.jsx +++ b/web/src/components/Settings/SettingsDialog.jsx @@ -6,14 +6,13 @@ import { FormControlLabel, useMediaQuery, useTheme } from '@material-ui/core' import { settingsHost } from 'utils/Hosts' import { useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' -import { Header } from 'style/DialogStyles' import AppBar from '@material-ui/core/AppBar' import Tabs from '@material-ui/core/Tabs' import Tab from '@material-ui/core/Tab' import SwipeableViews from 'react-swipeable-views' import CircularProgress from '@material-ui/core/CircularProgress' -import { FooterSection, Content } from './style' +import { SettingsHeader, FooterSection, Content } from './style' import defaultSettings from './defaultSettings' import { a11yProps, TabPanel } from './tabComponents' import PrimarySettingsComponent from './PrimarySettingsComponent' @@ -81,7 +80,23 @@ export default function SettingsDialog({ handleClose }) { return ( -
{t('SettingsDialog.Settings')}
+ +
{t('SettingsDialog.Settings')}
+ { + setIsProMode(checked) + localStorage.setItem('isProMode', checked) + if (!checked) setSelectedTab(0) + }} + style={{ color: 'white' }} + /> + } + label={t('SettingsDialog.ProMode')} + /> +
- { - setIsProMode(checked) - localStorage.setItem('isProMode', checked) - if (!checked) setSelectedTab(0) - }} - color='primary' - /> - } - label={t('SettingsDialog.ProMode')} - /> + -
- + - - - -
+
) diff --git a/web/src/components/Settings/style.js b/web/src/components/Settings/style.js index d305534..952bc67 100644 --- a/web/src/components/Settings/style.js +++ b/web/src/components/Settings/style.js @@ -1,18 +1,33 @@ import styled, { css } from 'styled-components' import { mainColors } from 'style/colors' +import { Header } from 'style/DialogStyles' export const cacheBeforeReaderColor = '#b3dfc9' export const cacheAfterReaderColor = mainColors.light.primary -export const FooterSection = styled.div` - padding: 20px; - display: flex; +export const SettingsHeader = styled(Header)` + display: grid; + grid-auto-flow: column; align-items: center; justify-content: space-between; + + @media (max-width: 340px) { + grid-auto-flow: row; + } +` + +export const FooterSection = styled.div` + padding: 20px; + display: grid; + grid-auto-flow: column; + justify-content: end; + gap: 10px; + align-items: center; background: #e8e5eb; - > :last-child > :not(:last-child) { - margin-right: 10px; + @media (max-width: 500px) { + grid-auto-flow: row; + justify-content: stretch; } ` export const Divider = styled.div` @@ -24,11 +39,12 @@ export const Divider = styled.div` export const Content = styled.div` ${({ isLoading }) => css` background: #f1eff3; - min-height: 500px; overflow: auto; + flex: 1; ${isLoading && css` + min-height: 500px; display: grid; place-items: center; `} @@ -74,6 +90,7 @@ export const StorageButton = styled.div` ${({ small, selected }) => css` transition: 0.2s; cursor: default; + text-align: center; ${!selected && css` @@ -110,18 +127,22 @@ export const StorageIconWrapper = styled.div` svg { transform: rotate(-45deg) scale(0.75); } + + @media (max-width: 930px) { + width: ${small ? '50px' : '90px'}; + height: ${small ? '50px' : '90px'}; + } `} ` export const CacheStorageSelector = styled.div` display: grid; grid-template-rows: max-content 1fr; - grid-template-columns: 1fr 1fr; grid-template-areas: 'label label'; place-items: center; @media (max-width: 930px) { - grid-template-columns: repeat(2, max-content); + justify-content: start; column-gap: 30px; } ` diff --git a/web/src/locales/en/translation.json b/web/src/locales/en/translation.json index 7a8b82b..cb04085 100644 --- a/web/src/locales/en/translation.json +++ b/web/src/locales/en/translation.json @@ -97,6 +97,7 @@ "RemoveRetrackers": "Remove retrackers", "ReplaceRetrackers": "Replace retrackers", "RetrackersMode": "Retrackers Mode", + "ResetToDefault": "Reset to default", "Settings": "Settings", "TorrentDisconnectTimeout": "Torrent Disconnect Timeout", "TorrentsSavePath": "Torrents Save Path", diff --git a/web/src/locales/ru/translation.json b/web/src/locales/ru/translation.json index 040b3ec..31c9c13 100644 --- a/web/src/locales/ru/translation.json +++ b/web/src/locales/ru/translation.json @@ -97,6 +97,7 @@ "RemoveRetrackers": "Удалять", "ReplaceRetrackers": "Заменять", "RetrackersMode": "Ретрекеры", + "ResetToDefault": "Сбросить по умолчанию", "Settings": "Настройки", "TorrentDisconnectTimeout": "Тайм-аут отключения торрента (секунды)", "TorrentsSavePath": "Путь хранения кеша", From e09b72e53defcbfb4b6f28ea588ed9e7844ccda8 Mon Sep 17 00:00:00 2001 From: Daniel Shleifman Date: Tue, 6 Jul 2021 14:38:10 +0300 Subject: [PATCH 12/13] refactor --- web/src/components/Settings/SettingsDialog.jsx | 7 ++++++- web/src/components/Settings/style.js | 1 + web/src/locales/en/translation.json | 2 +- web/src/locales/ru/translation.json | 2 +- 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/web/src/components/Settings/SettingsDialog.jsx b/web/src/components/Settings/SettingsDialog.jsx index 0b4bd97..f1700b1 100644 --- a/web/src/components/Settings/SettingsDialog.jsx +++ b/web/src/components/Settings/SettingsDialog.jsx @@ -110,7 +110,12 @@ export default function SettingsDialog({ handleClose }) { +
{t('SettingsDialog.Tabs.Additional')}
+ {!isProMode &&
{t('SettingsDialog.Tabs.AdditionalDisabled')}
} + + } {...a11yProps(1)} /> diff --git a/web/src/components/Settings/style.js b/web/src/components/Settings/style.js index 952bc67..075c63c 100644 --- a/web/src/components/Settings/style.js +++ b/web/src/components/Settings/style.js @@ -107,6 +107,7 @@ export const StorageButton = styled.div` grid-template-columns: max-content 1fr; gap: 20px; align-items: center; + justify-items: start; margin-bottom: 20px; ` : css` diff --git a/web/src/locales/en/translation.json b/web/src/locales/en/translation.json index cb04085..0eeea6c 100644 --- a/web/src/locales/en/translation.json +++ b/web/src/locales/en/translation.json @@ -107,7 +107,7 @@ "Tabs": { "Main": "Main", "Additional": "Additional", - "AdditionalDisabled": "Additional (enable PRO mode)" + "AdditionalDisabled": "(enable PRO mode)" } }, "Size": "Size", diff --git a/web/src/locales/ru/translation.json b/web/src/locales/ru/translation.json index 31c9c13..4d4dc25 100644 --- a/web/src/locales/ru/translation.json +++ b/web/src/locales/ru/translation.json @@ -107,7 +107,7 @@ "Tabs": { "Main": "Основные", "Additional": "Дополнительные", - "AdditionalDisabled": "Дополнительные (включите ПРО режим)" + "AdditionalDisabled": "(включите ПРО режим)" } }, "Size": "Размер", From 3b8e334f9083421a018cea6762b7307ba573b179 Mon Sep 17 00:00:00 2001 From: Daniel Shleifman Date: Tue, 6 Jul 2021 15:44:20 +0300 Subject: [PATCH 13/13] colors fixed --- .../Settings/PrimarySettingsComponent.jsx | 6 ++- .../Settings/SecondarySettingsComponent.jsx | 16 ++++---- .../components/Settings/SettingsDialog.jsx | 6 +-- web/src/components/Settings/SliderInput.jsx | 9 ++++- web/src/components/Settings/style.js | 37 ++++++++++++------- web/src/style/colors.js | 8 ++++ 6 files changed, 55 insertions(+), 27 deletions(-) diff --git a/web/src/components/Settings/PrimarySettingsComponent.jsx b/web/src/components/Settings/PrimarySettingsComponent.jsx index 4c51482..643e6bf 100644 --- a/web/src/components/Settings/PrimarySettingsComponent.jsx +++ b/web/src/components/Settings/PrimarySettingsComponent.jsx @@ -95,7 +95,7 @@ export default function PrimarySettingsComponent({ /> } + control={} label={t('SettingsDialog.PreloadBuffer')} />
@@ -123,7 +123,9 @@ export default function PrimarySettingsComponent({
} + control={ + + } label={t('SettingsDialog.RemoveCacheOnDrop')} />
diff --git a/web/src/components/Settings/SecondarySettingsComponent.jsx b/web/src/components/Settings/SecondarySettingsComponent.jsx index 0d1fcd6..12b6550 100644 --- a/web/src/components/Settings/SecondarySettingsComponent.jsx +++ b/web/src/components/Settings/SecondarySettingsComponent.jsx @@ -30,27 +30,27 @@ export default function SecondarySettingsComponent({ settings, inputForm }) { {t('SettingsDialog.AdditionalSettings')} } + control={} label='IPv6' />
} + control={} label='TCP (Transmission Control Protocol)' />
} + control={} label='μTP (Micro Transport Protocol)' />
} + control={} label='PEX (Peer Exchange)' />
} + control={} label={t('SettingsDialog.ForceEncrypt')} />
@@ -75,7 +75,7 @@ export default function SecondarySettingsComponent({ settings, inputForm }) { />
} + control={} label={t('SettingsDialog.DHT')} />
@@ -100,7 +100,7 @@ export default function SecondarySettingsComponent({ settings, inputForm }) { />
} + control={} label={t('SettingsDialog.Upload')} />
@@ -125,7 +125,7 @@ export default function SecondarySettingsComponent({ settings, inputForm }) { />
} + control={} label='UPnP (Universal Plug and Play)' />
diff --git a/web/src/components/Settings/SettingsDialog.jsx b/web/src/components/Settings/SettingsDialog.jsx index f1700b1..5c3368a 100644 --- a/web/src/components/Settings/SettingsDialog.jsx +++ b/web/src/components/Settings/SettingsDialog.jsx @@ -102,8 +102,8 @@ export default function SettingsDialog({ handleClose }) { @@ -169,7 +169,7 @@ export default function SettingsDialog({ handleClose }) { {t('SettingsDialog.ResetToDefault')} - diff --git a/web/src/components/Settings/SliderInput.jsx b/web/src/components/Settings/SliderInput.jsx index a4d987e..5dc0a1c 100644 --- a/web/src/components/Settings/SliderInput.jsx +++ b/web/src/components/Settings/SliderInput.jsx @@ -28,7 +28,14 @@ export default function SliderInput({ - + {isProMode && ( diff --git a/web/src/components/Settings/style.js b/web/src/components/Settings/style.js index 075c63c..ab1bea4 100644 --- a/web/src/components/Settings/style.js +++ b/web/src/components/Settings/style.js @@ -17,18 +17,24 @@ export const SettingsHeader = styled(Header)` ` export const FooterSection = styled.div` - padding: 20px; - display: grid; - grid-auto-flow: column; - justify-content: end; - gap: 10px; - align-items: center; - background: #e8e5eb; + ${({ + theme: { + settingsDialog: { footerBG }, + }, + }) => css` + padding: 20px; + display: grid; + grid-auto-flow: column; + justify-content: end; + gap: 10px; + align-items: center; + background: ${footerBG}; - @media (max-width: 500px) { - grid-auto-flow: row; - justify-content: stretch; - } + @media (max-width: 500px) { + grid-auto-flow: row; + justify-content: stretch; + } + `} ` export const Divider = styled.div` height: 1px; @@ -37,8 +43,13 @@ export const Divider = styled.div` ` export const Content = styled.div` - ${({ isLoading }) => css` - background: #f1eff3; + ${({ + isLoading, + theme: { + settingsDialog: { contentBG }, + }, + }) => css` + background: ${contentBG}; overflow: auto; flex: 1; diff --git a/web/src/style/colors.js b/web/src/style/colors.js index 1a009a0..d78eeae 100644 --- a/web/src/style/colors.js +++ b/web/src/style/colors.js @@ -47,6 +47,10 @@ export const themeColors = { defaultSecondaryColor: '#00a383', defaultTertiaryColor: '#03aa89', }, + settingsDialog: { + contentBG: '#f1eff3', + footerBG: '#f1eff3', + }, }, dark: { app: { @@ -94,6 +98,10 @@ export const themeColors = { defaultSecondaryColor: rgba('#545a5e', 0.9), defaultTertiaryColor: '#545a5e', }, + settingsDialog: { + contentBG: '#5A6166', + footerBG: '#323637', + }, }, }