added dark theme

This commit is contained in:
Daniel Shleifman
2021-06-26 21:31:43 +03:00
parent d5458a112e
commit 72ff729ee8
24 changed files with 950 additions and 587 deletions

View File

@@ -13,6 +13,7 @@
"material-ui-image": "^3.3.2", "material-ui-image": "^3.3.2",
"parse-torrent": "^9.1.3", "parse-torrent": "^9.1.3",
"parse-torrent-title": "^1.3.0", "parse-torrent-title": "^1.3.0",
"polished": "^4.1.3",
"react": "^17.0.2", "react": "^17.0.2",
"react-copy-to-clipboard": "^5.0.3", "react-copy-to-clipboard": "^5.0.3",
"react-div-100vh": "^0.6.0", "react-div-100vh": "^0.6.0",

View File

@@ -11,13 +11,10 @@ import ListItemIcon from '@material-ui/core/ListItemIcon'
import ListItemText from '@material-ui/core/ListItemText' import ListItemText from '@material-ui/core/ListItemText'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { echoHost } from 'utils/Hosts' import { echoHost } from 'utils/Hosts'
import { ThemeProvider } from '@material-ui/core/styles' import { ThemeProvider, useTheme } from '@material-ui/core/styles'
import { mainColors } from 'style/colors'
import { lightTheme } from '../style/materialUISetup' import { lightTheme } from '../style/materialUISetup'
const { primary } = mainColors
export default function AboutDialog() { export default function AboutDialog() {
const { t } = useTranslation() const { t } = useTranslation()
const [open, setOpen] = useState(false) const [open, setOpen] = useState(false)
@@ -26,6 +23,8 @@ export default function AboutDialog() {
axios.get(echoHost()).then(({ data }) => setTorrServerVersion(data)) axios.get(echoHost()).then(({ data }) => setTorrServerVersion(data))
}, []) }, [])
const primary = useTheme().palette.primary.main
return ( return (
<div> <div>
<ListItem button key='Settings' onClick={() => setOpen(true)}> <ListItem button key='Settings' onClick={() => setOpen(true)}>

View File

@@ -12,8 +12,6 @@ import usePreviousState from 'utils/usePreviousState'
import { useQuery } from 'react-query' import { useQuery } from 'react-query'
import { getTorrents } from 'utils/Utils' import { getTorrents } from 'utils/Utils'
import parseTorrent from 'parse-torrent' import parseTorrent from 'parse-torrent'
import { ThemeProvider } from '@material-ui/core/styles'
import { lightTheme } from 'style/materialUISetup'
import { checkImageURL, getMoviePosters, chechTorrentSource, parseTorrentTitle } from './helpers' import { checkImageURL, getMoviePosters, chechTorrentSource, parseTorrentTitle } from './helpers'
import { ButtonWrapper, Content, Header } from './style' import { ButtonWrapper, Content, Header } from './style'
@@ -221,7 +219,6 @@ export default function AddDialog({
} }
return ( return (
<ThemeProvider theme={lightTheme}>
<Dialog <Dialog
open open
onClose={handleClose} onClose={handleClose}
@@ -286,6 +283,5 @@ export default function AddDialog({
</Button> </Button>
</ButtonWrapper> </ButtonWrapper>
</Dialog> </Dialog>
</ThemeProvider>
) )
} }

View File

@@ -1,6 +1,6 @@
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { NoImageIcon } from 'icons' import { NoImageIcon } from 'icons'
import { IconButton, InputAdornment, TextField } from '@material-ui/core' import { IconButton, InputAdornment, TextField, useTheme } from '@material-ui/core'
import { CheckBox as CheckBoxIcon } from '@material-ui/icons' import { CheckBox as CheckBoxIcon } from '@material-ui/icons'
import { import {
@@ -41,6 +41,7 @@ export default function RightSideComponent({
isEditMode, isEditMode,
}) { }) {
const { t } = useTranslation() const { t } = useTranslation()
const primary = useTheme().palette.primary.main
const handleTitleChange = ({ target: { value } }) => setTitle(value) const handleTitleChange = ({ target: { value } }) => setTitle(value)
const handlePosterUrlChange = ({ target: { value } }) => { const handlePosterUrlChange = ({ target: { value } }) => {
@@ -91,7 +92,7 @@ export default function RightSideComponent({
setIsUserInteractedWithPoster(false) setIsUserInteractedWithPoster(false)
}} }}
> >
<CheckBoxIcon style={{ color: isCustomTitleEnabled ? 'green' : 'gray' }} /> <CheckBoxIcon style={{ color: isCustomTitleEnabled ? primary : 'gray' }} />
</IconButton> </IconButton>
</InputAdornment> </InputAdornment>
), ),

View File

@@ -15,14 +15,20 @@ export const Header = styled.div`
` `
export const Content = styled.div` export const Content = styled.div`
${({ isEditMode }) => css` ${({
isEditMode,
theme: {
addDialog: { gradientStartColor, gradientEndColor, fontColor },
},
}) => css`
height: 550px; height: 550px;
background: linear-gradient(145deg, #e4f6ed, #b5dec9); background: linear-gradient(145deg, ${gradientStartColor}, ${gradientEndColor});
flex: 1; flex: 1;
display: grid; display: grid;
grid-template-columns: repeat(${isEditMode ? '1' : '2'}, 1fr); grid-template-columns: repeat(${isEditMode ? '1' : '2'}, 1fr);
border-bottom: 1px solid rgba(0, 0, 0, 0.12); border-bottom: 1px solid rgba(0, 0, 0, 0.12);
overflow: auto; overflow: auto;
color: ${fontColor};
@media (max-width: 540px) { @media (max-width: 540px) {
${'' /* Just for bug fixing on small screens */} ${'' /* Just for bug fixing on small screens */}
@@ -44,7 +50,14 @@ export const RightSide = styled.div`
` `
export const RightSideContainer = styled.div` export const RightSideContainer = styled.div`
${({ isHidden, notificationMessage, isError }) => css` ${({
isHidden,
notificationMessage,
isError,
theme: {
addDialog: { notificationErrorBGColor, notificationSuccessBGColor },
},
}) => css`
height: 530px; height: 530px;
${notificationMessage && ${notificationMessage &&
@@ -58,7 +71,7 @@ export const RightSideContainer = styled.div`
content: '${notificationMessage}'; content: '${notificationMessage}';
display: grid; display: grid;
place-items: center; place-items: center;
background: ${isError ? '#cda184' : '#88cdaa'}; background: ${isError ? notificationErrorBGColor : notificationSuccessBGColor};
padding: 10px 15px; padding: 10px 15px;
position: absolute; position: absolute;
top: 52%; top: 52%;
@@ -172,11 +185,18 @@ export const IconWrapper = styled.div`
` `
export const LeftSideTopSection = styled.div` export const LeftSideTopSection = styled.div`
background: #e4f6ed; ${({
active,
theme: {
addDialog: { gradientStartColor },
},
}) => css`
background: ${gradientStartColor};
padding: 0 20px 20px 20px; padding: 0 20px 20px 20px;
transition: all 0.3s; transition: all 0.3s;
${({ active }) => active && 'box-shadow: 0 8px 10px -9px rgba(0, 0, 0, 0.5)'}; ${active && 'box-shadow: 0 8px 10px -9px rgba(0, 0, 0, 0.5)'};
`}
` `
export const PosterWrapper = styled.div` export const PosterWrapper = styled.div`
@@ -254,7 +274,12 @@ export const PosterSuggestionsItem = styled.div`
` `
export const Poster = styled.div` export const Poster = styled.div`
${({ poster }) => css` ${({
poster,
theme: {
addDialog: { posterBGColor },
},
}) => css`
border-radius: 5px; border-radius: 5px;
overflow: hidden; overflow: hidden;
width: 200px; width: 200px;
@@ -272,7 +297,7 @@ export const Poster = styled.div`
: css` : css`
display: grid; display: grid;
place-items: center; place-items: center;
background: #74c39c; background: ${posterBGColor};
svg { svg {
transform: scale(1.5) translateY(-3px); transform: scale(1.5) translateY(-3px);
@@ -294,6 +319,12 @@ export const ClearPosterButton = styled(Button)`
` `
export const PosterLanguageSwitch = styled.div` export const PosterLanguageSwitch = styled.div`
${({
showbutton,
theme: {
addDialog: { languageSwitchBGColor, languageSwitchFontColor },
},
}) => css`
grid-area: poster; grid-area: poster;
z-index: 5; z-index: 5;
position: absolute; position: absolute;
@@ -302,20 +333,21 @@ export const PosterLanguageSwitch = styled.div`
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
width: 30px; width: 30px;
height: 30px; height: 30px;
background: #74c39c; background: ${languageSwitchBGColor};
border-radius: 50%; border-radius: 50%;
display: grid; display: grid;
place-items: center; place-items: center;
color: #e4f6ed; color: ${languageSwitchFontColor};
font-weight: 600; font-weight: 600;
cursor: pointer; cursor: pointer;
transition: all 0.3s; transition: all 0.3s;
${({ showbutton }) => !showbutton && 'display: none'}; ${!showbutton && 'display: none'};
:hover { :hover {
filter: brightness(1.1); filter: brightness(1.1);
} }
`}
` `
export const ButtonWrapper = styled.div` export const ButtonWrapper = styled.div`

View File

@@ -21,18 +21,24 @@ const Sidebar = ({ isDrawerOpen, setIsDonationDialogOpen, isOffline, isLoading }
<AppSidebarStyle isDrawerOpen={isDrawerOpen}> <AppSidebarStyle isDrawerOpen={isDrawerOpen}>
<List> <List>
<AddDialogButton isOffline={isOffline} isLoading={isLoading} /> <AddDialogButton isOffline={isOffline} isLoading={isLoading} />
<RemoveAll isOffline={isOffline} isLoading={isLoading} /> <RemoveAll isOffline={isOffline} isLoading={isLoading} />
</List> </List>
<Divider /> <Divider />
<List> <List>
<SettingsDialog /> <SettingsDialog />
<AboutDialog /> <AboutDialog />
<ListItem button onClick={() => setIsDonationDialogOpen(true)}> <ListItem button onClick={() => setIsDonationDialogOpen(true)}>
<ListItemIcon> <ListItemIcon>
<CreditCardIcon /> <CreditCardIcon />
</ListItemIcon> </ListItemIcon>
<ListItemText primary={t('Donate')} /> <ListItemText primary={t('Donate')} />
</ListItem> </ListItem>
<CloseServer isOffline={isOffline} isLoading={isLoading} /> <CloseServer isOffline={isOffline} isLoading={isLoading} />
</List> </List>
</AppSidebarStyle> </AppSidebarStyle>

View File

@@ -1,8 +1,14 @@
import CssBaseline from '@material-ui/core/CssBaseline' import CssBaseline from '@material-ui/core/CssBaseline'
import { useEffect, useState } from 'react' import { createContext, useEffect, useState } from 'react'
import Typography from '@material-ui/core/Typography' import Typography from '@material-ui/core/Typography'
import IconButton from '@material-ui/core/IconButton' import IconButton from '@material-ui/core/IconButton'
import { Menu as MenuIcon, Close as CloseIcon } from '@material-ui/icons' import {
Menu as MenuIcon,
Close as CloseIcon,
Brightness4 as Brightness4Icon,
Brightness5 as Brightness5Icon,
BrightnessAuto as BrightnessAutoIcon,
} from '@material-ui/icons'
import { echoHost } from 'utils/Hosts' import { echoHost } from 'utils/Hosts'
import Div100vh from 'react-div-100vh' import Div100vh from 'react-div-100vh'
import axios from 'axios' import axios from 'axios'
@@ -16,18 +22,20 @@ import { useQuery } from 'react-query'
import { getTorrents } from 'utils/Utils' import { getTorrents } from 'utils/Utils'
import GlobalStyle from 'style/GlobalStyle' import GlobalStyle from 'style/GlobalStyle'
import { AppWrapper, AppHeader, LanguageSwitch } from './style' import { AppWrapper, AppHeader, HeaderToggle } from './style'
import Sidebar from './Sidebar' import Sidebar from './Sidebar'
import { darkTheme, lightTheme, useMaterialUITheme } from '../../style/materialUISetup' import { lightTheme, THEME_MODES, useMaterialUITheme } from '../../style/materialUISetup'
import getStyledComponentsTheme from '../../style/getStyledComponentsTheme' import getStyledComponentsTheme from '../../style/getStyledComponentsTheme'
export const DarkModeContext = createContext()
export default function App() { export default function App() {
const [isDrawerOpen, setIsDrawerOpen] = useState(false) const [isDrawerOpen, setIsDrawerOpen] = useState(false)
const [isDonationDialogOpen, setIsDonationDialogOpen] = useState(false) const [isDonationDialogOpen, setIsDonationDialogOpen] = useState(false)
const [torrServerVersion, setTorrServerVersion] = useState('') const [torrServerVersion, setTorrServerVersion] = useState('')
// https://material-ui.com/ru/customization/palette/ // https://material-ui.com/ru/customization/palette/
const [isDarkMode, muiTheme] = useMaterialUITheme() const [isDarkMode, currentThemeMode, setCurrentThemeMode, muiTheme] = useMaterialUITheme()
const [currentLang, changeLang] = useChangeLanguage() const [currentLang, changeLang] = useChangeLanguage()
const [isOffline, setIsOffline] = useState(false) const [isOffline, setIsOffline] = useState(false)
const { data: torrents, isLoading } = useQuery('torrents', getTorrents, { const { data: torrents, isLoading } = useQuery('torrents', getTorrents, {
@@ -45,8 +53,11 @@ export default function App() {
<> <>
<GlobalStyle /> <GlobalStyle />
<DarkModeContext.Provider value={{ isDarkMode }}>
<MuiThemeProvider theme={muiTheme}> <MuiThemeProvider theme={muiTheme}>
<StyledComponentsThemeProvider theme={getStyledComponentsTheme(isDarkMode ? 'dark' : 'light')}> <StyledComponentsThemeProvider
theme={getStyledComponentsTheme(isDarkMode ? THEME_MODES.DARK : THEME_MODES.LIGHT)}
>
<CssBaseline /> <CssBaseline />
{/* Div100vh - iOS WebKit fix */} {/* Div100vh - iOS WebKit fix */}
@@ -66,21 +77,37 @@ export default function App() {
TorrServer {torrServerVersion} TorrServer {torrServerVersion}
</Typography> </Typography>
<div style={{ justifySelf: 'end' }}> <div
<LanguageSwitch onClick={() => (currentLang === 'en' ? changeLang('ru') : changeLang('en'))}> style={{ justifySelf: 'end', display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: '10px' }}
>
<HeaderToggle
onClick={() => {
currentThemeMode === THEME_MODES.LIGHT && setCurrentThemeMode(THEME_MODES.DARK)
currentThemeMode === THEME_MODES.DARK && setCurrentThemeMode(THEME_MODES.AUTO)
currentThemeMode === THEME_MODES.AUTO && setCurrentThemeMode(THEME_MODES.LIGHT)
}}
>
{currentThemeMode === THEME_MODES.LIGHT ? (
<Brightness5Icon />
) : currentThemeMode === THEME_MODES.DARK ? (
<Brightness4Icon />
) : (
<BrightnessAutoIcon />
)}
</HeaderToggle>
<HeaderToggle onClick={() => (currentLang === 'en' ? changeLang('ru') : changeLang('en'))}>
{currentLang === 'en' ? 'RU' : 'EN'} {currentLang === 'en' ? 'RU' : 'EN'}
</LanguageSwitch> </HeaderToggle>
</div> </div>
</AppHeader> </AppHeader>
<MuiThemeProvider theme={darkTheme}>
<Sidebar <Sidebar
isOffline={isOffline} isOffline={isOffline}
isLoading={isLoading} isLoading={isLoading}
isDrawerOpen={isDrawerOpen} isDrawerOpen={isDrawerOpen}
setIsDonationDialogOpen={setIsDonationDialogOpen} setIsDonationDialogOpen={setIsDonationDialogOpen}
/> />
</MuiThemeProvider>
<TorrentList isOffline={isOffline} torrents={torrents} isLoading={isLoading} /> <TorrentList isOffline={isOffline} torrents={torrents} isLoading={isLoading} />
@@ -93,6 +120,7 @@ export default function App() {
</Div100vh> </Div100vh>
</StyledComponentsThemeProvider> </StyledComponentsThemeProvider>
</MuiThemeProvider> </MuiThemeProvider>
</DarkModeContext.Provider>
</> </>
) )
} }

View File

@@ -1,14 +1,21 @@
import { rgba } from 'polished'
import styled, { css } from 'styled-components' import styled, { css } from 'styled-components'
export const AppWrapper = styled.div` export const AppWrapper = styled.div`
${({
theme: {
app: { appSecondaryColor },
},
}) => css`
height: 100%; height: 100%;
background: #cbe8d9; background: ${rgba(appSecondaryColor, 0.8)};
display: grid; display: grid;
grid-template-columns: 60px 1fr; grid-template-columns: 60px 1fr;
grid-template-rows: 60px 1fr; grid-template-rows: 60px 1fr;
grid-template-areas: grid-template-areas:
'head head' 'head head'
'side content'; 'side content';
`}
` `
export const CenteredGrid = styled.div` export const CenteredGrid = styled.div`
@@ -32,16 +39,25 @@ export const AppHeader = styled.div`
`} `}
` `
export const AppSidebarStyle = styled.div` export const AppSidebarStyle = styled.div`
${({ isDrawerOpen }) => css` ${({
isDrawerOpen,
theme: {
app: { appSecondaryColor, sidebarBGColor, sidebarFillColor },
},
}) => css`
grid-area: side; grid-area: side;
width: ${isDrawerOpen ? '400%' : '100%'}; width: ${isDrawerOpen ? '400%' : '100%'};
z-index: 2; z-index: 2;
overflow-x: hidden; overflow-x: hidden;
transition: width 195ms cubic-bezier(0.4, 0, 0.6, 1) 0ms; transition: width 195ms cubic-bezier(0.4, 0, 0.6, 1) 0ms;
border-right: 1px solid rgba(0, 0, 0, 0.12); border-right: 1px solid ${rgba(appSecondaryColor, 0.12)};
background: #575757; background: ${sidebarBGColor};
color: #eee; color: ${sidebarFillColor};
white-space: nowrap; white-space: nowrap;
svg {
fill: ${sidebarFillColor};
}
`} `}
` `
export const TorrentListWrapper = styled.div` export const TorrentListWrapper = styled.div`
@@ -69,10 +85,15 @@ export const TorrentListWrapper = styled.div`
} }
` `
export const LanguageSwitch = styled.div` export const HeaderToggle = styled.div`
${({
theme: {
app: { headerToggleColor },
},
}) => css`
cursor: pointer; cursor: pointer;
border-radius: 50%; border-radius: 50%;
background: #56b887; background: ${headerToggleColor};
height: 35px; height: 35px;
width: 35px; width: 35px;
transition: all 0.2s; transition: all 0.2s;
@@ -82,7 +103,7 @@ export const LanguageSwitch = styled.div`
color: #fff; color: #fff;
:hover { :hover {
background: #4db380; background: ${rgba(headerToggleColor, 0.9)};
} }
@media (max-width: 700px) { @media (max-width: 700px) {
@@ -90,4 +111,5 @@ export const LanguageSwitch = styled.div`
width: 28px; width: 28px;
font-size: 12px; font-size: 12px;
} }
`}
` `

View File

@@ -1,19 +1,33 @@
import styled from 'styled-components' import styled, { css } from 'styled-components'
export const DetailedViewWidgetSection = styled.section` export const DetailedViewWidgetSection = styled.section`
${({
theme: {
detailedView: { gradientStartColor, gradientEndColor },
},
}) => css`
padding: 40px; padding: 40px;
background: linear-gradient(145deg, #e4f6ed, #b5dec9); background: linear-gradient(145deg, ${gradientStartColor}, ${gradientEndColor});
@media (max-width: 800px) { @media (max-width: 800px) {
padding: 20px; padding: 20px;
} }
`}
` `
export const DetailedViewCacheSection = styled.section` export const DetailedViewCacheSection = styled.section`
${({
theme: {
detailedView: { cacheSectionBGColor },
},
}) => css`
padding: 40px; padding: 40px;
box-shadow: inset 3px 25px 8px -25px rgba(0, 0, 0, 0.5); box-shadow: inset 3px 25px 8px -25px rgba(0, 0, 0, 0.5);
background: ${cacheSectionBGColor};
flex: 1;
@media (max-width: 800px) { @media (max-width: 800px) {
padding: 20px; padding: 20px;
} }
`}
` `

View File

@@ -1,15 +1,18 @@
import styled, { css } from 'styled-components' import styled, { css } from 'styled-components'
const bigTableDividerColor = '#ddd'
const bigTableViewedColor = '#f3f3f3'
const defaultPrimaryColor = '#009879'
const defaultSecondaryColor = '#00a383'
const defaultTertiaryColor = '#03aa89'
const viewedPrimaryColor = '#bdbdbd' const viewedPrimaryColor = '#bdbdbd'
const viewedSecondaryColor = '#c4c4c4' const viewedSecondaryColor = '#c4c4c4'
const viewedTertiaryColor = '#c9c9c9' const viewedTertiaryColor = '#c9c9c9'
const bigTableDividerColor = '#ddd'
const bigTableDefaultRowColor = '#fff'
const bigTableViewedRowColor = '#f3f3f3'
const viewedIndicator = css` const viewedIndicator = css`
${({
theme: {
table: { defaultPrimaryColor },
},
}) => css`
:before { :before {
content: ''; content: '';
width: 10px; width: 10px;
@@ -21,8 +24,14 @@ const viewedIndicator = css`
left: 50%; left: 50%;
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
} }
`}
` `
export const TableStyle = styled.table` export const TableStyle = styled.table`
${({
theme: {
table: { defaultPrimaryColor },
},
}) => css`
border-collapse: collapse; border-collapse: collapse;
margin: 25px 0; margin: 25px 0;
font-size: 0.9em; font-size: 0.9em;
@@ -30,6 +39,7 @@ export const TableStyle = styled.table`
border-radius: 5px 5px 0 0; border-radius: 5px 5px 0 0;
overflow: hidden; overflow: hidden;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.15); box-shadow: 0 0 20px rgba(0, 0, 0, 0.15);
color: #000;
thead tr { thead tr {
background: ${defaultPrimaryColor}; background: ${defaultPrimaryColor};
@@ -45,13 +55,14 @@ export const TableStyle = styled.table`
tbody tr { tbody tr {
border-bottom: 1px solid ${bigTableDividerColor}; border-bottom: 1px solid ${bigTableDividerColor};
background: ${bigTableDefaultRowColor};
:last-of-type { :last-of-type {
border-bottom: 2px solid ${defaultPrimaryColor}; border-bottom: 2px solid ${defaultPrimaryColor};
} }
&.viewed-file-row { &.viewed-file-row {
background: ${bigTableViewedColor}; background: ${bigTableViewedRowColor};
} }
} }
@@ -72,6 +83,7 @@ export const TableStyle = styled.table`
@media (max-width: 970px) { @media (max-width: 970px) {
display: none; display: none;
} }
`}
` `
export const ShortTableWrapper = styled.div` export const ShortTableWrapper = styled.div`
@@ -91,7 +103,12 @@ export const ShortTableWrapper = styled.div`
` `
export const ShortTable = styled.div` export const ShortTable = styled.div`
${({ isViewed }) => css` ${({
isViewed,
theme: {
table: { defaultPrimaryColor, defaultSecondaryColor, defaultTertiaryColor },
},
}) => css`
width: 100%; width: 100%;
grid-template-rows: repeat(3, max-content); grid-template-rows: repeat(3, max-content);
border-radius: 5px; border-radius: 5px;
@@ -170,6 +187,7 @@ export const ShortTable = styled.div`
grid-template-columns: repeat(3, 1fr); grid-template-columns: repeat(3, 1fr);
align-items: center; align-items: center;
gap: 20px; gap: 20px;
background: #fff;
@media (max-width: 410px) { @media (max-width: 410px) {
gap: 10px; gap: 10px;

View File

@@ -1,7 +1,8 @@
import Measure from 'react-measure' import Measure from 'react-measure'
import { useState, memo, useRef, useEffect } from 'react' import { useState, memo, useRef, useEffect, useContext } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import isEqual from 'lodash/isEqual' import isEqual from 'lodash/isEqual'
import { DarkModeContext } from 'components/App'
import { useCreateCacheMap } from '../customHooks' import { useCreateCacheMap } from '../customHooks'
import getShortCacheMap from './getShortCacheMap' import getShortCacheMap from './getShortCacheMap'
@@ -16,6 +17,9 @@ const TorrentCache = ({ cache, isMini }) => {
const ctxRef = useRef(null) const ctxRef = useRef(null)
const cacheMap = useCreateCacheMap(cache) const cacheMap = useCreateCacheMap(cache)
const settingsTarget = isMini ? 'mini' : 'default' const settingsTarget = isMini ? 'mini' : 'default'
const { isDarkMode } = useContext(DarkModeContext)
const theme = isDarkMode ? 'dark' : 'light'
const { const {
readerColor, readerColor,
rangeColor, rangeColor,
@@ -26,7 +30,7 @@ const TorrentCache = ({ cache, isMini }) => {
borderColor, borderColor,
cacheMaxHeight, cacheMaxHeight,
completeColor, completeColor,
} = snakeSettings[settingsTarget] } = snakeSettings[theme][settingsTarget]
const canvasWidth = isMini ? width * 0.93 : width const canvasWidth = isMini ? width * 0.93 : width
@@ -69,7 +73,7 @@ const TorrentCache = ({ cache, isMini }) => {
ctx.lineWidth = borderWidth ctx.lineWidth = borderWidth
ctx.fillStyle = inProgress ctx.fillStyle = inProgress
? createGradient(ctx, percentage, settingsTarget) ? createGradient(ctx, percentage, theme, settingsTarget)
: isCompleted : isCompleted
? completeColor ? completeColor
: backgroundColor : backgroundColor
@@ -102,13 +106,14 @@ const TorrentCache = ({ cache, isMini }) => {
completeColor, completeColor,
readerColor, readerColor,
rangeColor, rangeColor,
theme,
]) ])
return ( return (
<Measure bounds onResize={({ bounds }) => setDimensions(bounds)}> <Measure bounds onResize={({ bounds }) => setDimensions(bounds)}>
{({ measureRef }) => ( {({ measureRef }) => (
<div style={{ display: 'flex', flexDirection: 'column' }} ref={measureRef}> <div style={{ display: 'flex', flexDirection: 'column' }} ref={measureRef}>
<SnakeWrapper isMini={isMini}> <SnakeWrapper themeType={theme} isMini={isMini}>
<canvas ref={canvasRef} /> <canvas ref={canvasRef} />
</SnakeWrapper> </SnakeWrapper>

View File

@@ -1,12 +1,38 @@
import { mainColors } from 'style/colors' import { mainColors } from 'style/colors'
export const snakeSettings = { export const snakeSettings = {
dark: {
default: {
borderWidth: 1,
pieceSize: 14,
gapBetweenPieces: 3,
borderColor: mainColors.dark.primary,
completeColor: mainColors.dark.primary,
backgroundColor: '#fff',
progressColor: '#545a5e',
readerColor: '#fff',
rangeColor: '#cda184',
},
mini: {
cacheMaxHeight: 340,
borderWidth: 2,
pieceSize: 23,
gapBetweenPieces: 6,
borderColor: '#545a5e',
completeColor: '#545a5e',
backgroundColor: '#dee3e5',
progressColor: '#dee3e5',
readerColor: '#000',
rangeColor: '#cda184',
},
},
light: {
default: { default: {
borderWidth: 1, borderWidth: 1,
pieceSize: 14, pieceSize: 14,
gapBetweenPieces: 3, gapBetweenPieces: 3,
borderColor: '#dbf2e8', borderColor: '#dbf2e8',
completeColor: mainColors.primary, completeColor: mainColors.light.primary,
backgroundColor: '#fff', backgroundColor: '#fff',
progressColor: '#b3dfc9', progressColor: '#b3dfc9',
readerColor: '#000', readerColor: '#000',
@@ -24,10 +50,11 @@ export const snakeSettings = {
readerColor: '#2d714f', readerColor: '#2d714f',
rangeColor: '#afa6e3', rangeColor: '#afa6e3',
}, },
},
} }
export const createGradient = (ctx, percentage, snakeType) => { export const createGradient = (ctx, percentage, theme, snakeType) => {
const { pieceSize, completeColor, progressColor } = snakeSettings[snakeType] const { pieceSize, completeColor, progressColor } = snakeSettings[theme][snakeType]
const gradient = ctx.createLinearGradient(0, pieceSize, 0, 0) const gradient = ctx.createLinearGradient(0, pieceSize, 0, 0)
gradient.addColorStop(0, completeColor) gradient.addColorStop(0, completeColor)

View File

@@ -10,12 +10,12 @@ export const ScrollNotification = styled.div`
` `
export const SnakeWrapper = styled.div` export const SnakeWrapper = styled.div`
${({ isMini }) => css` ${({ isMini, themeType }) => css`
${isMini && ${isMini &&
css` css`
display: grid; display: grid;
justify-content: center; justify-content: center;
max-height: ${snakeSettings.mini.cacheMaxHeight}px; max-height: ${snakeSettings[themeType].mini.cacheMaxHeight}px;
overflow: auto; overflow: auto;
`} `}

View File

@@ -19,11 +19,17 @@ export const MainSectionButtonGroup = styled.div`
` `
export const SmallLabel = styled.div` export const SmallLabel = styled.div`
${({ mb }) => css` ${({
mb,
theme: {
torrentFunctions: { fontColor },
},
}) => css`
${mb && `margin-bottom: ${mb}px`}; ${mb && `margin-bottom: ${mb}px`};
font-size: 20px; font-size: 20px;
font-weight: 300; font-weight: 300;
line-height: 1; line-height: 1;
color: ${fontColor};
@media (max-width: 800px) { @media (max-width: 800px) {
font-size: 18px; font-size: 18px;

View File

@@ -133,7 +133,13 @@ export default function DialogTorrentDetailsContent({ closeDialog, torrent }) {
{...(isDetailedCacheView && { onBack: () => setIsDetailedCacheView(false) })} {...(isDetailedCacheView && { onBack: () => setIsDetailedCacheView(false) })}
/> />
<div style={{ minHeight: '80vh', overflow: 'auto' }}> <div
style={{
minHeight: '80vh',
overflow: 'auto',
...(isDetailedCacheView && { display: 'flex', flexDirection: 'column' }),
}}
>
{isLoading ? ( {isLoading ? (
<Loader /> <Loader />
) : isDetailedCacheView ? ( ) : isDetailedCacheView ? (

View File

@@ -1,3 +1,4 @@
import { rgba } from 'polished'
import styled, { css } from 'styled-components' import styled, { css } from 'styled-components'
export const DialogContentGrid = styled.div` export const DialogContentGrid = styled.div`
@@ -18,7 +19,12 @@ export const DialogContentGrid = styled.div`
} }
` `
export const Poster = styled.div` export const Poster = styled.div`
${({ poster }) => css` ${({
poster,
theme: {
dialogTorrentDetailsContent: { posterBGColor },
},
}) => css`
height: 400px; height: 400px;
border-radius: 5px; border-radius: 5px;
overflow: hidden; overflow: hidden;
@@ -35,7 +41,7 @@ export const Poster = styled.div`
width: 300px; width: 300px;
display: grid; display: grid;
place-items: center; place-items: center;
background: #74c39c; background: ${posterBGColor};
svg { svg {
transform: scale(2.5) translateY(-3px); transform: scale(2.5) translateY(-3px);
@@ -58,12 +64,17 @@ export const Poster = styled.div`
`} `}
` `
export const MainSection = styled.section` export const MainSection = styled.section`
${({
theme: {
dialogTorrentDetailsContent: { gradientStartColor, gradientEndColor },
},
}) => css`
grid-area: main; grid-area: main;
padding: 40px; padding: 40px;
display: grid; display: grid;
grid-template-columns: min-content 1fr; grid-template-columns: min-content 1fr;
gap: 30px; gap: 30px;
background: linear-gradient(145deg, #e4f6ed, #b5dec9); background: linear-gradient(145deg, ${gradientStartColor}, ${gradientEndColor});
@media (max-width: 840px) { @media (max-width: 840px) {
grid-template-columns: 1fr; grid-template-columns: 1fr;
@@ -72,56 +83,83 @@ export const MainSection = styled.section`
@media (max-width: 800px) { @media (max-width: 800px) {
padding: 20px; padding: 20px;
} }
`}
` `
export const CacheSection = styled.section` export const CacheSection = styled.section`
${({
theme: {
dialogTorrentDetailsContent: { chacheSectionBGColor },
},
}) => css`
grid-area: cache; grid-area: cache;
padding: 40px; padding: 40px;
display: grid; display: grid;
align-content: start; align-content: start;
grid-template-rows: min-content 1fr min-content; grid-template-rows: min-content 1fr min-content;
background: #88cdaa; background: ${chacheSectionBGColor};
@media (max-width: 800px) { @media (max-width: 800px) {
padding: 20px; padding: 20px;
} }
`}
` `
export const TorrentFilesSection = styled.section` export const TorrentFilesSection = styled.section`
${({
theme: {
dialogTorrentDetailsContent: { torrentFilesSectionBGColor },
},
}) => css`
grid-area: file-list; grid-area: file-list;
padding: 40px; padding: 40px;
box-shadow: inset 3px 25px 8px -25px rgba(0, 0, 0, 0.5); box-shadow: inset 3px 25px 8px -25px rgba(0, 0, 0, 0.5);
background: ${torrentFilesSectionBGColor};
@media (max-width: 800px) { @media (max-width: 800px) {
padding: 20px; padding: 20px;
} }
`}
` `
export const SectionSubName = styled.div` export const SectionSubName = styled.div`
${({
theme: {
dialogTorrentDetailsContent: { subNameFontColor },
},
}) => css`
${({ mb }) => css` ${({ mb }) => css`
${mb && `margin-bottom: ${mb}px`}; ${mb && `margin-bottom: ${mb}px`};
color: #7c7b7c; color: ${subNameFontColor};
@media (max-width: 800px) { @media (max-width: 800px) {
${mb && `margin-bottom: ${mb / 2}px`}; ${mb && `margin-bottom: ${mb / 2}px`};
font-size: 11px; font-size: 11px;
} }
`} `}
`}
` `
export const SectionTitle = styled.div` export const SectionTitle = styled.div`
${({
theme: {
dialogTorrentDetailsContent: { fontColor },
},
}) => css`
${({ mb }) => css` ${({ mb }) => css`
${mb && `margin-bottom: ${mb}px`}; ${mb && `margin-bottom: ${mb}px`};
font-size: 35px; font-size: 35px;
font-weight: 300; font-weight: 300;
line-height: 1; line-height: 1;
word-break: break-word; word-break: break-word;
color: ${fontColor};
@media (max-width: 800px) { @media (max-width: 800px) {
font-size: 25px; font-size: 25px;
${mb && `margin-bottom: ${mb / 2}px`}; ${mb && `margin-bottom: ${mb / 2}px`};
} }
`} `}
`}
` `
export const SectionHeader = styled.div` export const SectionHeader = styled.div`
@@ -182,18 +220,25 @@ export const WidgetFieldWrapper = styled.div`
} }
` `
export const WidgetFieldTitle = styled.div` export const WidgetFieldTitle = styled.div`
${({
theme: {
dialogTorrentDetailsContent: { fontColor },
},
}) => css`
grid-area: title; grid-area: title;
justify-self: start; justify-self: start;
text-transform: uppercase; text-transform: uppercase;
font-size: 11px; font-size: 11px;
margin-bottom: 2px; margin-bottom: 2px;
font-weight: 600; font-weight: 600;
color: ${fontColor};
`}
` `
export const WidgetFieldIcon = styled.div` export const WidgetFieldIcon = styled.div`
${({ bgColor }) => css` ${({ bgColor }) => css`
grid-area: icon; grid-area: icon;
color: rgba(255, 255, 255, 0.8); color: ${rgba('#fff', 0.8)};
background: ${bgColor}; background: ${bgColor};
border-radius: 5px 0 0 5px; border-radius: 5px 0 0 5px;
@@ -220,20 +265,29 @@ export const WidgetFieldValue = styled.div`
`} `}
` `
export const LoadingProgress = styled.div.attrs(({ value, fullAmount }) => { export const LoadingProgress = styled.div.attrs(
({
value,
fullAmount,
theme: {
dialogTorrentDetailsContent: { gradientEndColor },
},
}) => {
const percentage = Math.min(100, (value * 100) / fullAmount) const percentage = Math.min(100, (value * 100) / fullAmount)
return { return {
// this block is here according to styled-components recomendation about fast changable components // this block is here according to styled-components recomendation about fast changable components
style: { style: {
background: `linear-gradient(to right, #b5dec9 0%, #b5dec9 ${percentage}%, #fff ${percentage}%, #fff 100%)`, background: `linear-gradient(to right, ${gradientEndColor} 0%, ${gradientEndColor} ${percentage}%, #fff ${percentage}%, #fff 100%)`,
}, },
} }
})` },
)`
${({ label }) => css` ${({ label }) => css`
border: 1px solid; border: 1px solid;
padding: 10px 20px; padding: 10px 20px;
border-radius: 5px; border-radius: 5px;
color: #000;
:before { :before {
content: '${label}'; content: '${label}';

View File

@@ -1,7 +1,11 @@
import styled, { css } from 'styled-components' import styled, { css } from 'styled-components'
export const TorrentCard = styled.div` export const TorrentCard = styled.div`
${({ theme: { primary } }) => css` ${({
theme: {
torrentCard: { cardPrimaryColor },
},
}) => css`
border-radius: 5px; border-radius: 5px;
display: grid; display: grid;
grid-template-columns: 120px 260px 1fr; grid-template-columns: 120px 260px 1fr;
@@ -9,7 +13,7 @@ export const TorrentCard = styled.div`
grid-template-areas: 'poster description buttons'; grid-template-areas: 'poster description buttons';
gap: 10px; gap: 10px;
padding: 10px; padding: 10px;
background: ${primary}; background: ${cardPrimaryColor};
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%); 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%);
@media (max-width: 1260px), (max-height: 500px) { @media (max-width: 1260px), (max-height: 500px) {
@@ -34,7 +38,12 @@ export const TorrentCardPoster = styled.div`
overflow: hidden; overflow: hidden;
text-align: center; text-align: center;
${({ isPoster }) => ${({
isPoster,
theme: {
torrentCard: { cardSecondaryColor, accentCardColor },
},
}) =>
isPoster isPoster
? css` ? css`
img { img {
@@ -47,8 +56,8 @@ export const TorrentCardPoster = styled.div`
: css` : css`
display: grid; display: grid;
place-items: center; place-items: center;
background: #74c39c; background: ${cardSecondaryColor};
border: 1px solid #337a57; border: 1px solid ${accentCardColor};
svg { svg {
transform: translateY(-3px); transform: translateY(-3px);
@@ -76,8 +85,13 @@ export const TorrentCardButtons = styled.div`
} }
` `
export const TorrentCardDescription = styled.div` export const TorrentCardDescription = styled.div`
${({
theme: {
torrentCard: { cardSecondaryColor, accentCardColor },
},
}) => css`
grid-area: description; grid-area: description;
background: #74c39c; background: ${cardSecondaryColor};
border-radius: 5px; border-radius: 5px;
padding: 5px; padding: 5px;
display: grid; display: grid;
@@ -99,7 +113,7 @@ export const TorrentCardDescription = styled.div`
font-size: 10px; font-size: 10px;
font-weight: 600; font-weight: 600;
letter-spacing: 0.4px; letter-spacing: 0.4px;
color: #337a57; color: ${accentCardColor};
@media (max-width: 770px) { @media (max-width: 770px) {
font-size: 0.4rem; font-size: 0.4rem;
@@ -155,9 +169,15 @@ export const TorrentCardDescription = styled.div`
font-size: 10px; font-size: 10px;
} }
} }
`}
` `
export const StyledButton = styled.button` export const StyledButton = styled.button`
${({
theme: {
torrentCard: { buttonBGColor, accentCardColor },
},
}) => css`
border-radius: 5px; border-radius: 5px;
border: none; border: none;
cursor: pointer; cursor: pointer;
@@ -165,7 +185,7 @@ export const StyledButton = styled.button`
display: flex; display: flex;
align-items: center; align-items: center;
text-transform: uppercase; text-transform: uppercase;
background: #268757; background: ${buttonBGColor};
color: #fff; color: #fff;
font-size: 0.9rem; font-size: 0.9rem;
letter-spacing: 0.009em; letter-spacing: 0.009em;
@@ -175,7 +195,7 @@ export const StyledButton = styled.button`
} }
:hover { :hover {
background: #337a57; background: ${accentCardColor};
} }
> :first-child { > :first-child {
@@ -200,4 +220,5 @@ export const StyledButton = styled.button`
font-size: 0.6rem; font-size: 0.6rem;
padding: 7px 5px; padding: 7px 5px;
} }
`}
` `

View File

@@ -1,6 +1,6 @@
import { useTheme } from '@material-ui/core'
import { useState } from 'react' import { useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { mainColors } from 'style/colors'
import AddDialog from '../Add/AddDialog' import AddDialog from '../Add/AddDialog'
import IconWrapper from './style' import IconWrapper from './style'
@@ -10,6 +10,7 @@ export default function AddFirstTorrent() {
const [isDialogOpen, setIsDialogOpen] = useState(false) const [isDialogOpen, setIsDialogOpen] = useState(false)
const handleClickOpen = () => setIsDialogOpen(true) const handleClickOpen = () => setIsDialogOpen(true)
const handleClose = () => setIsDialogOpen(false) const handleClose = () => setIsDialogOpen(false)
const primary = useTheme().palette.primary.main
return ( return (
<> <>
@@ -17,7 +18,7 @@ export default function AddFirstTorrent() {
<lord-icon <lord-icon
src='https://cdn.lordicon.com/bbnkwdur.json' src='https://cdn.lordicon.com/bbnkwdur.json'
trigger='loop' trigger='loop'
colors={`primary:#121331,secondary:${mainColors.primary}`} colors={`primary:#121331,secondary:${primary}`}
stroke='26' stroke='26'
scale='60' scale='60'
/> />

View File

@@ -1,17 +1,18 @@
import { useTheme } from '@material-ui/core'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { mainColors } from 'style/colors'
import IconWrapper from './style' import IconWrapper from './style'
export default function NoServerConnection() { export default function NoServerConnection() {
const { t } = useTranslation() const { t } = useTranslation()
const primary = useTheme().palette.primary.main
return ( return (
<IconWrapper> <IconWrapper>
<lord-icon <lord-icon
src='https://cdn.lordicon.com/wrprwmwt.json' src='https://cdn.lordicon.com/wrprwmwt.json'
trigger='loop' trigger='loop'
colors={`primary:#121331,secondary:${mainColors.primary}`} colors={`primary:#121331,secondary:${primary}`}
stroke='26' stroke='26'
scale='60' scale='60'
/> />

View File

@@ -1,8 +1,13 @@
export const NoImageIcon = () => ( import { useTheme } from '@material-ui/core'
export const NoImageIcon = ({ color }) => {
const primary = useTheme().palette.primary.main
return (
<svg <svg
height='80px' height='80px'
width='80px' width='80px'
fill='#248a57' fill={color || primary}
xmlns='http://www.w3.org/2000/svg' xmlns='http://www.w3.org/2000/svg'
xmlnsXlink='http://www.w3.org/1999/xlink' xmlnsXlink='http://www.w3.org/1999/xlink'
version='1.1' version='1.1'
@@ -19,17 +24,21 @@ export const NoImageIcon = () => (
</g> </g>
</svg> </svg>
) )
}
export const AddItemIcon = () => ( export const AddItemIcon = () => {
const primary = useTheme().palette.primary.main
return (
<svg <svg
height='100px' height='100px'
width='100px' width='100px'
fill='#248a57' fill={primary}
viewBox='0 0 452 452' viewBox='0 0 452 452'
version='1.1' version='1.1'
xmlns='http://www.w3.org/2000/svg' xmlns='http://www.w3.org/2000/svg'
> >
<g id='#000000ff'> <g id='#000000'>
<path <path
opacity='1.00' opacity='1.00'
d=' M 210.49 18.69 C 244.92 16.12 280.02 22.13 311.46 36.47 C 344.90 51.54 374.16 75.69 395.41 105.58 C 415.62 133.87 428.55 167.34 432.48 201.89 C 438.07 248.86 427.02 297.61 401.45 337.43 C 382.92 366.59 357.02 391.04 326.80 407.80 C 300.81 422.31 271.64 431.08 241.96 433.26 C 207.37 435.97 172.14 429.83 140.54 415.51 C 109.95 401.69 82.82 380.33 62.16 353.86 C 39.25 324.67 24.38 289.21 19.78 252.38 C 14.94 214.51 20.65 175.31 36.47 140.54 C 54.11 101.38 84.24 67.99 121.37 46.39 C 148.44 30.52 179.19 20.98 210.49 18.69 M 213.46 36.60 C 178.91 38.80 145.03 50.71 116.76 70.72 C 84.67 93.21 59.84 125.88 46.91 162.88 C 34.87 196.99 32.96 234.54 41.25 269.73 C 48.89 302.45 65.53 332.98 88.79 357.21 C 113.91 383.56 146.78 402.45 182.25 410.72 C 216.67 418.86 253.37 417.21 286.87 405.85 C 329.85 391.49 367.13 361.01 389.89 321.85 C 406.02 294.41 414.96 262.84 415.73 231.03 C 416.71 196.59 408.11 161.91 390.97 132.00 C 372.31 99.13 343.57 72.09 309.61 55.49 C 279.95 40.89 246.43 34.40 213.46 36.60 Z' d=' M 210.49 18.69 C 244.92 16.12 280.02 22.13 311.46 36.47 C 344.90 51.54 374.16 75.69 395.41 105.58 C 415.62 133.87 428.55 167.34 432.48 201.89 C 438.07 248.86 427.02 297.61 401.45 337.43 C 382.92 366.59 357.02 391.04 326.80 407.80 C 300.81 422.31 271.64 431.08 241.96 433.26 C 207.37 435.97 172.14 429.83 140.54 415.51 C 109.95 401.69 82.82 380.33 62.16 353.86 C 39.25 324.67 24.38 289.21 19.78 252.38 C 14.94 214.51 20.65 175.31 36.47 140.54 C 54.11 101.38 84.24 67.99 121.37 46.39 C 148.44 30.52 179.19 20.98 210.49 18.69 M 213.46 36.60 C 178.91 38.80 145.03 50.71 116.76 70.72 C 84.67 93.21 59.84 125.88 46.91 162.88 C 34.87 196.99 32.96 234.54 41.25 269.73 C 48.89 302.45 65.53 332.98 88.79 357.21 C 113.91 383.56 146.78 402.45 182.25 410.72 C 216.67 418.86 253.37 417.21 286.87 405.85 C 329.85 391.49 367.13 361.01 389.89 321.85 C 406.02 294.41 414.96 262.84 415.73 231.03 C 416.71 196.59 408.11 161.91 390.97 132.00 C 372.31 99.13 343.57 72.09 309.61 55.49 C 279.95 40.89 246.43 34.40 213.46 36.60 Z'
@@ -41,39 +50,44 @@ export const AddItemIcon = () => (
</g> </g>
</svg> </svg>
) )
}
export const TorrentIcon = () => ( export const TorrentIcon = () => {
const primary = useTheme().palette.primary.main
const secondaryColor = primary === '#00a572' ? '#74c39c' : '#4a5255'
return (
<svg width='150px' height='150px' viewBox='0 0 512 512' version='1.1' xmlns='http://www.w3.org/2000/svg'> <svg width='150px' height='150px' viewBox='0 0 512 512' version='1.1' xmlns='http://www.w3.org/2000/svg'>
<g id='#248a57ff'> <g id={primary}>
<path <path
fill='#248a57' fill={primary}
opacity='1.00' opacity='1.00'
d=' M 102.41 0.00 L 319.87 0.00 C 320.21 29.68 319.87 59.37 320.04 89.05 C 320.29 97.32 323.88 105.47 329.94 111.12 C 336.01 117.07 344.56 120.18 353.01 120.01 C 382.02 119.87 411.04 120.22 440.05 119.83 C 439.94 236.88 440.04 353.93 440.00 470.98 C 440.01 478.16 440.50 485.68 437.47 492.41 C 432.79 503.85 421.05 511.80 408.71 512.00 L 103.28 512.00 C 90.95 511.79 79.20 503.84 74.53 492.42 C 72.06 486.96 71.87 480.87 71.99 474.97 C 72.01 327.63 71.99 180.30 72.00 32.96 C 71.95 27.61 73.03 22.22 75.52 17.46 C 80.55 7.39 91.19 0.57 102.41 0.00 M 360.00 382.07 C 358.69 383.73 359.01 385.99 358.90 387.97 C 358.95 396.36 358.91 404.75 358.93 413.14 C 352.50 403.51 346.13 393.83 339.77 384.16 C 338.65 382.47 337.13 380.65 334.92 380.63 C 331.97 380.41 329.13 382.87 329.22 385.89 C 328.94 396.58 329.24 407.28 329.08 417.98 C 329.14 420.43 328.85 422.98 329.54 425.38 C 330.75 429.14 337.11 428.63 337.54 424.63 C 338.19 415.09 337.55 405.51 337.83 395.95 C 343.71 404.78 349.41 413.73 355.26 422.58 C 356.92 424.93 358.74 427.96 362.00 428.00 C 365.02 428.51 367.54 425.83 367.40 422.90 C 367.55 411.27 367.39 399.62 367.48 387.99 C 367.40 386.11 367.63 384.06 366.61 382.38 C 365.24 380.16 361.58 380.00 360.00 382.07 M 100.79 382.81 C 98.94 384.82 100.19 388.63 103.01 388.89 C 106.91 389.29 110.85 388.97 114.77 389.07 C 114.77 399.73 114.78 410.39 114.75 421.05 C 114.76 423.37 114.89 426.34 117.28 427.52 C 119.95 429.02 123.67 427.14 123.86 424.04 C 124.22 412.40 123.84 400.72 124.04 389.07 C 128.25 388.87 132.57 389.54 136.71 388.62 C 140.15 387.40 139.25 381.72 135.61 381.56 C 126.10 381.14 116.55 381.57 107.03 381.37 C 104.95 381.53 102.34 381.06 100.79 382.81 M 156.46 381.58 C 150.26 383.15 145.11 388.05 143.12 394.11 C 140.49 401.86 140.79 410.83 144.81 418.06 C 151.07 429.05 167.20 430.79 177.27 424.26 C 183.48 420.06 186.24 412.28 186.28 405.03 C 186.43 398.11 184.59 390.56 179.19 385.85 C 173.03 380.52 164.12 379.62 156.46 381.58 M 197.74 381.67 C 195.24 381.99 194.12 384.61 194.23 386.87 C 194.06 397.92 194.27 408.97 194.15 420.02 C 194.24 422.43 193.92 425.36 195.97 427.11 C 198.62 429.25 203.28 427.47 203.31 423.89 C 203.66 418.45 203.32 412.99 203.49 407.54 C 206.76 407.72 210.68 407.24 213.15 409.89 C 217.60 414.61 220.01 420.80 223.85 425.97 C 225.63 428.66 230.20 428.72 231.83 425.86 C 232.87 424.27 231.80 422.43 231.24 420.89 C 228.63 415.38 225.17 409.99 220.02 406.56 C 223.42 405.53 227.11 404.31 229.29 401.31 C 233.14 395.94 231.83 387.34 226.14 383.76 C 221.99 381.01 216.77 381.52 212.04 381.39 C 207.28 381.52 202.48 381.08 197.74 381.67 M 240.23 386.91 C 240.19 398.28 240.20 409.66 240.22 421.03 C 240.25 423.12 240.14 425.65 241.97 427.09 C 244.58 429.23 249.25 427.52 249.33 423.98 C 249.76 418.50 249.34 413.00 249.49 407.51 C 252.77 407.64 256.62 407.29 259.13 409.85 C 263.88 414.69 266.10 421.38 270.41 426.55 C 272.74 429.20 278.48 428.00 278.28 424.04 C 276.28 417.09 271.87 410.81 266.09 406.46 C 269.75 405.55 273.64 404.05 275.74 400.71 C 278.91 395.49 277.81 387.82 272.73 384.18 C 268.85 381.14 263.64 381.44 259.00 381.41 C 254.02 381.52 249.02 381.13 244.05 381.58 C 241.41 381.77 240.05 384.51 240.23 386.91 M 286.38 386.01 C 286.17 397.35 286.39 408.70 286.27 420.04 C 286.31 422.30 286.17 425.31 288.52 426.53 C 291.20 427.60 294.20 427.07 297.03 427.21 C 304.36 427.04 311.73 427.52 319.04 426.95 C 322.44 426.37 322.43 420.75 319.05 420.15 C 311.25 419.44 303.38 420.13 295.56 419.82 C 295.59 415.47 295.58 411.12 295.58 406.78 C 302.60 406.71 309.65 407.09 316.66 406.54 C 320.07 405.84 319.57 399.91 315.98 399.96 C 309.20 399.54 302.39 399.95 295.59 399.80 C 295.57 396.05 295.57 392.30 295.58 388.55 C 303.03 388.43 310.50 388.74 317.94 388.37 C 321.67 388.25 321.80 381.95 318.11 381.66 C 309.41 381.03 300.65 381.57 291.93 381.42 C 289.16 381.15 286.27 383.00 286.38 386.01 M 375.06 381.95 C 372.19 383.34 372.77 388.27 375.95 388.84 C 379.96 389.33 384.02 388.96 388.05 389.08 C 387.92 400.08 388.05 411.07 387.99 422.07 C 387.75 424.61 389.07 427.71 391.95 427.92 C 394.85 428.51 397.33 425.86 397.14 423.05 C 397.37 411.73 397.16 400.40 397.23 389.08 C 401.42 388.89 405.69 389.52 409.82 388.64 C 413.41 387.46 412.48 381.48 408.64 381.52 C 400.79 381.23 392.93 381.50 385.08 381.39 C 381.74 381.50 378.31 381.05 375.06 381.95 Z' d=' M 102.41 0.00 L 319.87 0.00 C 320.21 29.68 319.87 59.37 320.04 89.05 C 320.29 97.32 323.88 105.47 329.94 111.12 C 336.01 117.07 344.56 120.18 353.01 120.01 C 382.02 119.87 411.04 120.22 440.05 119.83 C 439.94 236.88 440.04 353.93 440.00 470.98 C 440.01 478.16 440.50 485.68 437.47 492.41 C 432.79 503.85 421.05 511.80 408.71 512.00 L 103.28 512.00 C 90.95 511.79 79.20 503.84 74.53 492.42 C 72.06 486.96 71.87 480.87 71.99 474.97 C 72.01 327.63 71.99 180.30 72.00 32.96 C 71.95 27.61 73.03 22.22 75.52 17.46 C 80.55 7.39 91.19 0.57 102.41 0.00 M 360.00 382.07 C 358.69 383.73 359.01 385.99 358.90 387.97 C 358.95 396.36 358.91 404.75 358.93 413.14 C 352.50 403.51 346.13 393.83 339.77 384.16 C 338.65 382.47 337.13 380.65 334.92 380.63 C 331.97 380.41 329.13 382.87 329.22 385.89 C 328.94 396.58 329.24 407.28 329.08 417.98 C 329.14 420.43 328.85 422.98 329.54 425.38 C 330.75 429.14 337.11 428.63 337.54 424.63 C 338.19 415.09 337.55 405.51 337.83 395.95 C 343.71 404.78 349.41 413.73 355.26 422.58 C 356.92 424.93 358.74 427.96 362.00 428.00 C 365.02 428.51 367.54 425.83 367.40 422.90 C 367.55 411.27 367.39 399.62 367.48 387.99 C 367.40 386.11 367.63 384.06 366.61 382.38 C 365.24 380.16 361.58 380.00 360.00 382.07 M 100.79 382.81 C 98.94 384.82 100.19 388.63 103.01 388.89 C 106.91 389.29 110.85 388.97 114.77 389.07 C 114.77 399.73 114.78 410.39 114.75 421.05 C 114.76 423.37 114.89 426.34 117.28 427.52 C 119.95 429.02 123.67 427.14 123.86 424.04 C 124.22 412.40 123.84 400.72 124.04 389.07 C 128.25 388.87 132.57 389.54 136.71 388.62 C 140.15 387.40 139.25 381.72 135.61 381.56 C 126.10 381.14 116.55 381.57 107.03 381.37 C 104.95 381.53 102.34 381.06 100.79 382.81 M 156.46 381.58 C 150.26 383.15 145.11 388.05 143.12 394.11 C 140.49 401.86 140.79 410.83 144.81 418.06 C 151.07 429.05 167.20 430.79 177.27 424.26 C 183.48 420.06 186.24 412.28 186.28 405.03 C 186.43 398.11 184.59 390.56 179.19 385.85 C 173.03 380.52 164.12 379.62 156.46 381.58 M 197.74 381.67 C 195.24 381.99 194.12 384.61 194.23 386.87 C 194.06 397.92 194.27 408.97 194.15 420.02 C 194.24 422.43 193.92 425.36 195.97 427.11 C 198.62 429.25 203.28 427.47 203.31 423.89 C 203.66 418.45 203.32 412.99 203.49 407.54 C 206.76 407.72 210.68 407.24 213.15 409.89 C 217.60 414.61 220.01 420.80 223.85 425.97 C 225.63 428.66 230.20 428.72 231.83 425.86 C 232.87 424.27 231.80 422.43 231.24 420.89 C 228.63 415.38 225.17 409.99 220.02 406.56 C 223.42 405.53 227.11 404.31 229.29 401.31 C 233.14 395.94 231.83 387.34 226.14 383.76 C 221.99 381.01 216.77 381.52 212.04 381.39 C 207.28 381.52 202.48 381.08 197.74 381.67 M 240.23 386.91 C 240.19 398.28 240.20 409.66 240.22 421.03 C 240.25 423.12 240.14 425.65 241.97 427.09 C 244.58 429.23 249.25 427.52 249.33 423.98 C 249.76 418.50 249.34 413.00 249.49 407.51 C 252.77 407.64 256.62 407.29 259.13 409.85 C 263.88 414.69 266.10 421.38 270.41 426.55 C 272.74 429.20 278.48 428.00 278.28 424.04 C 276.28 417.09 271.87 410.81 266.09 406.46 C 269.75 405.55 273.64 404.05 275.74 400.71 C 278.91 395.49 277.81 387.82 272.73 384.18 C 268.85 381.14 263.64 381.44 259.00 381.41 C 254.02 381.52 249.02 381.13 244.05 381.58 C 241.41 381.77 240.05 384.51 240.23 386.91 M 286.38 386.01 C 286.17 397.35 286.39 408.70 286.27 420.04 C 286.31 422.30 286.17 425.31 288.52 426.53 C 291.20 427.60 294.20 427.07 297.03 427.21 C 304.36 427.04 311.73 427.52 319.04 426.95 C 322.44 426.37 322.43 420.75 319.05 420.15 C 311.25 419.44 303.38 420.13 295.56 419.82 C 295.59 415.47 295.58 411.12 295.58 406.78 C 302.60 406.71 309.65 407.09 316.66 406.54 C 320.07 405.84 319.57 399.91 315.98 399.96 C 309.20 399.54 302.39 399.95 295.59 399.80 C 295.57 396.05 295.57 392.30 295.58 388.55 C 303.03 388.43 310.50 388.74 317.94 388.37 C 321.67 388.25 321.80 381.95 318.11 381.66 C 309.41 381.03 300.65 381.57 291.93 381.42 C 289.16 381.15 286.27 383.00 286.38 386.01 M 375.06 381.95 C 372.19 383.34 372.77 388.27 375.95 388.84 C 379.96 389.33 384.02 388.96 388.05 389.08 C 387.92 400.08 388.05 411.07 387.99 422.07 C 387.75 424.61 389.07 427.71 391.95 427.92 C 394.85 428.51 397.33 425.86 397.14 423.05 C 397.37 411.73 397.16 400.40 397.23 389.08 C 401.42 388.89 405.69 389.52 409.82 388.64 C 413.41 387.46 412.48 381.48 408.64 381.52 C 400.79 381.23 392.93 381.50 385.08 381.39 C 381.74 381.50 378.31 381.05 375.06 381.95 Z'
/> />
<path <path
fill='#248a57' fill={primary}
opacity='1.00' opacity='1.00'
d=' M 160.39 388.45 C 164.79 387.33 170.01 388.38 173.03 391.97 C 176.12 395.52 177.00 400.46 176.87 405.04 C 176.76 409.47 175.56 414.16 172.29 417.34 C 167.50 421.98 158.82 421.68 154.58 416.43 C 150.59 411.44 150.26 404.45 151.51 398.43 C 152.46 393.85 155.68 389.57 160.39 388.45 Z' d=' M 160.39 388.45 C 164.79 387.33 170.01 388.38 173.03 391.97 C 176.12 395.52 177.00 400.46 176.87 405.04 C 176.76 409.47 175.56 414.16 172.29 417.34 C 167.50 421.98 158.82 421.68 154.58 416.43 C 150.59 411.44 150.26 404.45 151.51 398.43 C 152.46 393.85 155.68 389.57 160.39 388.45 Z'
/> />
<path <path
fill='#248a57' fill={primary}
opacity='1.00' opacity='1.00'
d=' M 203.47 388.42 C 208.28 388.55 213.18 387.93 217.93 388.93 C 222.82 390.10 223.71 398.14 218.81 399.89 C 213.88 401.57 208.52 400.89 203.40 400.90 C 203.44 396.73 203.45 392.57 203.47 388.42 Z' d=' M 203.47 388.42 C 208.28 388.55 213.18 387.93 217.93 388.93 C 222.82 390.10 223.71 398.14 218.81 399.89 C 213.88 401.57 208.52 400.89 203.40 400.90 C 203.44 396.73 203.45 392.57 203.47 388.42 Z'
/> />
<path <path
fill='#248a57' fill={primary}
opacity='1.00' opacity='1.00'
d=' M 249.45 388.38 C 254.29 388.56 259.22 387.96 264.00 388.94 C 268.52 390.07 269.67 397.04 265.66 399.44 C 260.63 401.83 254.85 400.80 249.47 400.94 C 249.51 396.75 249.48 392.57 249.45 388.38 Z' d=' M 249.45 388.38 C 254.29 388.56 259.22 387.96 264.00 388.94 C 268.52 390.07 269.67 397.04 265.66 399.44 C 260.63 401.83 254.85 400.80 249.47 400.94 C 249.51 396.75 249.48 392.57 249.45 388.38 Z'
/> />
</g> </g>
<g id='#74c39cff'> <g id={secondaryColor}>
<path <path
fill='#74c39c' fill={secondaryColor}
opacity='1.00' opacity='1.00'
d=' M 319.87 0.00 L 320.20 0.00 C 360.20 39.89 400.19 79.79 440.05 119.83 C 411.04 120.22 382.02 119.87 353.01 120.01 C 344.56 120.18 336.01 117.07 329.94 111.12 C 323.88 105.47 320.29 97.32 320.04 89.05 C 319.87 59.37 320.21 29.68 319.87 0.00 Z' d=' M 319.87 0.00 L 320.20 0.00 C 360.20 39.89 400.19 79.79 440.05 119.83 C 411.04 120.22 382.02 119.87 353.01 120.01 C 344.56 120.18 336.01 117.07 329.94 111.12 C 323.88 105.47 320.29 97.32 320.04 89.05 C 319.87 59.37 320.21 29.68 319.87 0.00 Z'
/> />
</g> </g>
<g id='#fdfdfdff'> <g id='#fdfdfd'>
<path <path
fill='#fdfdfd' fill='#fdfdfd'
opacity='1.00' opacity='1.00'
@@ -112,3 +126,4 @@ export const TorrentIcon = () => (
</g> </g>
</svg> </svg>
) )
}

View File

@@ -1,8 +1,105 @@
import { rgba } from 'polished'
export const themeColors = { export const themeColors = {
light: {}, light: {
dark: {}, app: {
headerToggleColor: '#4db380',
appSecondaryColor: '#f1eff3',
sidebarBGColor: '#575757',
sidebarFillColor: '#dee3e5',
},
torrentCard: {
accentCardColor: '#337a57',
buttonBGColor: rgba('#337a57', 0.5),
cardPrimaryColor: '#00a572',
cardSecondaryColor: '#74c39c',
},
dialogTorrentDetailsContent: {
posterBGColor: '#74c39c',
gradientStartColor: '#e4f6ed',
gradientEndColor: '#b5dec9',
chacheSectionBGColor: '#88cdaa',
fontColor: '#000',
subNameFontColor: '#7c7b7c',
torrentFilesSectionBGColor: '#f1eff3',
},
detailedView: {
gradientStartColor: '#e4f6ed',
gradientEndColor: '#b5dec9',
cacheSectionBGColor: '#fff',
},
addDialog: {
gradientStartColor: '#e4f6ed',
gradientEndColor: '#b5dec9',
fontColor: '#000',
notificationErrorBGColor: '#cda184',
notificationSuccessBGColor: '#88cdaa',
languageSwitchBGColor: '#74c39c',
languageSwitchFontColor: '#e4f6ed',
posterBGColor: '#74c39c',
},
torrentFunctions: {
fontColor: '#000',
},
table: {
defaultPrimaryColor: '#009879',
defaultSecondaryColor: '#00a383',
defaultTertiaryColor: '#03aa89',
},
},
dark: {
app: {
headerToggleColor: '#545a5e',
appSecondaryColor: '#545a5e',
sidebarBGColor: '#323637',
sidebarFillColor: '#dee3e5',
},
torrentCard: {
accentCardColor: '#323637',
buttonBGColor: rgba('#323637', 0.5),
cardPrimaryColor: '#545a5e',
cardSecondaryColor: rgba('#dee3e5', 0.4),
},
dialogTorrentDetailsContent: {
posterBGColor: rgba('#dee3e5', 0.4),
gradientStartColor: '#656f76',
gradientEndColor: '#545a5e',
chacheSectionBGColor: '#3c4244',
fontColor: '#f1eff3',
subNameFontColor: '#dee3e5',
torrentFilesSectionBGColor: rgba('#545a5e', 0.9),
},
detailedView: {
gradientStartColor: '#656f76',
gradientEndColor: '#545a5e',
cacheSectionBGColor: rgba('#545a5e', 0.7),
},
addDialog: {
gradientStartColor: '#656f76',
gradientEndColor: '#545a5e',
fontColor: '#fff',
notificationErrorBGColor: '#c82e3f',
notificationSuccessBGColor: '#323637',
languageSwitchBGColor: '#545a5e',
languageSwitchFontColor: '#dee3e5',
posterBGColor: '#dee3e5',
},
torrentFunctions: {
fontColor: '#f1eff3',
},
table: {
defaultPrimaryColor: '#323637',
defaultSecondaryColor: rgba('#545a5e', 0.9),
defaultTertiaryColor: '#545a5e',
},
},
} }
export const mainColors = { export const mainColors = {
light: {
primary: '#00a572', primary: '#00a572',
},
dark: {
primary: '#323637',
},
} }

View File

@@ -1,3 +1,3 @@
import { mainColors, themeColors } from './colors' import { mainColors, themeColors } from './colors'
export default type => ({ ...themeColors[type], ...mainColors }) export default type => ({ ...themeColors[type], ...mainColors[type] })

View File

@@ -1,45 +1,51 @@
import useMediaQuery from '@material-ui/core/useMediaQuery' import { createMuiTheme, useMediaQuery } from '@material-ui/core'
import { createMuiTheme } from '@material-ui/core' import { useEffect, useMemo, useState } from 'react'
import { useMemo } from 'react'
import { mainColors } from './colors' import { mainColors } from './colors'
const primary = { main: mainColors.primary }
const typography = { fontFamily: 'Open Sans, sans-serif' } const typography = { fontFamily: 'Open Sans, sans-serif' }
// https://material-ui.com/ru/customization/default-theme/
export const darkTheme = createMuiTheme({ export const darkTheme = createMuiTheme({
typography, typography,
palette: { palette: {
type: 'dark', type: 'dark',
background: { paper: '#575757' }, primary: { main: mainColors.dark.primary },
primary,
}, },
}) })
export const lightTheme = createMuiTheme({ export const lightTheme = createMuiTheme({
typography, typography,
palette: { palette: {
type: 'light', type: 'light',
background: { paper: '#f1f1f1' }, primary: { main: mainColors.light.primary },
primary,
}, },
}) })
export const THEME_MODES = { LIGHT: 'light', DARK: 'dark', AUTO: 'auto' }
export const useMaterialUITheme = () => { export const useMaterialUITheme = () => {
const isDarkMode = useMediaQuery('(prefers-color-scheme: dark)') const currentModeState = useMediaQuery('(prefers-color-scheme: dark)')
const [isDarkMode, setIsDarkMode] = useState(currentModeState)
const [currentThemeMode, setCurrentThemeMode] = useState(THEME_MODES.LIGHT)
useEffect(() => {
currentThemeMode === THEME_MODES.LIGHT && setIsDarkMode(false)
currentThemeMode === THEME_MODES.DARK && setIsDarkMode(true)
currentThemeMode === THEME_MODES.AUTO && setIsDarkMode(currentModeState)
}, [currentModeState, currentThemeMode])
const theme = isDarkMode ? THEME_MODES.DARK : THEME_MODES.LIGHT
const muiTheme = useMemo( const muiTheme = useMemo(
() => () =>
createMuiTheme({ createMuiTheme({
typography, typography,
palette: { palette: {
// type: isDarkMode ? 'dark' : 'light', type: theme,
type: 'light', primary: { main: mainColors[theme].primary },
primary,
}, },
}), }),
[], [theme],
) )
return [isDarkMode, muiTheme] return [isDarkMode, currentThemeMode, setCurrentThemeMode, muiTheme]
} }

View File

@@ -9416,6 +9416,13 @@ pnp-webpack-plugin@1.6.4:
dependencies: dependencies:
ts-pnp "^1.1.6" ts-pnp "^1.1.6"
polished@^4.1.3:
version "4.1.3"
resolved "https://registry.yarnpkg.com/polished/-/polished-4.1.3.tgz#7a3abf2972364e7d97770b827eec9a9e64002cfc"
integrity sha512-ocPAcVBUOryJEKe0z2KLd1l9EBa1r5mSwlKpExmrLzsnIzJo4axsoU9O2BjOTkDGDT4mZ0WFE5XKTlR3nLnZOA==
dependencies:
"@babel/runtime" "^7.14.0"
popper.js@1.16.1-lts: popper.js@1.16.1-lts:
version "1.16.1-lts" version "1.16.1-lts"
resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1-lts.tgz#cf6847b807da3799d80ee3d6d2f90df8a3f50b05" resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1-lts.tgz#cf6847b807da3799d80ee3d6d2f90df8a3f50b05"