forked from akai/readest
feat: add an option to invert image color in dark mode (#1223)
This commit is contained in:
@@ -33,9 +33,12 @@ const ViewMenu: React.FC<ViewMenuProps> = ({
|
||||
const { getView, getViewSettings, setViewSettings } = useReaderStore();
|
||||
const viewSettings = getViewSettings(bookKey)!;
|
||||
|
||||
const { themeMode, setThemeMode } = useThemeStore();
|
||||
const { themeMode, isDarkMode, setThemeMode } = useThemeStore();
|
||||
const [isScrolledMode, setScrolledMode] = useState(viewSettings!.scrolled);
|
||||
const [zoomLevel, setZoomLevel] = useState(viewSettings!.zoomLevel!);
|
||||
const [invertImgColorInDark, setInvertImgColorInDark] = useState(
|
||||
viewSettings!.invertImgColorInDark,
|
||||
);
|
||||
|
||||
const zoomIn = () => setZoomLevel((prev) => Math.min(prev + ZOOM_STEP, MAX_ZOOM_LEVEL));
|
||||
const zoomOut = () => setZoomLevel((prev) => Math.max(prev - ZOOM_STEP, MIN_ZOOM_LEVEL));
|
||||
@@ -76,6 +79,12 @@ const ViewMenu: React.FC<ViewMenuProps> = ({
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [zoomLevel]);
|
||||
|
||||
useEffect(() => {
|
||||
if (invertImgColorInDark === viewSettings.invertImgColorInDark) return;
|
||||
saveViewSettings(envConfig, bookKey, 'invertImgColorInDark', invertImgColorInDark, true, true);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [invertImgColorInDark]);
|
||||
|
||||
return (
|
||||
<div
|
||||
tabIndex={0}
|
||||
@@ -135,6 +144,12 @@ const ViewMenu: React.FC<ViewMenuProps> = ({
|
||||
Icon={themeMode === 'dark' ? BiMoon : themeMode === 'light' ? BiSun : TbSunMoon}
|
||||
onClick={cycleThemeMode}
|
||||
/>
|
||||
<MenuItem
|
||||
label={_('Invert Image In Dark Mode')}
|
||||
disabled={!isDarkMode}
|
||||
Icon={invertImgColorInDark ? MdCheck : undefined}
|
||||
onClick={() => setInvertImgColorInDark(!invertImgColorInDark)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -13,24 +13,38 @@ import {
|
||||
themes,
|
||||
} from '@/styles/themes';
|
||||
import { useEnv } from '@/context/EnvContext';
|
||||
import { useSettingsStore } from '@/store/settingsStore';
|
||||
import { useThemeStore } from '@/store/themeStore';
|
||||
import { useReaderStore } from '@/store/readerStore';
|
||||
import { useTranslation } from '@/hooks/useTranslation';
|
||||
import { useSettingsStore } from '@/store/settingsStore';
|
||||
import { useResponsiveSize } from '@/hooks/useResponsiveSize';
|
||||
import { saveViewSettings } from '../../utils/viewSettingsHelper';
|
||||
import ThemeEditor from './ThemeEditor';
|
||||
|
||||
const ColorPanel: React.FC<{ bookKey: string }> = ({}) => {
|
||||
const ColorPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => {
|
||||
const _ = useTranslation();
|
||||
const { themeMode, themeColor, isDarkMode, setThemeMode, setThemeColor, saveCustomTheme } =
|
||||
useThemeStore();
|
||||
const { envConfig } = useEnv();
|
||||
const { settings, setSettings } = useSettingsStore();
|
||||
const { getViewSettings } = useReaderStore();
|
||||
const viewSettings = getViewSettings(bookKey)!;
|
||||
const [invertImgColorInDark, setInvertImgColorInDark] = useState(
|
||||
viewSettings.invertImgColorInDark,
|
||||
);
|
||||
|
||||
const iconSize16 = useResponsiveSize(16);
|
||||
const iconSize24 = useResponsiveSize(24);
|
||||
const [editTheme, setEditTheme] = useState<CustomTheme | null>(null);
|
||||
const [customThems, setCustomThemes] = useState<Theme[]>([]);
|
||||
const [showCustomThemeEditor, setShowCustomThemeEditor] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (invertImgColorInDark === viewSettings.invertImgColorInDark) return;
|
||||
saveViewSettings(envConfig, bookKey, 'invertImgColorInDark', invertImgColorInDark);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [invertImgColorInDark]);
|
||||
|
||||
useEffect(() => {
|
||||
const customThemes = settings.globalReadSettings.customThemes ?? [];
|
||||
setCustomThemes(
|
||||
@@ -112,6 +126,17 @@ const ColorPanel: React.FC<{ bookKey: string }> = ({}) => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='flex items-center justify-between'>
|
||||
<h2 className='font-medium'>{_('Invert Image In Dark Mode')}</h2>
|
||||
<input
|
||||
type='checkbox'
|
||||
className='toggle'
|
||||
checked={invertImgColorInDark}
|
||||
disabled={!isDarkMode}
|
||||
onChange={() => setInvertImgColorInDark(!invertImgColorInDark)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2 className='mb-2 font-medium'>{_('Theme Color')}</h2>
|
||||
<div className='grid grid-cols-3 gap-4'>
|
||||
|
||||
@@ -162,6 +162,7 @@ const LayoutPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => {
|
||||
}, [writingMode]);
|
||||
|
||||
useEffect(() => {
|
||||
if (overrideLayout === viewSettings.overrideLayout) return;
|
||||
saveViewSettings(envConfig, bookKey, 'overrideLayout', overrideLayout);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [overrideLayout]);
|
||||
|
||||
Reference in New Issue
Block a user