Add pure black mode option
This commit is contained in:
@@ -818,6 +818,7 @@
|
||||
},
|
||||
"appearance": {
|
||||
"device_theme": "Device theme",
|
||||
"pure_black_mode": "Pure black dark mode",
|
||||
"theme": "Theme",
|
||||
"title": "Appearance"
|
||||
},
|
||||
@@ -914,12 +915,12 @@
|
||||
}
|
||||
},
|
||||
"label": {
|
||||
"theme": "Theme",
|
||||
"hide_library_entries": "Hide entries already in library",
|
||||
"language_description": "Feel free to translate the project on",
|
||||
"manga_item_width": "Manga item width",
|
||||
"show_nsfw": "Show NSFW",
|
||||
"show_nsfw_description": "Hide NSFW extensions and sources"
|
||||
"show_nsfw_description": "Hide NSFW extensions and sources",
|
||||
"theme": "Theme"
|
||||
},
|
||||
"server": {
|
||||
"address": {
|
||||
|
||||
@@ -57,14 +57,17 @@ export const AppContext: React.FC<Props> = ({ children }) => {
|
||||
}, []);
|
||||
|
||||
const [themeMode, setThemeMode] = useLocalStorage<ThemeMode>('themeMode', ThemeMode.SYSTEM);
|
||||
const [pureBlackMode, setPureBlackMode] = useLocalStorage<boolean>('pureBlackMode', false);
|
||||
const [activeDevice, setActiveDeviceContext] = useLocalStorage('activeDevice', DEFAULT_DEVICE);
|
||||
|
||||
const darkThemeContext = useMemo(
|
||||
() => ({
|
||||
themeMode,
|
||||
setThemeMode,
|
||||
pureBlackMode,
|
||||
setPureBlackMode,
|
||||
}),
|
||||
[themeMode],
|
||||
[themeMode, pureBlackMode],
|
||||
);
|
||||
|
||||
const activeDeviceContext = useMemo(
|
||||
@@ -73,8 +76,8 @@ export const AppContext: React.FC<Props> = ({ children }) => {
|
||||
);
|
||||
|
||||
const theme = useMemo(
|
||||
() => createTheme(themeMode, currentDirection),
|
||||
[themeMode, currentDirection, systemThemeMode],
|
||||
() => createTheme(themeMode, currentDirection, undefined, pureBlackMode),
|
||||
[themeMode, currentDirection, systemThemeMode, pureBlackMode],
|
||||
);
|
||||
|
||||
setActiveDevice(activeDevice);
|
||||
|
||||
@@ -17,9 +17,13 @@ export enum ThemeMode {
|
||||
type ContextType = {
|
||||
themeMode: ThemeMode;
|
||||
setThemeMode: React.Dispatch<React.SetStateAction<ThemeMode>>;
|
||||
pureBlackMode: boolean;
|
||||
setPureBlackMode: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
};
|
||||
|
||||
export const ThemeModeContext = React.createContext<ContextType>({
|
||||
themeMode: ThemeMode.SYSTEM,
|
||||
setThemeMode: (): void => {},
|
||||
pureBlackMode: false,
|
||||
setPureBlackMode: (): void => {},
|
||||
});
|
||||
|
||||
@@ -10,6 +10,7 @@ import useMediaQuery from '@mui/material/useMediaQuery';
|
||||
import { Breakpoint } from '@mui/material/styles';
|
||||
import { getCurrentTheme } from '@/theme.ts';
|
||||
import { ThemeMode } from '@/components/context/ThemeModeContext.tsx';
|
||||
import { AppStorage } from '@/util/AppStorage.ts';
|
||||
|
||||
export class MediaQuery {
|
||||
static useIsTouchDevice(): boolean {
|
||||
@@ -29,6 +30,17 @@ export class MediaQuery {
|
||||
return prefersDarkMode ? ThemeMode.DARK : ThemeMode.LIGHT;
|
||||
}
|
||||
|
||||
static getThemeMode(): Exclude<ThemeMode, 'system'> {
|
||||
const themeMode = AppStorage.local.getItemParsed<ThemeMode>('themeMode', ThemeMode.SYSTEM);
|
||||
|
||||
const isSystemMode = themeMode === ThemeMode.SYSTEM;
|
||||
if (isSystemMode) {
|
||||
return this.getSystemThemeMode();
|
||||
}
|
||||
|
||||
return themeMode;
|
||||
}
|
||||
|
||||
static listenToSystemThemeChange(onChange: (themeMode: Exclude<ThemeMode, 'system'>) => void): () => void {
|
||||
const handleSystemThemeModeChange = (e: MediaQueryListEvent) => {
|
||||
onChange(e.matches ? ThemeMode.DARK : ThemeMode.LIGHT);
|
||||
|
||||
@@ -13,13 +13,16 @@ import ListItem from '@mui/material/ListItem';
|
||||
import ListItemText from '@mui/material/ListItemText';
|
||||
import MenuItem from '@mui/material/MenuItem';
|
||||
import ListSubheader from '@mui/material/ListSubheader';
|
||||
import Switch from '@mui/material/Switch';
|
||||
import { NavBarContext } from '@/components/context/NavbarContext.tsx';
|
||||
import { ThemeMode, ThemeModeContext } from '@/components/context/ThemeModeContext.tsx';
|
||||
import { Select } from '@/components/atoms/Select.tsx';
|
||||
import { MediaQuery } from '@/lib/ui/MediaQuery.tsx';
|
||||
|
||||
export const Appearance = () => {
|
||||
const { t } = useTranslation();
|
||||
const { themeMode, setThemeMode } = useContext(ThemeModeContext);
|
||||
const { themeMode, setThemeMode, pureBlackMode, setPureBlackMode } = useContext(ThemeModeContext);
|
||||
const isDarkMode = MediaQuery.getThemeMode() === ThemeMode.DARK;
|
||||
|
||||
const { setTitle, setAction } = useContext(NavBarContext);
|
||||
useEffect(() => {
|
||||
@@ -54,6 +57,12 @@ export const Appearance = () => {
|
||||
</MenuItem>
|
||||
</Select>
|
||||
</ListItem>
|
||||
{isDarkMode && (
|
||||
<ListItem>
|
||||
<ListItemText primary={t('settings.appearance.pure_black_mode')} />
|
||||
<Switch checked={pureBlackMode} onChange={(_, enabled) => setPureBlackMode(enabled)} />
|
||||
</ListItem>
|
||||
)}
|
||||
</List>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -31,6 +31,7 @@ export const createTheme = (
|
||||
const systemMode = MediaQuery.getSystemThemeMode();
|
||||
const mode = themeMode === ThemeMode.SYSTEM ? systemMode : themeMode;
|
||||
const isDarkMode = mode === ThemeMode.DARK;
|
||||
const setPureBlackMode = isDarkMode && pureBlackMode;
|
||||
|
||||
const baseTheme = createMuiTheme({
|
||||
direction,
|
||||
@@ -55,7 +56,7 @@ export const createTheme = (
|
||||
default: lighten(baseTheme.palette.primary.dark, 0.85),
|
||||
};
|
||||
const backgroundThemeMode = isDarkMode ? backgroundDark : backgroundLight;
|
||||
const background = pureBlackMode ? backgroundTrueBlack : backgroundThemeMode;
|
||||
const background = setPureBlackMode ? backgroundTrueBlack : backgroundThemeMode;
|
||||
|
||||
const colorTheme = createMuiTheme(baseTheme, {
|
||||
palette: {
|
||||
|
||||
Reference in New Issue
Block a user