diff --git a/apps/readest-app/public/locales/ar/translation.json b/apps/readest-app/public/locales/ar/translation.json index 2b48717b..ebc07a1c 100644 --- a/apps/readest-app/public/locales/ar/translation.json +++ b/apps/readest-app/public/locales/ar/translation.json @@ -324,5 +324,6 @@ "Translated by {{provider}}.": "ترجم بواسطة {{provider}}.", "DeepL": "ديب إل", "Google Translate": "ترجمة جوجل", - "Azure Translator": "مترجم أزور" + "Azure Translator": "مترجم أزور", + "Invert Image In Dark Mode": "عكس الصورة في الوضع المظلم" } diff --git a/apps/readest-app/public/locales/de/translation.json b/apps/readest-app/public/locales/de/translation.json index d6698c09..146ae678 100644 --- a/apps/readest-app/public/locales/de/translation.json +++ b/apps/readest-app/public/locales/de/translation.json @@ -320,5 +320,6 @@ "Translated by {{provider}}.": "Übersetzt von {{provider}}.", "DeepL": "DeepL", "Google Translate": "Google Übersetzer", - "Azure Translator": "Azure Übersetzer" + "Azure Translator": "Azure Übersetzer", + "Invert Image In Dark Mode": "Invertiere Bild im Dunkeln" } diff --git a/apps/readest-app/public/locales/el/translation.json b/apps/readest-app/public/locales/el/translation.json index 20e07f21..de7ebbb0 100644 --- a/apps/readest-app/public/locales/el/translation.json +++ b/apps/readest-app/public/locales/el/translation.json @@ -320,5 +320,6 @@ "Translated by {{provider}}.": "Μεταφρασμένο από {{provider}}.", "DeepL": "DeepL", "Google Translate": "Μετάφραση Google", - "Azure Translator": "Μεταφραστής Azure" + "Azure Translator": "Μεταφραστής Azure", + "Invert Image In Dark Mode": "Αντιστροφή σε σκούρο" } diff --git a/apps/readest-app/public/locales/es/translation.json b/apps/readest-app/public/locales/es/translation.json index 335a2015..5d7e93fd 100644 --- a/apps/readest-app/public/locales/es/translation.json +++ b/apps/readest-app/public/locales/es/translation.json @@ -321,5 +321,6 @@ "Translated by {{provider}}.": "Traducido por {{provider}}.", "DeepL": "DeepL", "Google Translate": "Google Translate", - "Azure Translator": "Azure Translator" + "Azure Translator": "Azure Translator", + "Invert Image In Dark Mode": "Invertir imagen en oscuro" } diff --git a/apps/readest-app/public/locales/fr/translation.json b/apps/readest-app/public/locales/fr/translation.json index 35000f07..fd1be275 100644 --- a/apps/readest-app/public/locales/fr/translation.json +++ b/apps/readest-app/public/locales/fr/translation.json @@ -321,5 +321,6 @@ "Translated by {{provider}}.": "Traduit par {{provider}}.", "DeepL": "DeepL", "Google Translate": "Google Traduction", - "Azure Translator": "Traducteur Azure" + "Azure Translator": "Traducteur Azure", + "Invert Image In Dark Mode": "Inverser l'image en mode sombre" } diff --git a/apps/readest-app/public/locales/hi/translation.json b/apps/readest-app/public/locales/hi/translation.json index 1a59fc57..acc71269 100644 --- a/apps/readest-app/public/locales/hi/translation.json +++ b/apps/readest-app/public/locales/hi/translation.json @@ -320,5 +320,6 @@ "Translated by {{provider}}.": "{{provider}} द्वारा अनुवादित।", "DeepL": "डीपएल", "Google Translate": "गूगल अनुवाद", - "Azure Translator": "एज़्योर अनुवादक" + "Azure Translator": "एज़्योर अनुवादक", + "Invert Image In Dark Mode": "अंधेरे में छवि को उलटें" } diff --git a/apps/readest-app/public/locales/id/translation.json b/apps/readest-app/public/locales/id/translation.json index 45456f23..f5b01d94 100644 --- a/apps/readest-app/public/locales/id/translation.json +++ b/apps/readest-app/public/locales/id/translation.json @@ -319,5 +319,6 @@ "Translated by {{provider}}.": "Terjemahan oleh {{provider}}.", "DeepL": "DeepL", "Google Translate": "Google Translate", - "Azure Translator": "Azure Translator" + "Azure Translator": "Azure Translator", + "Invert Image In Dark Mode": "Inversi Gambar di Gelap" } diff --git a/apps/readest-app/public/locales/it/translation.json b/apps/readest-app/public/locales/it/translation.json index 53f7187f..1f1905e4 100644 --- a/apps/readest-app/public/locales/it/translation.json +++ b/apps/readest-app/public/locales/it/translation.json @@ -321,5 +321,6 @@ "Translated by {{provider}}.": "Tradotto da {{provider}}.", "DeepL": "DeepL", "Google Translate": "Google Translate", - "Azure Translator": "Traduttore Azure" + "Azure Translator": "Traduttore Azure", + "Invert Image In Dark Mode": "Inverti immagine in scuro" } diff --git a/apps/readest-app/public/locales/ja/translation.json b/apps/readest-app/public/locales/ja/translation.json index 50713a7a..7f15352f 100644 --- a/apps/readest-app/public/locales/ja/translation.json +++ b/apps/readest-app/public/locales/ja/translation.json @@ -319,5 +319,6 @@ "Translated by {{provider}}.": "{{provider}}によって翻訳されました。", "DeepL": "DeepL", "Google Translate": "Google翻訳", - "Azure Translator": "Azure翻訳" + "Azure Translator": "Azure翻訳", + "Invert Image In Dark Mode": "ダークモードで画像を反転" } diff --git a/apps/readest-app/public/locales/ko/translation.json b/apps/readest-app/public/locales/ko/translation.json index 3345b50b..df82cadd 100644 --- a/apps/readest-app/public/locales/ko/translation.json +++ b/apps/readest-app/public/locales/ko/translation.json @@ -319,5 +319,6 @@ "Translated by {{provider}}.": "{{provider}}에 의해 번역됨.", "DeepL": "DeepL", "Google Translate": "구글 번역", - "Azure Translator": "Azure 번역기" + "Azure Translator": "Azure 번역기", + "Invert Image In Dark Mode": "어두운 곳에서 이미지 반전" } diff --git a/apps/readest-app/public/locales/nl/translation.json b/apps/readest-app/public/locales/nl/translation.json index efc46248..f423fb8a 100644 --- a/apps/readest-app/public/locales/nl/translation.json +++ b/apps/readest-app/public/locales/nl/translation.json @@ -320,5 +320,6 @@ "Translated by {{provider}}.": "Vertaald door {{provider}}.", "DeepL": "DeepL", "Google Translate": "Google Vertalen", - "Azure Translator": "Azure Vertaler" + "Azure Translator": "Azure Vertaler", + "Invert Image In Dark Mode": "Inverteer afbeelding in het donker" } diff --git a/apps/readest-app/public/locales/pl/translation.json b/apps/readest-app/public/locales/pl/translation.json index 540f6caa..4b62e34d 100644 --- a/apps/readest-app/public/locales/pl/translation.json +++ b/apps/readest-app/public/locales/pl/translation.json @@ -322,5 +322,6 @@ "Translated by {{provider}}.": "Przetłumaczone przez {{provider}}.", "DeepL": "DeepL", "Google Translate": "Tłumacz Google", - "Azure Translator": "Azure Translator" + "Azure Translator": "Azure Translator", + "Invert Image In Dark Mode": "Odwróć obraz w ciemności" } diff --git a/apps/readest-app/public/locales/pt/translation.json b/apps/readest-app/public/locales/pt/translation.json index d480d3e5..bc9257f8 100644 --- a/apps/readest-app/public/locales/pt/translation.json +++ b/apps/readest-app/public/locales/pt/translation.json @@ -321,5 +321,6 @@ "Translated by {{provider}}.": "Traduzido por {{provider}}.", "DeepL": "DeepL", "Google Translate": "Google Tradutor", - "Azure Translator": "Tradutor Azure" + "Azure Translator": "Tradutor Azure", + "Invert Image In Dark Mode": "Inverter Imagem no Escuro" } diff --git a/apps/readest-app/public/locales/ru/translation.json b/apps/readest-app/public/locales/ru/translation.json index 920770fb..64428a96 100644 --- a/apps/readest-app/public/locales/ru/translation.json +++ b/apps/readest-app/public/locales/ru/translation.json @@ -322,5 +322,6 @@ "Translated by {{provider}}.": "Переведено {{provider}}.", "DeepL": "DeepL", "Google Translate": "Google Translate", - "Azure Translator": "Azure Translator" + "Azure Translator": "Azure Translator", + "Invert Image In Dark Mode": "Инвертировать в тёмной теме" } diff --git a/apps/readest-app/public/locales/tr/translation.json b/apps/readest-app/public/locales/tr/translation.json index b1d5ce72..3a9b2cb6 100644 --- a/apps/readest-app/public/locales/tr/translation.json +++ b/apps/readest-app/public/locales/tr/translation.json @@ -320,5 +320,6 @@ "Translated by {{provider}}.": "{{provider}} tarafından çevrildi.", "DeepL": "DeepL", "Google Translate": "Google Çeviri", - "Azure Translator": "Azure Çevirmen" + "Azure Translator": "Azure Çevirmen", + "Invert Image In Dark Mode": "Karartılmış Görüntüyü Ters Çevir" } diff --git a/apps/readest-app/public/locales/uk/translation.json b/apps/readest-app/public/locales/uk/translation.json index 254731c3..cebcc139 100644 --- a/apps/readest-app/public/locales/uk/translation.json +++ b/apps/readest-app/public/locales/uk/translation.json @@ -322,5 +322,6 @@ "Translated by {{provider}}.": "Перекладено {{provider}}.", "DeepL": "DeepL", "Google Translate": "Google Translate", - "Azure Translator": "Azure Translator" + "Azure Translator": "Azure Translator", + "Invert Image In Dark Mode": "Інвертувати зображення в темряві" } diff --git a/apps/readest-app/public/locales/vi/translation.json b/apps/readest-app/public/locales/vi/translation.json index bed6c175..43dd6f54 100644 --- a/apps/readest-app/public/locales/vi/translation.json +++ b/apps/readest-app/public/locales/vi/translation.json @@ -319,5 +319,6 @@ "Translated by {{provider}}.": "Được dịch bởi {{provider}}.", "DeepL": "DeepL", "Google Translate": "Google Dịch", - "Azure Translator": "Azure Translator" + "Azure Translator": "Azure Translator", + "Invert Image In Dark Mode": "Đảo ảnh chế độ tối" } diff --git a/apps/readest-app/public/locales/zh-CN/translation.json b/apps/readest-app/public/locales/zh-CN/translation.json index 5c06020a..cf47eed4 100644 --- a/apps/readest-app/public/locales/zh-CN/translation.json +++ b/apps/readest-app/public/locales/zh-CN/translation.json @@ -319,5 +319,6 @@ "Translated by {{provider}}.": "由 {{provider}} 提供翻译", "DeepL": "DeepL", "Google Translate": "Google Translate", - "Azure Translator": "Azure Translator" + "Azure Translator": "Azure Translator", + "Invert Image In Dark Mode": "深色主题下图片反色" } diff --git a/apps/readest-app/public/locales/zh-TW/translation.json b/apps/readest-app/public/locales/zh-TW/translation.json index 7ecee567..db7563e0 100644 --- a/apps/readest-app/public/locales/zh-TW/translation.json +++ b/apps/readest-app/public/locales/zh-TW/translation.json @@ -319,5 +319,6 @@ "Translated by {{provider}}.": "由 {{provider}} 提供翻譯", "DeepL": "DeepL", "Google Translate": "Google Translate", - "Azure Translator": "Azure Translator" + "Azure Translator": "Azure Translator", + "Invert Image In Dark Mode": "深色主題下圖片反相" } diff --git a/apps/readest-app/src/app/reader/components/ViewMenu.tsx b/apps/readest-app/src/app/reader/components/ViewMenu.tsx index ac47c30c..fab01669 100644 --- a/apps/readest-app/src/app/reader/components/ViewMenu.tsx +++ b/apps/readest-app/src/app/reader/components/ViewMenu.tsx @@ -33,9 +33,12 @@ const ViewMenu: React.FC = ({ 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 = ({ // 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 (
= ({ Icon={themeMode === 'dark' ? BiMoon : themeMode === 'light' ? BiSun : TbSunMoon} onClick={cycleThemeMode} /> + setInvertImgColorInDark(!invertImgColorInDark)} + />
); }; diff --git a/apps/readest-app/src/app/reader/components/settings/ColorPanel.tsx b/apps/readest-app/src/app/reader/components/settings/ColorPanel.tsx index 9fe00bef..9e78aa39 100644 --- a/apps/readest-app/src/app/reader/components/settings/ColorPanel.tsx +++ b/apps/readest-app/src/app/reader/components/settings/ColorPanel.tsx @@ -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(null); const [customThems, setCustomThemes] = useState([]); 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 }> = ({}) => { +
+

{_('Invert Image In Dark Mode')}

+ setInvertImgColorInDark(!invertImgColorInDark)} + /> +
+

{_('Theme Color')}

diff --git a/apps/readest-app/src/app/reader/components/settings/LayoutPanel.tsx b/apps/readest-app/src/app/reader/components/settings/LayoutPanel.tsx index f60f3e8b..0e394c4c 100644 --- a/apps/readest-app/src/app/reader/components/settings/LayoutPanel.tsx +++ b/apps/readest-app/src/app/reader/components/settings/LayoutPanel.tsx @@ -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]); diff --git a/apps/readest-app/src/services/constants.ts b/apps/readest-app/src/services/constants.ts index b77ee40a..64b4001d 100644 --- a/apps/readest-app/src/services/constants.ts +++ b/apps/readest-app/src/services/constants.ts @@ -118,7 +118,7 @@ export const DEFAULT_BOOK_STYLE: BookStyle = { textIndent: 0, fullJustification: true, hyphenation: true, - invert: false, + invertImgColorInDark: false, theme: 'light', overrideFont: false, overrideLayout: false, diff --git a/apps/readest-app/src/types/book.ts b/apps/readest-app/src/types/book.ts index db2fb650..d82708dc 100644 --- a/apps/readest-app/src/types/book.ts +++ b/apps/readest-app/src/types/book.ts @@ -99,7 +99,7 @@ export interface BookStyle { textIndent: number; fullJustification: boolean; hyphenation: boolean; - invert: boolean; + invertImgColorInDark: boolean; theme: string; overrideFont: boolean; overrideLayout: boolean; diff --git a/apps/readest-app/src/utils/style.ts b/apps/readest-app/src/utils/style.ts index 007645cb..8d290969 100644 --- a/apps/readest-app/src/utils/style.ts +++ b/apps/readest-app/src/utils/style.ts @@ -29,7 +29,7 @@ const getFontStyles = ( overrideFont: boolean, themeCode: ThemeCode, ) => { - const { fg, primary } = themeCode; + const { fg, primary, isDarkMode } = themeCode; const lastSerifFonts = ['Georgia', 'Times New Roman']; const serifFonts = [ serif, @@ -87,15 +87,9 @@ const getFontStyles = ( ${overrideFont ? 'font-family: revert !important;' : ''} } a:any-link, a:any-link * { - ${overrideFont ? `color: ${primary};` : ''} + ${overrideFont ? `color: ${primary};` : isDarkMode ? `color: lightblue;` : ''} text-decoration: none; } - /* https://github.com/whatwg/html/issues/5426 */ - @media (prefers-color-scheme: dark) { - a:any-link, a:any-link * { - ${overrideFont ? `color: ${primary};` : `color: lightblue;`} - } - } /* override inline hardcoded text color */ *[style*="color: rgb(0,0,0)"], *[style*="color: rgb(0, 0, 0)"], *[style*="color: #000"], *[style*="color: #000000"], *[style*="color: black"], @@ -188,6 +182,7 @@ const getLayoutStyles = ( zoomLevel: number, writingMode: string, vertical: boolean, + invertImgColorInDark: boolean, themeCode: ThemeCode, ) => { const { bg, fg, primary, isDarkMode } = themeCode; @@ -293,11 +288,13 @@ const getLayoutStyles = ( color: unset; } + img { + ${isDarkMode && invertImgColorInDark ? 'filter: invert(100%);' : ''} + } /* inline images without dimension */ p img, span img, sup img { height: 1em; mix-blend-mode: ${isDarkMode ? 'screen' : 'multiply'}; - ${isDarkMode ? 'filter: invert(100%);' : ''} } p:has(img), span:has(img) { background-color: ${bg}; @@ -345,12 +342,6 @@ export const getFootnoteStyles = () => ` text-decoration: none; } - @media (prefers-color-scheme: dark) { - a:any-link, a:any-link * { - color: unset; - } - } - ol { margin: 0; padding: 0; @@ -423,6 +414,7 @@ export const getStyles = (viewSettings: ViewSettings, themeCode?: ThemeCode) => viewSettings.zoomLevel! / 100.0, viewSettings.writingMode!, viewSettings.vertical!, + viewSettings.invertImgColorInDark!, themeCode, ); // scale the font size on-the-fly so that we can sync the same font size on different devices