Dark theme integration
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import React, { useEffect, useState } from "react"
|
import React, { useEffect, useMemo, useState } from "react"
|
||||||
import { ThemeProvider } from "@emotion/react";
|
import { ThemeProvider } from "@emotion/react";
|
||||||
import {
|
import {
|
||||||
Badge,
|
Badge,
|
||||||
@@ -13,7 +13,13 @@ import {
|
|||||||
} from "@mui/material"
|
} from "@mui/material"
|
||||||
import MuiDrawer from '@mui/material/Drawer';
|
import MuiDrawer from '@mui/material/Drawer';
|
||||||
import MuiAppBar, { AppBarProps as MuiAppBarProps } from '@mui/material/AppBar';
|
import MuiAppBar, { AppBarProps as MuiAppBarProps } from '@mui/material/AppBar';
|
||||||
import { ChevronLeft, Dashboard, Menu, Settings as SettingsIcon, SettingsEthernet, Storage } from "@mui/icons-material";
|
import {
|
||||||
|
ChevronLeft,
|
||||||
|
Dashboard,
|
||||||
|
Menu, Settings as SettingsIcon,
|
||||||
|
SettingsEthernet,
|
||||||
|
Storage,
|
||||||
|
} from "@mui/icons-material";
|
||||||
import ListItemButton from '@mui/material/ListItemButton';
|
import ListItemButton from '@mui/material/ListItemButton';
|
||||||
import {
|
import {
|
||||||
BrowserRouter as Router,
|
BrowserRouter as Router,
|
||||||
@@ -25,9 +31,9 @@ import Home from "./Home";
|
|||||||
import Settings from "./Settings";
|
import Settings from "./Settings";
|
||||||
import { io } from "socket.io-client";
|
import { io } from "socket.io-client";
|
||||||
import { RootState, store } from './stores/store';
|
import { RootState, store } from './stores/store';
|
||||||
import { Provider, useSelector } from "react-redux";
|
import { Provider, useDispatch, useSelector } from "react-redux";
|
||||||
|
import { setTheme } from "./features/settings/settingsSlice";
|
||||||
|
|
||||||
const theme = createTheme();
|
|
||||||
|
|
||||||
const drawerWidth: number = 240;
|
const drawerWidth: number = 240;
|
||||||
|
|
||||||
@@ -85,13 +91,23 @@ function AppContent() {
|
|||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const [freeDiskSpace, setFreeDiskSpace] = useState('');
|
const [freeDiskSpace, setFreeDiskSpace] = useState('');
|
||||||
|
|
||||||
|
const settings = useSelector((state: RootState) => state.settings)
|
||||||
|
const status = useSelector((state: RootState) => state.status)
|
||||||
|
|
||||||
|
const mode = settings.theme
|
||||||
|
|
||||||
|
const theme = useMemo(() =>
|
||||||
|
createTheme({
|
||||||
|
palette: {
|
||||||
|
mode,
|
||||||
|
},
|
||||||
|
}), [settings.theme]
|
||||||
|
);
|
||||||
|
|
||||||
const toggleDrawer = () => {
|
const toggleDrawer = () => {
|
||||||
setOpen(!open);
|
setOpen(!open);
|
||||||
};
|
};
|
||||||
|
|
||||||
const settings = useSelector((state: RootState) => state.settings)
|
|
||||||
const status = useSelector((state: RootState) => state.status)
|
|
||||||
|
|
||||||
/* Get disk free space */
|
/* Get disk free space */
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
socket.on('free-space', (res: string) => {
|
socket.on('free-space', (res: string) => {
|
||||||
@@ -175,7 +191,7 @@ function AppContent() {
|
|||||||
<Link to={'/'} style={
|
<Link to={'/'} style={
|
||||||
{
|
{
|
||||||
textDecoration: 'none',
|
textDecoration: 'none',
|
||||||
color: '#222222'
|
color: mode === 'dark' ? '#ffffff' : '#000000DE'
|
||||||
}
|
}
|
||||||
}>
|
}>
|
||||||
<ListItemButton disabled={status.downloading}>
|
<ListItemButton disabled={status.downloading}>
|
||||||
@@ -188,7 +204,7 @@ function AppContent() {
|
|||||||
<Link to={'/settings'} style={
|
<Link to={'/settings'} style={
|
||||||
{
|
{
|
||||||
textDecoration: 'none',
|
textDecoration: 'none',
|
||||||
color: '#222222'
|
color: mode === 'dark' ? '#ffffff' : '#000000DE'
|
||||||
}
|
}
|
||||||
}>
|
}>
|
||||||
<ListItemButton disabled={status.downloading}>
|
<ListItemButton disabled={status.downloading}>
|
||||||
@@ -203,10 +219,6 @@ function AppContent() {
|
|||||||
<Box
|
<Box
|
||||||
component="main"
|
component="main"
|
||||||
sx={{
|
sx={{
|
||||||
backgroundColor: (theme) =>
|
|
||||||
theme.palette.mode === 'light'
|
|
||||||
? theme.palette.grey[100]
|
|
||||||
: theme.palette.grey[900],
|
|
||||||
flexGrow: 1,
|
flexGrow: 1,
|
||||||
height: '100vh',
|
height: '100vh',
|
||||||
overflow: 'auto',
|
overflow: 'auto',
|
||||||
|
|||||||
@@ -17,10 +17,10 @@ import {
|
|||||||
TextField,
|
TextField,
|
||||||
Typography
|
Typography
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { useDispatch, useSelector } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
import { Socket } from "socket.io-client";
|
import { Socket } from "socket.io-client";
|
||||||
import { LanguageUnion, setCliArgs, setLanguage, setServerAddr } from "./features/settings/settingsSlice";
|
import { LanguageUnion, setCliArgs, setLanguage, setServerAddr, setTheme, ThemeUnion } from "./features/settings/settingsSlice";
|
||||||
import { alreadyUpdated, updated } from "./features/status/statusSlice";
|
import { alreadyUpdated, updated } from "./features/status/statusSlice";
|
||||||
import { RootState } from "./stores/store";
|
import { RootState } from "./stores/store";
|
||||||
import { validateDomain, validateIP } from "./utils";
|
import { validateDomain, validateIP } from "./utils";
|
||||||
@@ -34,25 +34,7 @@ export default function Settings({ socket }: Props) {
|
|||||||
const status = useSelector((state: RootState) => state.status)
|
const status = useSelector((state: RootState) => state.status)
|
||||||
const dispatch = useDispatch()
|
const dispatch = useDispatch()
|
||||||
|
|
||||||
const [halt, setHalt] = useState(false);
|
|
||||||
const [invalidIP, setInvalidIP] = useState(false);
|
const [invalidIP, setInvalidIP] = useState(false);
|
||||||
const [updatedBin, setUpdatedBin] = useState(false);
|
|
||||||
const [freeDiskSpace, setFreeDiskSpace] = useState('');
|
|
||||||
|
|
||||||
/* Handle yt-dlp update success */
|
|
||||||
useEffect(() => {
|
|
||||||
socket.on('updated', () => {
|
|
||||||
setUpdatedBin(true)
|
|
||||||
setHalt(false)
|
|
||||||
})
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
/* Get disk free space */
|
|
||||||
useEffect(() => {
|
|
||||||
socket.on('free-space', (res: string) => {
|
|
||||||
setFreeDiskSpace(res)
|
|
||||||
})
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the server ip address state and localstorage whenever the input value changes.
|
* Update the server ip address state and localstorage whenever the input value changes.
|
||||||
@@ -75,10 +57,17 @@ export default function Settings({ socket }: Props) {
|
|||||||
/**
|
/**
|
||||||
* Language toggler handler
|
* Language toggler handler
|
||||||
*/
|
*/
|
||||||
const handleLanguageChage = (event: SelectChangeEvent<LanguageUnion>) => {
|
const handleLanguageChange = (event: SelectChangeEvent<LanguageUnion>) => {
|
||||||
dispatch(setLanguage(event.target.value as LanguageUnion));
|
dispatch(setLanguage(event.target.value as LanguageUnion));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Language toggler handler
|
||||||
|
*/
|
||||||
|
const handleThemeChange = (event: SelectChangeEvent<ThemeUnion>) => {
|
||||||
|
dispatch(setTheme(event.target.value as ThemeUnion));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send via WebSocket a message in order to update the yt-dlp binary from server
|
* Send via WebSocket a message in order to update the yt-dlp binary from server
|
||||||
*/
|
*/
|
||||||
@@ -115,21 +104,38 @@ export default function Settings({ socket }: Props) {
|
|||||||
}}
|
}}
|
||||||
sx={{ mb: 2 }}
|
sx={{ mb: 2 }}
|
||||||
/>
|
/>
|
||||||
<FormControl fullWidth>
|
<Grid container spacing={2}>
|
||||||
<InputLabel id="demo-simple-select-label">Language</InputLabel>
|
<Grid item xs={12} md={6}>
|
||||||
<Select
|
<FormControl fullWidth>
|
||||||
defaultValue={settings.language}
|
<InputLabel id="demo-simple-select-label">Language</InputLabel>
|
||||||
label="Language"
|
<Select
|
||||||
onChange={handleLanguageChage}
|
defaultValue={settings.language}
|
||||||
>
|
label="Language"
|
||||||
<MenuItem value="english">English</MenuItem>
|
onChange={handleLanguageChange}
|
||||||
<MenuItem value="spanish">Spanish</MenuItem>
|
>
|
||||||
<MenuItem value="italian">Italian</MenuItem>
|
<MenuItem value="english">English</MenuItem>
|
||||||
<MenuItem value="chinese">Chinese</MenuItem>
|
<MenuItem value="spanish">Spanish</MenuItem>
|
||||||
<MenuItem value="russian">Russian</MenuItem>
|
<MenuItem value="italian">Italian</MenuItem>
|
||||||
<MenuItem value="korean">Korean</MenuItem>
|
<MenuItem value="chinese">Chinese</MenuItem>
|
||||||
</Select>
|
<MenuItem value="russian">Russian</MenuItem>
|
||||||
</FormControl>
|
<MenuItem value="korean">Korean</MenuItem>
|
||||||
|
</Select>
|
||||||
|
</FormControl>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} md={6}>
|
||||||
|
<FormControl fullWidth>
|
||||||
|
<InputLabel>Theme</InputLabel>
|
||||||
|
<Select
|
||||||
|
defaultValue={settings.theme}
|
||||||
|
label="Theme"
|
||||||
|
onChange={handleThemeChange}
|
||||||
|
>
|
||||||
|
<MenuItem value="light">Light</MenuItem>
|
||||||
|
<MenuItem value="dark">Dark</MenuItem>
|
||||||
|
</Select>
|
||||||
|
</FormControl>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
<FormControlLabel
|
<FormControlLabel
|
||||||
control={
|
control={
|
||||||
<Switch
|
<Switch
|
||||||
|
|||||||
Reference in New Issue
Block a user