From d5458a112e59fc57805704be3ebc109475345861 Mon Sep 17 00:00:00 2001 From: Daniel Shleifman Date: Sat, 26 Jun 2021 12:44:45 +0300 Subject: [PATCH 1/6] colors refactor --- .../Table/index.jsx | 30 +++++++------- .../Table/style.js | 39 ++++++++++++------- web/src/style/materialUISetup.js | 5 ++- 3 files changed, 43 insertions(+), 31 deletions(-) diff --git a/web/src/components/DialogTorrentDetailsContent/Table/index.jsx b/web/src/components/DialogTorrentDetailsContent/Table/index.jsx index 0837622..8a15bb1 100644 --- a/web/src/components/DialogTorrentDetailsContent/Table/index.jsx +++ b/web/src/components/DialogTorrentDetailsContent/Table/index.jsx @@ -60,22 +60,24 @@ const Table = memo( {fileHasEpisodeText && {episode}} {fileHasResolutionText && {resolution}} {humanizeSize(length)} - - - - - - - - - + + + + + + + + ) diff --git a/web/src/components/DialogTorrentDetailsContent/Table/style.js b/web/src/components/DialogTorrentDetailsContent/Table/style.js index acaa594..58705f2 100644 --- a/web/src/components/DialogTorrentDetailsContent/Table/style.js +++ b/web/src/components/DialogTorrentDetailsContent/Table/style.js @@ -1,11 +1,20 @@ 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 viewedSecondaryColor = '#c4c4c4' +const viewedTertiaryColor = '#c9c9c9' + const viewedIndicator = css` :before { content: ''; width: 10px; height: 10px; - background: #009879; + background: ${defaultPrimaryColor}; border-radius: 50%; position: absolute; top: 50%; @@ -23,7 +32,7 @@ export const TableStyle = styled.table` box-shadow: 0 0 20px rgba(0, 0, 0, 0.15); thead tr { - background: #009879; + background: ${defaultPrimaryColor}; color: #fff; text-align: left; text-transform: uppercase; @@ -35,14 +44,14 @@ export const TableStyle = styled.table` } tbody tr { - border-bottom: 1px solid #ddd; + border-bottom: 1px solid ${bigTableDividerColor}; :last-of-type { - border-bottom: 2px solid #009879; + border-bottom: 2px solid ${defaultPrimaryColor}; } &.viewed-file-row { - background: #f3f3f3; + background: ${bigTableViewedColor}; } } @@ -52,12 +61,12 @@ export const TableStyle = styled.table` ${viewedIndicator} } + } - &.button-cell { - display: grid; - grid-template-columns: repeat(3, 1fr); - gap: 10px; - } + .button-cell { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 10px; } @media (max-width: 970px) { @@ -91,7 +100,7 @@ export const ShortTable = styled.div` .short-table { &-name { - background: ${isViewed ? '#bdbdbd' : '#009879'}; + background: ${isViewed ? viewedPrimaryColor : defaultPrimaryColor}; display: grid; place-items: center; padding: 15px; @@ -116,11 +125,11 @@ export const ShortTable = styled.div` grid-template-rows: 30px 1fr; background: black; :not(:last-child) { - border-right: 1px solid ${isViewed ? '#bdbdbd' : '#009879'}; + border-right: 1px solid ${isViewed ? viewedPrimaryColor : defaultPrimaryColor}; } &-name { - background: ${isViewed ? '#c4c4c4' : '#00a383'}; + background: ${isViewed ? viewedSecondaryColor : defaultSecondaryColor}; color: #fff; text-transform: uppercase; font-size: 12px; @@ -135,7 +144,7 @@ export const ShortTable = styled.div` } &-value { - background: ${isViewed ? '#c9c9c9' : '#03aa89'}; + background: ${isViewed ? viewedTertiaryColor : defaultTertiaryColor}; display: grid; place-items: center; color: #fff; @@ -156,7 +165,7 @@ export const ShortTable = styled.div` &-buttons { padding: 20px; - border-bottom: 2px solid ${isViewed ? '#bdbdbd' : '#009879'}; + border-bottom: 2px solid ${isViewed ? viewedPrimaryColor : defaultPrimaryColor}; display: grid; grid-template-columns: repeat(3, 1fr); align-items: center; diff --git a/web/src/style/materialUISetup.js b/web/src/style/materialUISetup.js index 8d169d6..1d42903 100644 --- a/web/src/style/materialUISetup.js +++ b/web/src/style/materialUISetup.js @@ -33,11 +33,12 @@ export const useMaterialUITheme = () => { createMuiTheme({ typography, palette: { - type: isDarkMode ? 'dark' : 'light', + // type: isDarkMode ? 'dark' : 'light', + type: 'light', primary, }, }), - [isDarkMode], + [], ) return [isDarkMode, muiTheme] From 72ff729ee8bbc560c62826eedd44715ce46e14f2 Mon Sep 17 00:00:00 2001 From: Daniel Shleifman Date: Sat, 26 Jun 2021 21:31:43 +0300 Subject: [PATCH 2/6] added dark theme --- web/package.json | 1 + web/src/components/About.jsx | 7 +- web/src/components/Add/AddDialog.jsx | 120 ++++----- web/src/components/Add/RightSideComponent.jsx | 5 +- web/src/components/Add/style.js | 92 ++++--- web/src/components/App/Sidebar.jsx | 6 + web/src/components/App/index.jsx | 108 +++++--- web/src/components/App/style.js | 84 +++--- .../DetailedView/style.js | 36 ++- .../Table/style.js | 132 ++++++---- .../TorrentCache/index.jsx | 13 +- .../TorrentCache/snakeSettings.js | 73 ++++-- .../TorrentCache/style.js | 4 +- .../TorrentFunctions/style.js | 8 +- .../DialogTorrentDetailsContent/index.jsx | 8 +- .../DialogTorrentDetailsContent/style.js | 196 +++++++++----- web/src/components/TorrentCard/style.js | 247 ++++++++++-------- .../TorrentList/AddFirstTorrent.jsx | 5 +- .../TorrentList/NoServerConnection.jsx | 5 +- web/src/icons/index.jsx | 239 +++++++++-------- web/src/style/colors.js | 103 +++++++- web/src/style/getStyledComponentsTheme.js | 2 +- web/src/style/materialUISetup.js | 36 +-- web/yarn.lock | 7 + 24 files changed, 950 insertions(+), 587 deletions(-) diff --git a/web/package.json b/web/package.json index d166c66..67a8c88 100644 --- a/web/package.json +++ b/web/package.json @@ -13,6 +13,7 @@ "material-ui-image": "^3.3.2", "parse-torrent": "^9.1.3", "parse-torrent-title": "^1.3.0", + "polished": "^4.1.3", "react": "^17.0.2", "react-copy-to-clipboard": "^5.0.3", "react-div-100vh": "^0.6.0", diff --git a/web/src/components/About.jsx b/web/src/components/About.jsx index d4bc273..29f1def 100644 --- a/web/src/components/About.jsx +++ b/web/src/components/About.jsx @@ -11,13 +11,10 @@ import ListItemIcon from '@material-ui/core/ListItemIcon' import ListItemText from '@material-ui/core/ListItemText' import { useTranslation } from 'react-i18next' import { echoHost } from 'utils/Hosts' -import { ThemeProvider } from '@material-ui/core/styles' -import { mainColors } from 'style/colors' +import { ThemeProvider, useTheme } from '@material-ui/core/styles' import { lightTheme } from '../style/materialUISetup' -const { primary } = mainColors - export default function AboutDialog() { const { t } = useTranslation() const [open, setOpen] = useState(false) @@ -26,6 +23,8 @@ export default function AboutDialog() { axios.get(echoHost()).then(({ data }) => setTorrServerVersion(data)) }, []) + const primary = useTheme().palette.primary.main + return (
setOpen(true)}> diff --git a/web/src/components/Add/AddDialog.jsx b/web/src/components/Add/AddDialog.jsx index 73a2d2c..65262cf 100644 --- a/web/src/components/Add/AddDialog.jsx +++ b/web/src/components/Add/AddDialog.jsx @@ -12,8 +12,6 @@ import usePreviousState from 'utils/usePreviousState' import { useQuery } from 'react-query' import { getTorrents } from 'utils/Utils' 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 { ButtonWrapper, Content, Header } from './style' @@ -221,71 +219,69 @@ export default function AddDialog({ } return ( - - -
{t(isEditMode ? 'EditTorrent' : 'AddNewTorrent')}
+ +
{t(isEditMode ? 'EditTorrent' : 'AddNewTorrent')}
- - {!isEditMode && ( - - )} - - + {!isEditMode && ( + - + )} - - + + - - -
-
+ + + + + + ) } diff --git a/web/src/components/Add/RightSideComponent.jsx b/web/src/components/Add/RightSideComponent.jsx index 1b90b81..ea8c962 100644 --- a/web/src/components/Add/RightSideComponent.jsx +++ b/web/src/components/Add/RightSideComponent.jsx @@ -1,6 +1,6 @@ import { useTranslation } from 'react-i18next' 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 { @@ -41,6 +41,7 @@ export default function RightSideComponent({ isEditMode, }) { const { t } = useTranslation() + const primary = useTheme().palette.primary.main const handleTitleChange = ({ target: { value } }) => setTitle(value) const handlePosterUrlChange = ({ target: { value } }) => { @@ -91,7 +92,7 @@ export default function RightSideComponent({ setIsUserInteractedWithPoster(false) }} > - + ), diff --git a/web/src/components/Add/style.js b/web/src/components/Add/style.js index 7444a8b..d29809e 100644 --- a/web/src/components/Add/style.js +++ b/web/src/components/Add/style.js @@ -15,14 +15,20 @@ export const Header = styled.div` ` export const Content = styled.div` - ${({ isEditMode }) => css` + ${({ + isEditMode, + theme: { + addDialog: { gradientStartColor, gradientEndColor, fontColor }, + }, + }) => css` height: 550px; - background: linear-gradient(145deg, #e4f6ed, #b5dec9); + background: linear-gradient(145deg, ${gradientStartColor}, ${gradientEndColor}); flex: 1; display: grid; grid-template-columns: repeat(${isEditMode ? '1' : '2'}, 1fr); border-bottom: 1px solid rgba(0, 0, 0, 0.12); overflow: auto; + color: ${fontColor}; @media (max-width: 540px) { ${'' /* Just for bug fixing on small screens */} @@ -44,7 +50,14 @@ export const RightSide = styled.div` ` export const RightSideContainer = styled.div` - ${({ isHidden, notificationMessage, isError }) => css` + ${({ + isHidden, + notificationMessage, + isError, + theme: { + addDialog: { notificationErrorBGColor, notificationSuccessBGColor }, + }, + }) => css` height: 530px; ${notificationMessage && @@ -58,7 +71,7 @@ export const RightSideContainer = styled.div` content: '${notificationMessage}'; display: grid; place-items: center; - background: ${isError ? '#cda184' : '#88cdaa'}; + background: ${isError ? notificationErrorBGColor : notificationSuccessBGColor}; padding: 10px 15px; position: absolute; top: 52%; @@ -172,11 +185,18 @@ export const IconWrapper = styled.div` ` export const LeftSideTopSection = styled.div` - background: #e4f6ed; - padding: 0 20px 20px 20px; - transition: all 0.3s; + ${({ + active, + theme: { + addDialog: { gradientStartColor }, + }, + }) => css` + background: ${gradientStartColor}; + padding: 0 20px 20px 20px; + 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` @@ -254,7 +274,12 @@ export const PosterSuggestionsItem = styled.div` ` export const Poster = styled.div` - ${({ poster }) => css` + ${({ + poster, + theme: { + addDialog: { posterBGColor }, + }, + }) => css` border-radius: 5px; overflow: hidden; width: 200px; @@ -272,7 +297,7 @@ export const Poster = styled.div` : css` display: grid; place-items: center; - background: #74c39c; + background: ${posterBGColor}; svg { transform: scale(1.5) translateY(-3px); @@ -294,28 +319,35 @@ export const ClearPosterButton = styled(Button)` ` export const PosterLanguageSwitch = styled.div` - grid-area: poster; - z-index: 5; - position: absolute; - top: 0; - left: 50%; - transform: translate(-50%, -50%); - width: 30px; - height: 30px; - background: #74c39c; - border-radius: 50%; - display: grid; - place-items: center; - color: #e4f6ed; - font-weight: 600; - cursor: pointer; - transition: all 0.3s; + ${({ + showbutton, + theme: { + addDialog: { languageSwitchBGColor, languageSwitchFontColor }, + }, + }) => css` + grid-area: poster; + z-index: 5; + position: absolute; + top: 0; + left: 50%; + transform: translate(-50%, -50%); + width: 30px; + height: 30px; + background: ${languageSwitchBGColor}; + border-radius: 50%; + display: grid; + place-items: center; + color: ${languageSwitchFontColor}; + font-weight: 600; + cursor: pointer; + transition: all 0.3s; - ${({ showbutton }) => !showbutton && 'display: none'}; + ${!showbutton && 'display: none'}; - :hover { - filter: brightness(1.1); - } + :hover { + filter: brightness(1.1); + } + `} ` export const ButtonWrapper = styled.div` diff --git a/web/src/components/App/Sidebar.jsx b/web/src/components/App/Sidebar.jsx index 36a17ec..03e098b 100644 --- a/web/src/components/App/Sidebar.jsx +++ b/web/src/components/App/Sidebar.jsx @@ -21,18 +21,24 @@ const Sidebar = ({ isDrawerOpen, setIsDonationDialogOpen, isOffline, isLoading } + + + + + setIsDonationDialogOpen(true)}> + diff --git a/web/src/components/App/index.jsx b/web/src/components/App/index.jsx index d835286..66fe88d 100644 --- a/web/src/components/App/index.jsx +++ b/web/src/components/App/index.jsx @@ -1,8 +1,14 @@ 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 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 Div100vh from 'react-div-100vh' import axios from 'axios' @@ -16,18 +22,20 @@ import { useQuery } from 'react-query' import { getTorrents } from 'utils/Utils' import GlobalStyle from 'style/GlobalStyle' -import { AppWrapper, AppHeader, LanguageSwitch } from './style' +import { AppWrapper, AppHeader, HeaderToggle } from './style' import Sidebar from './Sidebar' -import { darkTheme, lightTheme, useMaterialUITheme } from '../../style/materialUISetup' +import { lightTheme, THEME_MODES, useMaterialUITheme } from '../../style/materialUISetup' import getStyledComponentsTheme from '../../style/getStyledComponentsTheme' +export const DarkModeContext = createContext() + export default function App() { const [isDrawerOpen, setIsDrawerOpen] = useState(false) const [isDonationDialogOpen, setIsDonationDialogOpen] = useState(false) const [torrServerVersion, setTorrServerVersion] = useState('') // https://material-ui.com/ru/customization/palette/ - const [isDarkMode, muiTheme] = useMaterialUITheme() + const [isDarkMode, currentThemeMode, setCurrentThemeMode, muiTheme] = useMaterialUITheme() const [currentLang, changeLang] = useChangeLanguage() const [isOffline, setIsOffline] = useState(false) const { data: torrents, isLoading } = useQuery('torrents', getTorrents, { @@ -45,54 +53,74 @@ export default function App() { <> - - - + + + + - {/* Div100vh - iOS WebKit fix */} - - - - setIsDrawerOpen(!isDrawerOpen)} - edge='start' - > - {isDrawerOpen ? : } - + {/* Div100vh - iOS WebKit fix */} + + + + setIsDrawerOpen(!isDrawerOpen)} + edge='start' + > + {isDrawerOpen ? : } + - - TorrServer {torrServerVersion} - + + TorrServer {torrServerVersion} + -
- (currentLang === 'en' ? changeLang('ru') : changeLang('en'))}> - {currentLang === 'en' ? 'RU' : 'EN'} - -
-
+
+ { + 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 ? ( + + ) : currentThemeMode === THEME_MODES.DARK ? ( + + ) : ( + + )} + + + (currentLang === 'en' ? changeLang('ru') : changeLang('en'))}> + {currentLang === 'en' ? 'RU' : 'EN'} + +
+
- - - + - - {isDonationDialogOpen && setIsDonationDialogOpen(false)} />} - + + {isDonationDialogOpen && setIsDonationDialogOpen(false)} />} + - {!JSON.parse(localStorage.getItem('snackbarIsClosed')) && } -
-
-
-
+ {!JSON.parse(localStorage.getItem('snackbarIsClosed')) && } + + +
+
+ ) } diff --git a/web/src/components/App/style.js b/web/src/components/App/style.js index 857af8d..c5700f1 100644 --- a/web/src/components/App/style.js +++ b/web/src/components/App/style.js @@ -1,14 +1,21 @@ +import { rgba } from 'polished' import styled, { css } from 'styled-components' export const AppWrapper = styled.div` - height: 100%; - background: #cbe8d9; - display: grid; - grid-template-columns: 60px 1fr; - grid-template-rows: 60px 1fr; - grid-template-areas: - 'head head' - 'side content'; + ${({ + theme: { + app: { appSecondaryColor }, + }, + }) => css` + height: 100%; + background: ${rgba(appSecondaryColor, 0.8)}; + display: grid; + grid-template-columns: 60px 1fr; + grid-template-rows: 60px 1fr; + grid-template-areas: + 'head head' + 'side content'; + `} ` export const CenteredGrid = styled.div` @@ -32,16 +39,25 @@ export const AppHeader = styled.div` `} ` export const AppSidebarStyle = styled.div` - ${({ isDrawerOpen }) => css` + ${({ + isDrawerOpen, + theme: { + app: { appSecondaryColor, sidebarBGColor, sidebarFillColor }, + }, + }) => css` grid-area: side; width: ${isDrawerOpen ? '400%' : '100%'}; z-index: 2; overflow-x: hidden; transition: width 195ms cubic-bezier(0.4, 0, 0.6, 1) 0ms; - border-right: 1px solid rgba(0, 0, 0, 0.12); - background: #575757; - color: #eee; + border-right: 1px solid ${rgba(appSecondaryColor, 0.12)}; + background: ${sidebarBGColor}; + color: ${sidebarFillColor}; white-space: nowrap; + + svg { + fill: ${sidebarFillColor}; + } `} ` export const TorrentListWrapper = styled.div` @@ -69,25 +85,31 @@ export const TorrentListWrapper = styled.div` } ` -export const LanguageSwitch = styled.div` - cursor: pointer; - border-radius: 50%; - background: #56b887; - height: 35px; - width: 35px; - transition: all 0.2s; - font-weight: 600; - display: grid; - place-items: center; - color: #fff; +export const HeaderToggle = styled.div` + ${({ + theme: { + app: { headerToggleColor }, + }, + }) => css` + cursor: pointer; + border-radius: 50%; + background: ${headerToggleColor}; + height: 35px; + width: 35px; + transition: all 0.2s; + font-weight: 600; + display: grid; + place-items: center; + color: #fff; - :hover { - background: #4db380; - } + :hover { + background: ${rgba(headerToggleColor, 0.9)}; + } - @media (max-width: 700px) { - height: 28px; - width: 28px; - font-size: 12px; - } + @media (max-width: 700px) { + height: 28px; + width: 28px; + font-size: 12px; + } + `} ` diff --git a/web/src/components/DialogTorrentDetailsContent/DetailedView/style.js b/web/src/components/DialogTorrentDetailsContent/DetailedView/style.js index 3fd9431..c3d6002 100644 --- a/web/src/components/DialogTorrentDetailsContent/DetailedView/style.js +++ b/web/src/components/DialogTorrentDetailsContent/DetailedView/style.js @@ -1,19 +1,33 @@ -import styled from 'styled-components' +import styled, { css } from 'styled-components' export const DetailedViewWidgetSection = styled.section` - padding: 40px; - background: linear-gradient(145deg, #e4f6ed, #b5dec9); + ${({ + theme: { + detailedView: { gradientStartColor, gradientEndColor }, + }, + }) => css` + padding: 40px; + background: linear-gradient(145deg, ${gradientStartColor}, ${gradientEndColor}); - @media (max-width: 800px) { - padding: 20px; - } + @media (max-width: 800px) { + padding: 20px; + } + `} ` export const DetailedViewCacheSection = styled.section` - padding: 40px; - box-shadow: inset 3px 25px 8px -25px rgba(0, 0, 0, 0.5); + ${({ + theme: { + detailedView: { cacheSectionBGColor }, + }, + }) => css` + padding: 40px; + box-shadow: inset 3px 25px 8px -25px rgba(0, 0, 0, 0.5); + background: ${cacheSectionBGColor}; + flex: 1; - @media (max-width: 800px) { - padding: 20px; - } + @media (max-width: 800px) { + padding: 20px; + } + `} ` diff --git a/web/src/components/DialogTorrentDetailsContent/Table/style.js b/web/src/components/DialogTorrentDetailsContent/Table/style.js index 58705f2..a9079c4 100644 --- a/web/src/components/DialogTorrentDetailsContent/Table/style.js +++ b/web/src/components/DialogTorrentDetailsContent/Table/style.js @@ -1,77 +1,89 @@ 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 viewedSecondaryColor = '#c4c4c4' const viewedTertiaryColor = '#c9c9c9' +const bigTableDividerColor = '#ddd' +const bigTableDefaultRowColor = '#fff' +const bigTableViewedRowColor = '#f3f3f3' const viewedIndicator = css` - :before { - content: ''; - width: 10px; - height: 10px; - background: ${defaultPrimaryColor}; - border-radius: 50%; - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - } + ${({ + theme: { + table: { defaultPrimaryColor }, + }, + }) => css` + :before { + content: ''; + width: 10px; + height: 10px; + background: ${defaultPrimaryColor}; + border-radius: 50%; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + } + `} ` export const TableStyle = styled.table` - border-collapse: collapse; - margin: 25px 0; - font-size: 0.9em; - width: 100%; - border-radius: 5px 5px 0 0; - overflow: hidden; - box-shadow: 0 0 20px rgba(0, 0, 0, 0.15); + ${({ + theme: { + table: { defaultPrimaryColor }, + }, + }) => css` + border-collapse: collapse; + margin: 25px 0; + font-size: 0.9em; + width: 100%; + border-radius: 5px 5px 0 0; + overflow: hidden; + box-shadow: 0 0 20px rgba(0, 0, 0, 0.15); + color: #000; - thead tr { - background: ${defaultPrimaryColor}; - color: #fff; - text-align: left; - text-transform: uppercase; - } - - th, - td { - padding: 12px 15px; - } - - tbody tr { - border-bottom: 1px solid ${bigTableDividerColor}; - - :last-of-type { - border-bottom: 2px solid ${defaultPrimaryColor}; + thead tr { + background: ${defaultPrimaryColor}; + color: #fff; + text-align: left; + text-transform: uppercase; } - &.viewed-file-row { - background: ${bigTableViewedColor}; + th, + td { + padding: 12px 15px; } - } - td { - &.viewed-file-indicator { - position: relative; + tbody tr { + border-bottom: 1px solid ${bigTableDividerColor}; + background: ${bigTableDefaultRowColor}; - ${viewedIndicator} + :last-of-type { + border-bottom: 2px solid ${defaultPrimaryColor}; + } + + &.viewed-file-row { + background: ${bigTableViewedRowColor}; + } } - } - .button-cell { - display: grid; - grid-template-columns: repeat(3, 1fr); - gap: 10px; - } + td { + &.viewed-file-indicator { + position: relative; - @media (max-width: 970px) { - display: none; - } + ${viewedIndicator} + } + } + + .button-cell { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 10px; + } + + @media (max-width: 970px) { + display: none; + } + `} ` export const ShortTableWrapper = styled.div` @@ -91,7 +103,12 @@ export const ShortTableWrapper = styled.div` ` export const ShortTable = styled.div` - ${({ isViewed }) => css` + ${({ + isViewed, + theme: { + table: { defaultPrimaryColor, defaultSecondaryColor, defaultTertiaryColor }, + }, + }) => css` width: 100%; grid-template-rows: repeat(3, max-content); border-radius: 5px; @@ -170,6 +187,7 @@ export const ShortTable = styled.div` grid-template-columns: repeat(3, 1fr); align-items: center; gap: 20px; + background: #fff; @media (max-width: 410px) { gap: 10px; diff --git a/web/src/components/DialogTorrentDetailsContent/TorrentCache/index.jsx b/web/src/components/DialogTorrentDetailsContent/TorrentCache/index.jsx index 451094b..b66e6b8 100644 --- a/web/src/components/DialogTorrentDetailsContent/TorrentCache/index.jsx +++ b/web/src/components/DialogTorrentDetailsContent/TorrentCache/index.jsx @@ -1,7 +1,8 @@ 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 isEqual from 'lodash/isEqual' +import { DarkModeContext } from 'components/App' import { useCreateCacheMap } from '../customHooks' import getShortCacheMap from './getShortCacheMap' @@ -16,6 +17,9 @@ const TorrentCache = ({ cache, isMini }) => { const ctxRef = useRef(null) const cacheMap = useCreateCacheMap(cache) const settingsTarget = isMini ? 'mini' : 'default' + const { isDarkMode } = useContext(DarkModeContext) + const theme = isDarkMode ? 'dark' : 'light' + const { readerColor, rangeColor, @@ -26,7 +30,7 @@ const TorrentCache = ({ cache, isMini }) => { borderColor, cacheMaxHeight, completeColor, - } = snakeSettings[settingsTarget] + } = snakeSettings[theme][settingsTarget] const canvasWidth = isMini ? width * 0.93 : width @@ -69,7 +73,7 @@ const TorrentCache = ({ cache, isMini }) => { ctx.lineWidth = borderWidth ctx.fillStyle = inProgress - ? createGradient(ctx, percentage, settingsTarget) + ? createGradient(ctx, percentage, theme, settingsTarget) : isCompleted ? completeColor : backgroundColor @@ -102,13 +106,14 @@ const TorrentCache = ({ cache, isMini }) => { completeColor, readerColor, rangeColor, + theme, ]) return ( setDimensions(bounds)}> {({ measureRef }) => (
- + diff --git a/web/src/components/DialogTorrentDetailsContent/TorrentCache/snakeSettings.js b/web/src/components/DialogTorrentDetailsContent/TorrentCache/snakeSettings.js index a567066..4f79f27 100644 --- a/web/src/components/DialogTorrentDetailsContent/TorrentCache/snakeSettings.js +++ b/web/src/components/DialogTorrentDetailsContent/TorrentCache/snakeSettings.js @@ -1,33 +1,60 @@ import { mainColors } from 'style/colors' export const snakeSettings = { - default: { - borderWidth: 1, - pieceSize: 14, - gapBetweenPieces: 3, - borderColor: '#dbf2e8', - completeColor: mainColors.primary, - backgroundColor: '#fff', - progressColor: '#b3dfc9', - readerColor: '#000', - rangeColor: '#afa6e3', + 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', + }, }, - mini: { - cacheMaxHeight: 340, - borderWidth: 2, - pieceSize: 23, - gapBetweenPieces: 6, - borderColor: '#4db380', - completeColor: '#4db380', - backgroundColor: '#dbf2e8', - progressColor: '#dbf2e8', - readerColor: '#2d714f', - rangeColor: '#afa6e3', + light: { + default: { + borderWidth: 1, + pieceSize: 14, + gapBetweenPieces: 3, + borderColor: '#dbf2e8', + completeColor: mainColors.light.primary, + backgroundColor: '#fff', + progressColor: '#b3dfc9', + readerColor: '#000', + rangeColor: '#afa6e3', + }, + mini: { + cacheMaxHeight: 340, + borderWidth: 2, + pieceSize: 23, + gapBetweenPieces: 6, + borderColor: '#4db380', + completeColor: '#4db380', + backgroundColor: '#dbf2e8', + progressColor: '#dbf2e8', + readerColor: '#2d714f', + rangeColor: '#afa6e3', + }, }, } -export const createGradient = (ctx, percentage, snakeType) => { - const { pieceSize, completeColor, progressColor } = snakeSettings[snakeType] +export const createGradient = (ctx, percentage, theme, snakeType) => { + const { pieceSize, completeColor, progressColor } = snakeSettings[theme][snakeType] const gradient = ctx.createLinearGradient(0, pieceSize, 0, 0) gradient.addColorStop(0, completeColor) diff --git a/web/src/components/DialogTorrentDetailsContent/TorrentCache/style.js b/web/src/components/DialogTorrentDetailsContent/TorrentCache/style.js index ace99fc..af461e5 100644 --- a/web/src/components/DialogTorrentDetailsContent/TorrentCache/style.js +++ b/web/src/components/DialogTorrentDetailsContent/TorrentCache/style.js @@ -10,12 +10,12 @@ export const ScrollNotification = styled.div` ` export const SnakeWrapper = styled.div` - ${({ isMini }) => css` + ${({ isMini, themeType }) => css` ${isMini && css` display: grid; justify-content: center; - max-height: ${snakeSettings.mini.cacheMaxHeight}px; + max-height: ${snakeSettings[themeType].mini.cacheMaxHeight}px; overflow: auto; `} diff --git a/web/src/components/DialogTorrentDetailsContent/TorrentFunctions/style.js b/web/src/components/DialogTorrentDetailsContent/TorrentFunctions/style.js index 0955c5e..f8acc9d 100644 --- a/web/src/components/DialogTorrentDetailsContent/TorrentFunctions/style.js +++ b/web/src/components/DialogTorrentDetailsContent/TorrentFunctions/style.js @@ -19,11 +19,17 @@ export const MainSectionButtonGroup = styled.div` ` export const SmallLabel = styled.div` - ${({ mb }) => css` + ${({ + mb, + theme: { + torrentFunctions: { fontColor }, + }, + }) => css` ${mb && `margin-bottom: ${mb}px`}; font-size: 20px; font-weight: 300; line-height: 1; + color: ${fontColor}; @media (max-width: 800px) { font-size: 18px; diff --git a/web/src/components/DialogTorrentDetailsContent/index.jsx b/web/src/components/DialogTorrentDetailsContent/index.jsx index 8a4140f..3df8f30 100644 --- a/web/src/components/DialogTorrentDetailsContent/index.jsx +++ b/web/src/components/DialogTorrentDetailsContent/index.jsx @@ -133,7 +133,13 @@ export default function DialogTorrentDetailsContent({ closeDialog, torrent }) { {...(isDetailedCacheView && { onBack: () => setIsDetailedCacheView(false) })} /> -
+
{isLoading ? ( ) : isDetailedCacheView ? ( diff --git a/web/src/components/DialogTorrentDetailsContent/style.js b/web/src/components/DialogTorrentDetailsContent/style.js index 4884967..261c57e 100644 --- a/web/src/components/DialogTorrentDetailsContent/style.js +++ b/web/src/components/DialogTorrentDetailsContent/style.js @@ -1,3 +1,4 @@ +import { rgba } from 'polished' import styled, { css } from 'styled-components' export const DialogContentGrid = styled.div` @@ -18,7 +19,12 @@ export const DialogContentGrid = styled.div` } ` export const Poster = styled.div` - ${({ poster }) => css` + ${({ + poster, + theme: { + dialogTorrentDetailsContent: { posterBGColor }, + }, + }) => css` height: 400px; border-radius: 5px; overflow: hidden; @@ -35,7 +41,7 @@ export const Poster = styled.div` width: 300px; display: grid; place-items: center; - background: #74c39c; + background: ${posterBGColor}; svg { transform: scale(2.5) translateY(-3px); @@ -58,72 +64,104 @@ export const Poster = styled.div` `} ` export const MainSection = styled.section` - grid-area: main; - padding: 40px; - display: grid; - grid-template-columns: min-content 1fr; - gap: 30px; - background: linear-gradient(145deg, #e4f6ed, #b5dec9); + ${({ + theme: { + dialogTorrentDetailsContent: { gradientStartColor, gradientEndColor }, + }, + }) => css` + grid-area: main; + padding: 40px; + display: grid; + grid-template-columns: min-content 1fr; + gap: 30px; + background: linear-gradient(145deg, ${gradientStartColor}, ${gradientEndColor}); - @media (max-width: 840px) { - grid-template-columns: 1fr; - } - - @media (max-width: 800px) { - padding: 20px; - } -` - -export const CacheSection = styled.section` - grid-area: cache; - padding: 40px; - display: grid; - align-content: start; - grid-template-rows: min-content 1fr min-content; - background: #88cdaa; - - @media (max-width: 800px) { - padding: 20px; - } -` - -export const TorrentFilesSection = styled.section` - grid-area: file-list; - padding: 40px; - box-shadow: inset 3px 25px 8px -25px rgba(0, 0, 0, 0.5); - - @media (max-width: 800px) { - padding: 20px; - } -` - -export const SectionSubName = styled.div` - ${({ mb }) => css` - ${mb && `margin-bottom: ${mb}px`}; - color: #7c7b7c; + @media (max-width: 840px) { + grid-template-columns: 1fr; + } @media (max-width: 800px) { - ${mb && `margin-bottom: ${mb / 2}px`}; - font-size: 11px; + padding: 20px; } `} ` -export const SectionTitle = styled.div` - ${({ mb }) => css` - ${mb && `margin-bottom: ${mb}px`}; - font-size: 35px; - font-weight: 300; - line-height: 1; - word-break: break-word; +export const CacheSection = styled.section` + ${({ + theme: { + dialogTorrentDetailsContent: { chacheSectionBGColor }, + }, + }) => css` + grid-area: cache; + padding: 40px; + display: grid; + align-content: start; + grid-template-rows: min-content 1fr min-content; + background: ${chacheSectionBGColor}; @media (max-width: 800px) { - font-size: 25px; - ${mb && `margin-bottom: ${mb / 2}px`}; + padding: 20px; } `} ` +export const TorrentFilesSection = styled.section` + ${({ + theme: { + dialogTorrentDetailsContent: { torrentFilesSectionBGColor }, + }, + }) => css` + grid-area: file-list; + padding: 40px; + box-shadow: inset 3px 25px 8px -25px rgba(0, 0, 0, 0.5); + background: ${torrentFilesSectionBGColor}; + + @media (max-width: 800px) { + padding: 20px; + } + `} +` + +export const SectionSubName = styled.div` + ${({ + theme: { + dialogTorrentDetailsContent: { subNameFontColor }, + }, + }) => css` + ${({ mb }) => css` + ${mb && `margin-bottom: ${mb}px`}; + color: ${subNameFontColor}; + + @media (max-width: 800px) { + ${mb && `margin-bottom: ${mb / 2}px`}; + font-size: 11px; + } + `} + `} +` + +export const SectionTitle = styled.div` + ${({ + theme: { + dialogTorrentDetailsContent: { fontColor }, + }, + }) => css` + ${({ mb }) => css` + ${mb && `margin-bottom: ${mb}px`}; + font-size: 35px; + font-weight: 300; + line-height: 1; + word-break: break-word; + color: ${fontColor}; + + @media (max-width: 800px) { + font-size: 25px; + ${mb && `margin-bottom: ${mb / 2}px`}; + } + `} + `} +` + export const SectionHeader = styled.div` margin-bottom: 20px; ` @@ -182,18 +220,25 @@ export const WidgetFieldWrapper = styled.div` } ` export const WidgetFieldTitle = styled.div` - grid-area: title; - justify-self: start; - text-transform: uppercase; - font-size: 11px; - margin-bottom: 2px; - font-weight: 600; + ${({ + theme: { + dialogTorrentDetailsContent: { fontColor }, + }, + }) => css` + grid-area: title; + justify-self: start; + text-transform: uppercase; + font-size: 11px; + margin-bottom: 2px; + font-weight: 600; + color: ${fontColor}; + `} ` export const WidgetFieldIcon = styled.div` ${({ bgColor }) => css` grid-area: icon; - color: rgba(255, 255, 255, 0.8); + color: ${rgba('#fff', 0.8)}; background: ${bgColor}; border-radius: 5px 0 0 5px; @@ -220,20 +265,29 @@ export const WidgetFieldValue = styled.div` `} ` -export const LoadingProgress = styled.div.attrs(({ value, fullAmount }) => { - const percentage = Math.min(100, (value * 100) / fullAmount) - - return { - // this block is here according to styled-components recomendation about fast changable components - style: { - background: `linear-gradient(to right, #b5dec9 0%, #b5dec9 ${percentage}%, #fff ${percentage}%, #fff 100%)`, +export const LoadingProgress = styled.div.attrs( + ({ + value, + fullAmount, + theme: { + dialogTorrentDetailsContent: { gradientEndColor }, }, - } -})` + }) => { + const percentage = Math.min(100, (value * 100) / fullAmount) + + return { + // this block is here according to styled-components recomendation about fast changable components + style: { + background: `linear-gradient(to right, ${gradientEndColor} 0%, ${gradientEndColor} ${percentage}%, #fff ${percentage}%, #fff 100%)`, + }, + } + }, +)` ${({ label }) => css` border: 1px solid; padding: 10px 20px; border-radius: 5px; + color: #000; :before { content: '${label}'; diff --git a/web/src/components/TorrentCard/style.js b/web/src/components/TorrentCard/style.js index 2f721c9..bbc4eb7 100644 --- a/web/src/components/TorrentCard/style.js +++ b/web/src/components/TorrentCard/style.js @@ -1,7 +1,11 @@ import styled, { css } from 'styled-components' export const TorrentCard = styled.div` - ${({ theme: { primary } }) => css` + ${({ + theme: { + torrentCard: { cardPrimaryColor }, + }, + }) => css` border-radius: 5px; display: grid; grid-template-columns: 120px 260px 1fr; @@ -9,7 +13,7 @@ export const TorrentCard = styled.div` grid-template-areas: 'poster description buttons'; gap: 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%); @media (max-width: 1260px), (max-height: 500px) { @@ -34,7 +38,12 @@ export const TorrentCardPoster = styled.div` overflow: hidden; text-align: center; - ${({ isPoster }) => + ${({ + isPoster, + theme: { + torrentCard: { cardSecondaryColor, accentCardColor }, + }, + }) => isPoster ? css` img { @@ -47,8 +56,8 @@ export const TorrentCardPoster = styled.div` : css` display: grid; place-items: center; - background: #74c39c; - border: 1px solid #337a57; + background: ${cardSecondaryColor}; + border: 1px solid ${accentCardColor}; svg { transform: translateY(-3px); @@ -76,128 +85,140 @@ export const TorrentCardButtons = styled.div` } ` export const TorrentCardDescription = styled.div` - grid-area: description; - background: #74c39c; - border-radius: 5px; - padding: 5px; - display: grid; - grid-template-rows: 55% 1fr; - gap: 10px; - - @media (max-width: 770px) { - grid-template-rows: 60% 1fr; - gap: 3px; - } - - .description-title-wrapper { - display: flex; - flex-direction: column; - } - - .description-section-name { - text-transform: uppercase; - font-size: 10px; - font-weight: 600; - letter-spacing: 0.4px; - color: #337a57; - - @media (max-width: 770px) { - font-size: 0.4rem; - } - } - - .description-torrent-title { - overflow: auto; - word-break: break-all; - } - - .description-statistics-wrapper { + ${({ + theme: { + torrentCard: { cardSecondaryColor, accentCardColor }, + }, + }) => css` + grid-area: description; + background: ${cardSecondaryColor}; + border-radius: 5px; + padding: 5px; display: grid; - grid-template-columns: 80px 80px 1fr; - align-self: end; - - @media (max-width: 1260px), (max-height: 500px) { - grid-template-columns: 70px 70px 1fr; - } + grid-template-rows: 55% 1fr; + gap: 10px; @media (max-width: 770px) { - grid-template-columns: 65px 65px 1fr; + grid-template-rows: 60% 1fr; + gap: 3px; } - @media (max-width: 700px) { - display: grid; - grid-template-columns: repeat(3, 1fr); - } - } - - .description-statistics-element-wrapper { - } - - .description-statistics-element-value { - margin-left: 5px; - margin-bottom: 10px; - word-break: break-all; - - @media (max-width: 1260px), (max-height: 500px) { - font-size: 0.7rem; - margin-bottom: 0; - margin-left: 0; - } - } - - .description-torrent-title, - .description-statistics-element-value { - @media (max-width: 770px) { - font-size: 0.6rem; + .description-title-wrapper { + display: flex; + flex-direction: column; } - @media (max-width: 410px) { + .description-section-name { + text-transform: uppercase; font-size: 10px; + font-weight: 600; + letter-spacing: 0.4px; + color: ${accentCardColor}; + + @media (max-width: 770px) { + font-size: 0.4rem; + } } - } + + .description-torrent-title { + overflow: auto; + word-break: break-all; + } + + .description-statistics-wrapper { + display: grid; + grid-template-columns: 80px 80px 1fr; + align-self: end; + + @media (max-width: 1260px), (max-height: 500px) { + grid-template-columns: 70px 70px 1fr; + } + + @media (max-width: 770px) { + grid-template-columns: 65px 65px 1fr; + } + + @media (max-width: 700px) { + display: grid; + grid-template-columns: repeat(3, 1fr); + } + } + + .description-statistics-element-wrapper { + } + + .description-statistics-element-value { + margin-left: 5px; + margin-bottom: 10px; + word-break: break-all; + + @media (max-width: 1260px), (max-height: 500px) { + font-size: 0.7rem; + margin-bottom: 0; + margin-left: 0; + } + } + + .description-torrent-title, + .description-statistics-element-value { + @media (max-width: 770px) { + font-size: 0.6rem; + } + + @media (max-width: 410px) { + font-size: 10px; + } + } + `} ` export const StyledButton = styled.button` - border-radius: 5px; - border: none; - cursor: pointer; - transition: 0.2s; - display: flex; - align-items: center; - text-transform: uppercase; - background: #268757; - color: #fff; - font-size: 0.9rem; - letter-spacing: 0.009em; - padding: 0 12px; - svg { - width: 20px; - } - - :hover { - background: #337a57; - } - - > :first-child { - margin-right: 10px; - } - - @media (max-width: 1260px), (max-height: 500px) { - padding: 7px 10px; - justify-content: center; - font-size: 0.8rem; - + ${({ + theme: { + torrentCard: { buttonBGColor, accentCardColor }, + }, + }) => css` + border-radius: 5px; + border: none; + cursor: pointer; + transition: 0.2s; + display: flex; + align-items: center; + text-transform: uppercase; + background: ${buttonBGColor}; + color: #fff; + font-size: 0.9rem; + letter-spacing: 0.009em; + padding: 0 12px; svg { - display: none; + width: 20px; } - } - @media (max-width: 770px) { - font-size: 0.7rem; - } + :hover { + background: ${accentCardColor}; + } - @media (max-width: 420px) { - font-size: 0.6rem; - padding: 7px 5px; - } + > :first-child { + margin-right: 10px; + } + + @media (max-width: 1260px), (max-height: 500px) { + padding: 7px 10px; + justify-content: center; + font-size: 0.8rem; + + svg { + display: none; + } + } + + @media (max-width: 770px) { + font-size: 0.7rem; + } + + @media (max-width: 420px) { + font-size: 0.6rem; + padding: 7px 5px; + } + `} ` diff --git a/web/src/components/TorrentList/AddFirstTorrent.jsx b/web/src/components/TorrentList/AddFirstTorrent.jsx index f2d856d..68f509c 100644 --- a/web/src/components/TorrentList/AddFirstTorrent.jsx +++ b/web/src/components/TorrentList/AddFirstTorrent.jsx @@ -1,6 +1,6 @@ +import { useTheme } from '@material-ui/core' import { useState } from 'react' import { useTranslation } from 'react-i18next' -import { mainColors } from 'style/colors' import AddDialog from '../Add/AddDialog' import IconWrapper from './style' @@ -10,6 +10,7 @@ export default function AddFirstTorrent() { const [isDialogOpen, setIsDialogOpen] = useState(false) const handleClickOpen = () => setIsDialogOpen(true) const handleClose = () => setIsDialogOpen(false) + const primary = useTheme().palette.primary.main return ( <> @@ -17,7 +18,7 @@ export default function AddFirstTorrent() { diff --git a/web/src/components/TorrentList/NoServerConnection.jsx b/web/src/components/TorrentList/NoServerConnection.jsx index ce354d3..c3d05e8 100644 --- a/web/src/components/TorrentList/NoServerConnection.jsx +++ b/web/src/components/TorrentList/NoServerConnection.jsx @@ -1,17 +1,18 @@ +import { useTheme } from '@material-ui/core' import { useTranslation } from 'react-i18next' -import { mainColors } from 'style/colors' import IconWrapper from './style' export default function NoServerConnection() { const { t } = useTranslation() + const primary = useTheme().palette.primary.main return ( diff --git a/web/src/icons/index.jsx b/web/src/icons/index.jsx index f8c792e..914e109 100644 --- a/web/src/icons/index.jsx +++ b/web/src/icons/index.jsx @@ -1,114 +1,129 @@ -export const NoImageIcon = () => ( - - - - - - - -) +import { useTheme } from '@material-ui/core' -export const AddItemIcon = () => ( - - - - - - -) +export const NoImageIcon = ({ color }) => { + const primary = useTheme().palette.primary.main -export const TorrentIcon = () => ( - - - - - - - - - - - - - - - - - - - - -) + return ( + + + + + + + + ) +} + +export const AddItemIcon = () => { + const primary = useTheme().palette.primary.main + + return ( + + + + + + + ) +} + +export const TorrentIcon = () => { + const primary = useTheme().palette.primary.main + const secondaryColor = primary === '#00a572' ? '#74c39c' : '#4a5255' + + return ( + + + + + + + + + + + + + + + + + + + + + ) +} diff --git a/web/src/style/colors.js b/web/src/style/colors.js index 7ea161b..a7dce73 100644 --- a/web/src/style/colors.js +++ b/web/src/style/colors.js @@ -1,8 +1,105 @@ +import { rgba } from 'polished' + export const themeColors = { - light: {}, - dark: {}, + light: { + 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 = { - primary: '#00a572', + light: { + primary: '#00a572', + }, + dark: { + primary: '#323637', + }, } diff --git a/web/src/style/getStyledComponentsTheme.js b/web/src/style/getStyledComponentsTheme.js index f9a019e..cf6b338 100644 --- a/web/src/style/getStyledComponentsTheme.js +++ b/web/src/style/getStyledComponentsTheme.js @@ -1,3 +1,3 @@ import { mainColors, themeColors } from './colors' -export default type => ({ ...themeColors[type], ...mainColors }) +export default type => ({ ...themeColors[type], ...mainColors[type] }) diff --git a/web/src/style/materialUISetup.js b/web/src/style/materialUISetup.js index 1d42903..dada4a7 100644 --- a/web/src/style/materialUISetup.js +++ b/web/src/style/materialUISetup.js @@ -1,45 +1,51 @@ -import useMediaQuery from '@material-ui/core/useMediaQuery' -import { createMuiTheme } from '@material-ui/core' -import { useMemo } from 'react' +import { createMuiTheme, useMediaQuery } from '@material-ui/core' +import { useEffect, useMemo, useState } from 'react' import { mainColors } from './colors' -const primary = { main: mainColors.primary } const typography = { fontFamily: 'Open Sans, sans-serif' } -// https://material-ui.com/ru/customization/default-theme/ export const darkTheme = createMuiTheme({ typography, palette: { type: 'dark', - background: { paper: '#575757' }, - primary, + primary: { main: mainColors.dark.primary }, }, }) export const lightTheme = createMuiTheme({ typography, palette: { type: 'light', - background: { paper: '#f1f1f1' }, - primary, + primary: { main: mainColors.light.primary }, }, }) +export const THEME_MODES = { LIGHT: 'light', DARK: 'dark', AUTO: 'auto' } + 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( () => createMuiTheme({ typography, palette: { - // type: isDarkMode ? 'dark' : 'light', - type: 'light', - primary, + type: theme, + primary: { main: mainColors[theme].primary }, }, }), - [], + [theme], ) - return [isDarkMode, muiTheme] + return [isDarkMode, currentThemeMode, setCurrentThemeMode, muiTheme] } diff --git a/web/yarn.lock b/web/yarn.lock index 3d65690..0fa0ddd 100644 --- a/web/yarn.lock +++ b/web/yarn.lock @@ -9416,6 +9416,13 @@ pnp-webpack-plugin@1.6.4: dependencies: 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: version "1.16.1-lts" resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1-lts.tgz#cf6847b807da3799d80ee3d6d2f90df8a3f50b05" From ca4f78120cdbcec855ed13335fe1267b8290b7cc Mon Sep 17 00:00:00 2001 From: Daniel Shleifman Date: Sat, 26 Jun 2021 21:47:33 +0300 Subject: [PATCH 3/6] added theme switcher --- web/src/components/App/index.jsx | 11 ++++++++--- .../TorrentCache/index.jsx | 3 ++- web/src/style/materialUISetup.js | 19 ++++++++++--------- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/web/src/components/App/index.jsx b/web/src/components/App/index.jsx index 66fe88d..d40b350 100644 --- a/web/src/components/App/index.jsx +++ b/web/src/components/App/index.jsx @@ -82,9 +82,14 @@ export default function App() { > { - currentThemeMode === THEME_MODES.LIGHT && setCurrentThemeMode(THEME_MODES.DARK) - currentThemeMode === THEME_MODES.DARK && setCurrentThemeMode(THEME_MODES.AUTO) - currentThemeMode === THEME_MODES.AUTO && setCurrentThemeMode(THEME_MODES.LIGHT) + const updateThemeMode = mode => { + setCurrentThemeMode(mode) + localStorage.setItem('themeMode', mode) + } + + if (currentThemeMode === THEME_MODES.LIGHT) updateThemeMode(THEME_MODES.DARK) + if (currentThemeMode === THEME_MODES.DARK) updateThemeMode(THEME_MODES.AUTO) + if (currentThemeMode === THEME_MODES.AUTO) updateThemeMode(THEME_MODES.LIGHT) }} > {currentThemeMode === THEME_MODES.LIGHT ? ( diff --git a/web/src/components/DialogTorrentDetailsContent/TorrentCache/index.jsx b/web/src/components/DialogTorrentDetailsContent/TorrentCache/index.jsx index b66e6b8..fce00ce 100644 --- a/web/src/components/DialogTorrentDetailsContent/TorrentCache/index.jsx +++ b/web/src/components/DialogTorrentDetailsContent/TorrentCache/index.jsx @@ -3,6 +3,7 @@ import { useState, memo, useRef, useEffect, useContext } from 'react' import { useTranslation } from 'react-i18next' import isEqual from 'lodash/isEqual' import { DarkModeContext } from 'components/App' +import { THEME_MODES } from 'style/materialUISetup' import { useCreateCacheMap } from '../customHooks' import getShortCacheMap from './getShortCacheMap' @@ -18,7 +19,7 @@ const TorrentCache = ({ cache, isMini }) => { const cacheMap = useCreateCacheMap(cache) const settingsTarget = isMini ? 'mini' : 'default' const { isDarkMode } = useContext(DarkModeContext) - const theme = isDarkMode ? 'dark' : 'light' + const theme = isDarkMode ? THEME_MODES.DARK : THEME_MODES.LIGHT const { readerColor, diff --git a/web/src/style/materialUISetup.js b/web/src/style/materialUISetup.js index dada4a7..4587cfe 100644 --- a/web/src/style/materialUISetup.js +++ b/web/src/style/materialUISetup.js @@ -3,35 +3,36 @@ import { useEffect, useMemo, useState } from 'react' import { mainColors } from './colors' +export const THEME_MODES = { LIGHT: 'light', DARK: 'dark', AUTO: 'auto' } + const typography = { fontFamily: 'Open Sans, sans-serif' } export const darkTheme = createMuiTheme({ typography, palette: { - type: 'dark', + type: THEME_MODES.DARK, primary: { main: mainColors.dark.primary }, }, }) export const lightTheme = createMuiTheme({ typography, palette: { - type: 'light', + type: THEME_MODES.LIGHT, primary: { main: mainColors.light.primary }, }, }) -export const THEME_MODES = { LIGHT: 'light', DARK: 'dark', AUTO: 'auto' } - export const useMaterialUITheme = () => { - const currentModeState = useMediaQuery('(prefers-color-scheme: dark)') - const [isDarkMode, setIsDarkMode] = useState(currentModeState) - const [currentThemeMode, setCurrentThemeMode] = useState(THEME_MODES.LIGHT) + const savedThemeMode = localStorage.getItem('themeMode') + const isSystemModeDark = useMediaQuery('(prefers-color-scheme: dark)') + const [isDarkMode, setIsDarkMode] = useState(savedThemeMode === 'dark' || isSystemModeDark) + const [currentThemeMode, setCurrentThemeMode] = useState(savedThemeMode || THEME_MODES.LIGHT) useEffect(() => { currentThemeMode === THEME_MODES.LIGHT && setIsDarkMode(false) currentThemeMode === THEME_MODES.DARK && setIsDarkMode(true) - currentThemeMode === THEME_MODES.AUTO && setIsDarkMode(currentModeState) - }, [currentModeState, currentThemeMode]) + currentThemeMode === THEME_MODES.AUTO && setIsDarkMode(isSystemModeDark) + }, [isSystemModeDark, currentThemeMode]) const theme = isDarkMode ? THEME_MODES.DARK : THEME_MODES.LIGHT From f3e00e918b0443beb09faafd6143652d9b8344de Mon Sep 17 00:00:00 2001 From: Daniel Shleifman Date: Sat, 26 Jun 2021 21:52:14 +0300 Subject: [PATCH 4/6] refactor --- web/src/components/App/index.jsx | 7 +------ web/src/style/colors.js | 2 +- web/src/style/materialUISetup.js | 7 ++++++- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/web/src/components/App/index.jsx b/web/src/components/App/index.jsx index d40b350..1896f94 100644 --- a/web/src/components/App/index.jsx +++ b/web/src/components/App/index.jsx @@ -35,7 +35,7 @@ export default function App() { const [torrServerVersion, setTorrServerVersion] = useState('') // https://material-ui.com/ru/customization/palette/ - const [isDarkMode, currentThemeMode, setCurrentThemeMode, muiTheme] = useMaterialUITheme() + const [isDarkMode, currentThemeMode, updateThemeMode, muiTheme] = useMaterialUITheme() const [currentLang, changeLang] = useChangeLanguage() const [isOffline, setIsOffline] = useState(false) const { data: torrents, isLoading } = useQuery('torrents', getTorrents, { @@ -82,11 +82,6 @@ export default function App() { > { - const updateThemeMode = mode => { - setCurrentThemeMode(mode) - localStorage.setItem('themeMode', mode) - } - if (currentThemeMode === THEME_MODES.LIGHT) updateThemeMode(THEME_MODES.DARK) if (currentThemeMode === THEME_MODES.DARK) updateThemeMode(THEME_MODES.AUTO) if (currentThemeMode === THEME_MODES.AUTO) updateThemeMode(THEME_MODES.LIGHT) diff --git a/web/src/style/colors.js b/web/src/style/colors.js index a7dce73..afedb59 100644 --- a/web/src/style/colors.js +++ b/web/src/style/colors.js @@ -4,7 +4,7 @@ export const themeColors = { light: { app: { headerToggleColor: '#4db380', - appSecondaryColor: '#f1eff3', + appSecondaryColor: '#CBE8D9', sidebarBGColor: '#575757', sidebarFillColor: '#dee3e5', }, diff --git a/web/src/style/materialUISetup.js b/web/src/style/materialUISetup.js index 4587cfe..705977f 100644 --- a/web/src/style/materialUISetup.js +++ b/web/src/style/materialUISetup.js @@ -28,6 +28,11 @@ export const useMaterialUITheme = () => { const [isDarkMode, setIsDarkMode] = useState(savedThemeMode === 'dark' || isSystemModeDark) const [currentThemeMode, setCurrentThemeMode] = useState(savedThemeMode || THEME_MODES.LIGHT) + const updateThemeMode = mode => { + setCurrentThemeMode(mode) + localStorage.setItem('themeMode', mode) + } + useEffect(() => { currentThemeMode === THEME_MODES.LIGHT && setIsDarkMode(false) currentThemeMode === THEME_MODES.DARK && setIsDarkMode(true) @@ -48,5 +53,5 @@ export const useMaterialUITheme = () => { [theme], ) - return [isDarkMode, currentThemeMode, setCurrentThemeMode, muiTheme] + return [isDarkMode, currentThemeMode, updateThemeMode, muiTheme] } From 9b521ef06cc2d90b966a954badcfdc1c8d212a44 Mon Sep 17 00:00:00 2001 From: Daniel Shleifman Date: Sat, 26 Jun 2021 21:52:33 +0300 Subject: [PATCH 5/6] refactor --- web/src/components/App/index.jsx | 1 - 1 file changed, 1 deletion(-) diff --git a/web/src/components/App/index.jsx b/web/src/components/App/index.jsx index 1896f94..367cd8a 100644 --- a/web/src/components/App/index.jsx +++ b/web/src/components/App/index.jsx @@ -34,7 +34,6 @@ export default function App() { const [isDonationDialogOpen, setIsDonationDialogOpen] = useState(false) const [torrServerVersion, setTorrServerVersion] = useState('') - // https://material-ui.com/ru/customization/palette/ const [isDarkMode, currentThemeMode, updateThemeMode, muiTheme] = useMaterialUITheme() const [currentLang, changeLang] = useChangeLanguage() const [isOffline, setIsOffline] = useState(false) From e2241cf7fd0b49ad41fc7ec0fb15c7237e82da48 Mon Sep 17 00:00:00 2001 From: Daniel Shleifman Date: Sat, 26 Jun 2021 22:28:50 +0300 Subject: [PATCH 6/6] refactor --- web/src/components/Add/AddDialog.jsx | 2 +- .../DetailedView/index.jsx | 4 +++- .../TorrentCache/snakeSettings.js | 13 +++++++------ .../DialogTorrentDetailsContent/index.jsx | 4 ++-- .../components/DialogTorrentDetailsContent/style.js | 3 ++- web/src/components/TorrentList/index.jsx | 2 +- web/src/style/colors.js | 4 +++- web/src/style/materialUISetup.js | 3 +++ 8 files changed, 22 insertions(+), 13 deletions(-) diff --git a/web/src/components/Add/AddDialog.jsx b/web/src/components/Add/AddDialog.jsx index 65262cf..69431d9 100644 --- a/web/src/components/Add/AddDialog.jsx +++ b/web/src/components/Add/AddDialog.jsx @@ -268,7 +268,7 @@ export default function AddDialog({ - diff --git a/web/src/components/DialogTorrentDetailsContent/DetailedView/index.jsx b/web/src/components/DialogTorrentDetailsContent/DetailedView/index.jsx index 926712e..4222d7d 100644 --- a/web/src/components/DialogTorrentDetailsContent/DetailedView/index.jsx +++ b/web/src/components/DialogTorrentDetailsContent/DetailedView/index.jsx @@ -42,7 +42,9 @@ export default function DetailedView({ - {t('Cache')} + + {t('Cache')} + diff --git a/web/src/components/DialogTorrentDetailsContent/TorrentCache/snakeSettings.js b/web/src/components/DialogTorrentDetailsContent/TorrentCache/snakeSettings.js index 4f79f27..b2fc35b 100644 --- a/web/src/components/DialogTorrentDetailsContent/TorrentCache/snakeSettings.js +++ b/web/src/components/DialogTorrentDetailsContent/TorrentCache/snakeSettings.js @@ -1,16 +1,17 @@ +import { rgba } from 'polished' import { mainColors } from 'style/colors' export const snakeSettings = { dark: { default: { - borderWidth: 1, + borderWidth: 2, pieceSize: 14, gapBetweenPieces: 3, - borderColor: mainColors.dark.primary, - completeColor: mainColors.dark.primary, - backgroundColor: '#fff', - progressColor: '#545a5e', - readerColor: '#fff', + borderColor: mainColors.dark.secondary, + completeColor: rgba(mainColors.dark.primary, 0.65), + backgroundColor: '#f1eff3', + progressColor: mainColors.dark.secondary, + readerColor: '#000', rangeColor: '#cda184', }, mini: { diff --git a/web/src/components/DialogTorrentDetailsContent/index.jsx b/web/src/components/DialogTorrentDetailsContent/index.jsx index 3df8f30..7db86dd 100644 --- a/web/src/components/DialogTorrentDetailsContent/index.jsx +++ b/web/src/components/DialogTorrentDetailsContent/index.jsx @@ -33,7 +33,7 @@ import { isFilePlayable } from './helpers' const Loader = () => (
- +
) @@ -225,7 +225,7 @@ export default function DialogTorrentDetailsContent({ closeDialog, torrent }) { {seasonAmount?.length > 1 && ( <> {t('SelectSeason')} - + {seasonAmount.map(season => (