This commit is contained in:
Daniel Shleifman
2021-07-02 17:56:32 +03:00
parent bc717647ea
commit dbfc1db5d2
4 changed files with 533 additions and 459 deletions

View File

@@ -28,7 +28,7 @@ const Sidebar = ({ isDrawerOpen, setIsDonationDialogOpen, isOffline, isLoading }
<Divider />
<List>
<SettingsDialog />
<SettingsDialog isOffline={isOffline} isLoading={isLoading} />
<AboutDialog />

View File

@@ -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 }) => (
</div>
)
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 }) {
<Dialog open onClose={handleClose} fullScreen={fullScreen} fullWidth maxWidth='md'>
<Header>{t('Settings')}</Header>
<>
<AppBar position='static' color='default'>
<Tabs
value={selectedTab}
onChange={handleChange}
indicatorColor='primary'
textColor='primary'
variant='fullWidth'
{settings ? (
<>
<AppBar position='static' color='default'>
<Tabs
value={selectedTab}
onChange={handleChange}
indicatorColor='primary'
textColor='primary'
variant='fullWidth'
>
<Tab label='Основные' {...a11yProps(0)} />
<Tab
disabled={!isProMode}
label={isProMode ? 'Дополнительные' : 'Дополнительные (включите pro mode)'}
{...a11yProps(1)}
/>
</Tabs>
</AppBar>
<SwipeableViews
axis={direction === 'rtl' ? 'x-reverse' : 'x'}
index={selectedTab}
onChangeIndex={handleChangeIndex}
>
<Tab label='Основные' {...a11yProps(0)} />
<TabPanel value={selectedTab} index={0} dir={direction}>
<MainSettingsContent>
<CacheSizeSettings>
<SettingSectionLabel>Настройки кеша</SettingSectionLabel>
<Tab
disabled={!isProMode}
label={isProMode ? 'Дополнительные' : 'Дополнительные (включите pro mode)'}
{...a11yProps(1)}
/>
</Tabs>
</AppBar>
<SwipeableViews
axis={direction === 'rtl' ? 'x-reverse' : 'x'}
index={selectedTab}
onChangeIndex={handleChangeIndex}
>
<TabPanel value={selectedTab} index={0} dir={direction}>
<MainSettingsContent>
<CacheSizeSettings>
<SettingSectionLabel>Настройки кеша</SettingSectionLabel>
<PreloadCachePercentage
value={100 - cachePercentage}
label={`Кеш ${cacheSize} МБ`}
isPreloadEnabled={PreloadBuffer}
/>
<PreloadCacheValue color='orangered'>
<div>
{100 - cachePercentage}% ({Math.round((cacheSize / 100) * (100 - cachePercentage))} МБ)
</div>
<div>От кеша будет оставаться позади воспроизводимого блока</div>
</PreloadCacheValue>
<PreloadCacheValue color='lightblue'>
<div>
{cachePercentage}% ({Math.round((cacheSize / 100) * cachePercentage)} МБ)
</div>
<div>От кеша будет спереди от воспроизводимого блока</div>
</PreloadCacheValue>
<Divider />
<SettingSection>
<SettingLabel>Размер кеша</SettingLabel>
<Grid container spacing={2} alignItems='center'>
<Grid item xs>
<Slider min={32} max={1024} value={cacheSize} onChange={handleSliderChange} step={8} />
</Grid>
{isProMode && (
<Grid item>
<Input
value={cacheSize}
margin='dense'
onChange={handleInputChange}
onBlur={handleBlur}
style={{ width: '65px' }}
inputProps={{
step: 8,
min: 32,
max: 20000,
type: 'number',
}}
/>
</Grid>
)}
</Grid>
</SettingSection>
<SettingSection>
<SettingLabel>Кеш предзагрузки</SettingLabel>
<Grid container spacing={2} alignItems='center'>
<Grid item xs>
<Slider
min={40}
max={95}
value={cachePercentage}
onChange={(_, newValue) => setCachePercentage(newValue)}
/>
</Grid>
{isProMode && (
<Grid item>
<Input
value={cachePercentage}
margin='dense'
onChange={({ target: { value } }) => 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',
}}
/>
</Grid>
)}
</Grid>
</SettingSection>
<SettingSection>
<FormControlLabel
control={<Switch checked={PreloadBuffer} onChange={inputForm} id='PreloadBuffer' color='primary' />}
label={t('PreloadBuffer')}
<PreloadCachePercentage
value={100 - cachePercentage}
label={`Кеш ${cacheSize} МБ`}
isPreloadEnabled={PreloadBuffer}
/>
</SettingSection>
</CacheSizeSettings>
{isRamSelected ? (
<CacheStorageSelector>
<SettingSectionLabel style={{ placeSelf: 'start', gridArea: 'label' }}>
Место хранения кеша
</SettingSectionLabel>
<PreloadCacheValue color={cacheBeforeReaderColor}>
<div>
{100 - cachePercentage}% ({Math.round((cacheSize / 100) * (100 - cachePercentage))} МБ)
</div>
<div>От кеша будет оставаться позади воспроизводимого блока</div>
</PreloadCacheValue>
<StorageButton>
<StorageIconWrapper selected>
<RAMIcon />
</StorageIconWrapper>
<div>Оперативная память</div>
</StorageButton>
<PreloadCacheValue color={cacheAfterReaderColor}>
<div>
{cachePercentage}% ({Math.round((cacheSize / 100) * cachePercentage)} МБ)
</div>
<div>От кеша будет спереди от воспроизводимого блока</div>
</PreloadCacheValue>
<StorageButton>
<StorageIconWrapper onClick={() => setIsRamSelected(false)}>
<USBIcon />
</StorageIconWrapper>
<div>Диск</div>
</StorageButton>
</CacheStorageSelector>
) : (
<CacheStorageSettings>
<SettingSectionLabel>Место хранения кеша</SettingSectionLabel>
<Divider />
<ButtonGroup fullWidth color='primary'>
<Button onClick={() => setIsRamSelected(true)}>
<div>
<RAMIcon width='50px' />
<div>Оперативная память</div>
</div>
</Button>
<SettingSection>
<SettingLabel>Размер кеша</SettingLabel>
<Button variant='contained'>
<div>
<USBIcon width='50px' color='white' />
<div>Диск</div>
</div>
</Button>
</ButtonGroup>
<Grid container spacing={2} alignItems='center'>
<Grid item xs>
<Slider
min={32}
max={1024}
value={cacheSize}
onChange={(_, newValue) => setCacheSize(newValue)}
step={8}
/>
</Grid>
{isProMode && (
<Grid item>
<Input
value={cacheSize}
margin='dense'
onChange={handleInputChange}
onBlur={handleBlur}
style={{ width: '65px' }}
inputProps={{ step: 8, min: 32, max: 20000, type: 'number' }}
/>
</Grid>
)}
</Grid>
</SettingSection>
<SettingSection>
<SettingLabel>Кеш предзагрузки</SettingLabel>
<Grid container spacing={2} alignItems='center'>
<Grid item xs>
<Slider
min={40}
max={95}
value={cachePercentage}
onChange={(_, newValue) => setCachePercentage(newValue)}
/>
</Grid>
{isProMode && (
<Grid item>
<Input
value={cachePercentage}
margin='dense'
onChange={({ target: { value } }) => 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' }}
/>
</Grid>
)}
</Grid>
</SettingSection>
<FormControlLabel
control={
<Switch checked={RemoveCacheOnDrop} onChange={inputForm} id='RemoveCacheOnDrop' color='primary' />
<Switch checked={!!PreloadBuffer} onChange={inputForm} id='PreloadBuffer' color='primary' />
}
label={t('RemoveCacheOnDrop')}
label={t('PreloadBuffer')}
/>
<small>{t('RemoveCacheOnDropDesc')}</small>
<TextField
onChange={inputForm}
margin='dense'
id='TorrentsSavePath'
label={t('TorrentsSavePath')}
value={TorrentsSavePath}
type='url'
fullWidth
/>
</CacheStorageSettings>
)}
</MainSettingsContent>
</TabPanel>
</CacheSizeSettings>
<TabPanel value={selectedTab} index={1} dir={direction}>
<SecondarySettingsContent>
<SettingSectionLabel>Дополнительные настройки</SettingSectionLabel>
{UseDisk ? (
<CacheStorageSettings>
<SettingSectionLabel>Место хранения кеша</SettingSectionLabel>
<FormControlLabel
control={<Switch checked={EnableIPv6} onChange={inputForm} id='EnableIPv6' color='primary' />}
label={t('EnableIPv6')}
/>
<br />
<FormControlLabel
control={<Switch checked={!DisableTCP} onChange={inputForm} id='DisableTCP' color='primary' />}
label={t('TCP')}
/>
<br />
<FormControlLabel
control={<Switch checked={!DisableUTP} onChange={inputForm} id='DisableUTP' color='primary' />}
label={t('UTP')}
/>
<br />
<FormControlLabel
control={<Switch checked={!DisablePEX} onChange={inputForm} id='DisablePEX' color='primary' />}
label={t('PEX')}
/>
<br />
<FormControlLabel
control={<Switch checked={ForceEncrypt} onChange={inputForm} id='ForceEncrypt' color='primary' />}
label={t('ForceEncrypt')}
/>
<br />
<TextField
onChange={inputForm}
margin='dense'
id='TorrentDisconnectTimeout'
label={t('TorrentDisconnectTimeout')}
value={TorrentDisconnectTimeout}
type='number'
fullWidth
/>
<br />
<TextField
onChange={inputForm}
margin='dense'
id='ConnectionsLimit'
label={t('ConnectionsLimit')}
value={ConnectionsLimit}
type='number'
fullWidth
/>
<br />
<FormControlLabel
control={<Switch checked={!DisableDHT} onChange={inputForm} id='DisableDHT' color='primary' />}
label={t('DHT')}
/>
<br />
<TextField
onChange={inputForm}
margin='dense'
id='DhtConnectionLimit'
label={t('DhtConnectionLimit')}
value={DhtConnectionLimit}
type='number'
fullWidth
/>
<br />
<TextField
onChange={inputForm}
margin='dense'
id='DownloadRateLimit'
label={t('DownloadRateLimit')}
value={DownloadRateLimit}
type='number'
fullWidth
/>
<br />
<FormControlLabel
control={<Switch checked={!DisableUpload} onChange={inputForm} id='DisableUpload' color='primary' />}
label={t('Upload')}
/>
<br />
<TextField
onChange={inputForm}
margin='dense'
id='UploadRateLimit'
label={t('UploadRateLimit')}
value={UploadRateLimit}
type='number'
fullWidth
/>
<br />
<TextField
onChange={inputForm}
margin='dense'
id='PeersListenPort'
label={t('PeersListenPort')}
value={PeersListenPort}
type='number'
fullWidth
/>
<br />
<FormControlLabel
control={<Switch checked={!DisableUPNP} onChange={inputForm} id='DisableUPNP' color='primary' />}
label={t('UPNP')}
/>
<br />
<InputLabel htmlFor='RetrackersMode'>{t('RetrackersMode')}</InputLabel>
<Select onChange={inputForm} type='number' native id='RetrackersMode' value={RetrackersMode}>
<option value={0}>{t('DontAddRetrackers')}</option>
<option value={1}>{t('AddRetrackers')}</option>
<option value={2}>{t('RemoveRetrackers')}</option>
<option value={3}>{t('ReplaceRetrackers')}</option>
</Select>
<br />
</SecondarySettingsContent>
</TabPanel>
</SwipeableViews>
</>
<div style={{ display: 'grid', gridAutoFlow: 'column' }}>
<StorageButton small onClick={() => updateSettings({ UseDisk: false })}>
<StorageIconWrapper small>
<RAMIcon color='#323637' />
</StorageIconWrapper>
<div>Оперативная память</div>
</StorageButton>
<StorageButton small selected>
<StorageIconWrapper small selected>
<USBIcon color='#dee3e5' />
</StorageIconWrapper>
<div>Диск</div>
</StorageButton>
</div>
<FormControlLabel
control={
<Switch
checked={RemoveCacheOnDrop}
onChange={inputForm}
id='RemoveCacheOnDrop'
color='primary'
/>
}
label={t('RemoveCacheOnDrop')}
/>
<small>{t('RemoveCacheOnDropDesc')}</small>
<TextField
onChange={inputForm}
margin='dense'
id='TorrentsSavePath'
label={t('TorrentsSavePath')}
value={TorrentsSavePath}
type='url'
fullWidth
/>
</CacheStorageSettings>
) : (
<CacheStorageSelector>
<SettingSectionLabel style={{ placeSelf: 'start', gridArea: 'label' }}>
Место хранения кеша
</SettingSectionLabel>
<StorageButton selected>
<StorageIconWrapper selected>
<RAMIcon color='#dee3e5' />
</StorageIconWrapper>
<div>Оперативная память</div>
</StorageButton>
<StorageButton onClick={() => updateSettings({ UseDisk: true })}>
<StorageIconWrapper>
<USBIcon color='#323637' />
</StorageIconWrapper>
<div>Диск</div>
</StorageButton>
</CacheStorageSelector>
)}
</MainSettingsContent>
</TabPanel>
<TabPanel value={selectedTab} index={1} dir={direction}>
<SecondarySettingsContent>
<SettingSectionLabel>Дополнительные настройки</SettingSectionLabel>
<FormControlLabel
control={<Switch checked={EnableIPv6} onChange={inputForm} id='EnableIPv6' color='primary' />}
label={t('EnableIPv6')}
/>
<br />
<FormControlLabel
control={<Switch checked={!DisableTCP} onChange={inputForm} id='DisableTCP' color='primary' />}
label={t('TCP')}
/>
<br />
<FormControlLabel
control={<Switch checked={!DisableUTP} onChange={inputForm} id='DisableUTP' color='primary' />}
label={t('UTP')}
/>
<br />
<FormControlLabel
control={<Switch checked={!DisablePEX} onChange={inputForm} id='DisablePEX' color='primary' />}
label={t('PEX')}
/>
<br />
<FormControlLabel
control={<Switch checked={ForceEncrypt} onChange={inputForm} id='ForceEncrypt' color='primary' />}
label={t('ForceEncrypt')}
/>
<br />
<TextField
onChange={inputForm}
margin='dense'
id='TorrentDisconnectTimeout'
label={t('TorrentDisconnectTimeout')}
value={TorrentDisconnectTimeout}
type='number'
fullWidth
/>
<br />
<TextField
onChange={inputForm}
margin='dense'
id='ConnectionsLimit'
label={t('ConnectionsLimit')}
value={ConnectionsLimit}
type='number'
fullWidth
/>
<br />
<FormControlLabel
control={<Switch checked={!DisableDHT} onChange={inputForm} id='DisableDHT' color='primary' />}
label={t('DHT')}
/>
<br />
<TextField
onChange={inputForm}
margin='dense'
id='DhtConnectionLimit'
label={t('DhtConnectionLimit')}
value={DhtConnectionLimit}
type='number'
fullWidth
/>
<br />
<TextField
onChange={inputForm}
margin='dense'
id='DownloadRateLimit'
label={t('DownloadRateLimit')}
value={DownloadRateLimit}
type='number'
fullWidth
/>
<br />
<FormControlLabel
control={<Switch checked={!DisableUpload} onChange={inputForm} id='DisableUpload' color='primary' />}
label={t('Upload')}
/>
<br />
<TextField
onChange={inputForm}
margin='dense'
id='UploadRateLimit'
label={t('UploadRateLimit')}
value={UploadRateLimit}
type='number'
fullWidth
/>
<br />
<TextField
onChange={inputForm}
margin='dense'
id='PeersListenPort'
label={t('PeersListenPort')}
value={PeersListenPort}
type='number'
fullWidth
/>
<br />
<FormControlLabel
control={<Switch checked={!DisableUPNP} onChange={inputForm} id='DisableUPNP' color='primary' />}
label={t('UPNP')}
/>
<br />
<InputLabel htmlFor='RetrackersMode'>{t('RetrackersMode')}</InputLabel>
<Select onChange={inputForm} type='number' native id='RetrackersMode' value={RetrackersMode}>
<option value={0}>{t('DontAddRetrackers')}</option>
<option value={1}>{t('AddRetrackers')}</option>
<option value={2}>{t('RemoveRetrackers')}</option>
<option value={3}>{t('ReplaceRetrackers')}</option>
</Select>
<br />
</SecondarySettingsContent>
</TabPanel>
</SwipeableViews>
</>
) : (
'loading...'
)}
{/* <DialogTitle id='form-dialog-title'>{t('Settings')}</DialogTitle>
<DialogContent>
<TextField
@@ -805,6 +706,18 @@ export default function SettingsDialog({ handleClose }) {
{t('Cancel')}
</Button>
<Button
onClick={() => {
setCacheSize(defaultSettings.CacheSize)
setCachePercentage(defaultSettings.ReaderReadAHead)
updateSettings(defaultSettings)
}}
color='secondary'
variant='outlined'
>
Reset to default
</Button>
<Button variant='contained' onClick={handleSave} color='primary'>
{t('Save')}
</Button>

View File

@@ -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 (
<div>
<ListItem button onClick={handleClickOpen}>
<ListItem disabled={isOffline || isLoading} button onClick={handleClickOpen}>
<ListItemIcon>
<SettingsIcon />
</ListItemIcon>

View File

@@ -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;
}
`}
`}
`