From 15939ce2fcc0bc2d66a39afa8d477d3af6beb947 Mon Sep 17 00:00:00 2001 From: chrox Date: Tue, 19 Nov 2024 19:28:17 +0100 Subject: [PATCH] Add theme and color config --- apps/readest-app/package.json | 2 + apps/readest-app/src-tauri/tauri.conf.json | 2 +- apps/readest-app/src/app/layout.tsx | 2 + .../src/app/library/components/Bookshelf.tsx | 10 +- .../app/library/components/LibraryHeader.tsx | 14 ++- apps/readest-app/src/app/library/page.tsx | 4 +- .../app/reader/components/BookmarkToggler.tsx | 6 +- .../app/reader/components/FoliateViewer.tsx | 4 +- .../src/app/reader/components/FooterBar.tsx | 4 +- .../app/reader/components/NotebookToggler.tsx | 4 +- .../src/app/reader/components/PageInfo.tsx | 4 +- .../app/reader/components/ReaderContent.tsx | 2 +- .../src/app/reader/components/SectionInfo.tsx | 4 +- .../app/reader/components/SidebarToggler.tsx | 4 +- .../src/app/reader/components/ViewMenu.tsx | 110 +++++++++--------- .../app/reader/components/notebook/Header.tsx | 2 +- .../reader/components/notebook/NoteEditor.tsx | 2 +- .../reader/components/notebook/Notebook.tsx | 2 +- .../reader/components/settings/ColorPanel.tsx | 99 ++++++++++++---- .../reader/components/settings/DialogMenu.tsx | 4 +- .../reader/components/settings/FontPanel.tsx | 34 +++--- .../components/settings/LayoutPanel.tsx | 20 ++-- .../reader/components/settings/MiscPanel.tsx | 4 +- .../components/settings/NumberInput.tsx | 6 +- .../components/settings/SettingsDialog.tsx | 10 +- .../reader/components/sidebar/BookCard.tsx | 11 +- .../reader/components/sidebar/BookMenu.tsx | 29 ++--- .../components/sidebar/BooknoteItem.tsx | 2 +- .../app/reader/components/sidebar/Header.tsx | 8 +- .../app/reader/components/sidebar/SideBar.tsx | 4 +- .../app/reader/components/sidebar/TOCView.tsx | 9 +- .../components/sidebar/TabNavigation.tsx | 2 +- apps/readest-app/src/components/Dropdown.tsx | 6 +- apps/readest-app/src/components/MenuItem.tsx | 31 +++++ .../src/components/WindowButtons.tsx | 6 +- apps/readest-app/src/hooks/useTheme.ts | 96 +++++++++++++++ apps/readest-app/src/styles/globals.css | 36 +++--- apps/readest-app/src/styles/themes.ts | 110 ++++++++++++++++++ apps/readest-app/src/utils/event.ts | 14 +-- apps/readest-app/src/utils/style.ts | 46 +++++++- apps/readest-app/tailwind.config.ts | 15 +++ pnpm-lock.yaml | 18 ++- 42 files changed, 582 insertions(+), 220 deletions(-) create mode 100644 apps/readest-app/src/components/MenuItem.tsx create mode 100644 apps/readest-app/src/hooks/useTheme.ts create mode 100644 apps/readest-app/src/styles/themes.ts diff --git a/apps/readest-app/package.json b/apps/readest-app/package.json index e6831e85..96d62f12 100644 --- a/apps/readest-app/package.json +++ b/apps/readest-app/package.json @@ -37,6 +37,7 @@ "react": "18.3.1", "react-dom": "18.3.1", "react-icons": "^5.3.0", + "tinycolor2": "^1.6.0", "zustand": "5.0.0-rc.2" }, "devDependencies": { @@ -45,6 +46,7 @@ "@types/node": "^20", "@types/react": "18.3.12", "@types/react-dom": "18.3.1", + "@types/tinycolor2": "^1.4.6", "autoprefixer": "^10.4.20", "cpx": "^1.5.0", "cross-var": "^1.1.0", diff --git a/apps/readest-app/src-tauri/tauri.conf.json b/apps/readest-app/src-tauri/tauri.conf.json index 724e0bc0..ab8e4415 100644 --- a/apps/readest-app/src-tauri/tauri.conf.json +++ b/apps/readest-app/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "../node_modules/@tauri-apps/cli/config.schema.json", "productName": "Readest", - "version": "0.6.2", + "version": "0.6.5", "identifier": "com.bilingify.digest", "build": { "frontendDist": "../out", diff --git a/apps/readest-app/src/app/layout.tsx b/apps/readest-app/src/app/layout.tsx index f1ed41bc..69c53c2f 100644 --- a/apps/readest-app/src/app/layout.tsx +++ b/apps/readest-app/src/app/layout.tsx @@ -5,10 +5,12 @@ import { usePathname } from 'next/navigation'; import { AuthProvider } from '@/context/AuthContext'; import { EnvProvider } from '@/context/EnvContext'; import { CSPostHogProvider } from '@/context/PHContext'; +import { useTheme } from '@/hooks/useTheme'; import '../styles/globals.css'; import '../styles/fonts.css'; export default function RootLayout({ children }: { children: React.ReactNode }) { + useTheme(); const pathname = usePathname(); React.useEffect(() => { document.documentElement.setAttribute('data-page', pathname.replace('/', '') || 'default'); diff --git a/apps/readest-app/src/app/library/components/Bookshelf.tsx b/apps/readest-app/src/app/library/components/Bookshelf.tsx index ca33a2ef..fdec9f33 100644 --- a/apps/readest-app/src/app/library/components/Bookshelf.tsx +++ b/apps/readest-app/src/app/library/components/Bookshelf.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { FaPlus } from 'react-icons/fa'; +import { PiPlus } from 'react-icons/pi'; import { MdDelete, MdOpenInNew } from 'react-icons/md'; import { MdCheckCircle, MdCheckCircleOutline } from 'react-icons/md'; @@ -97,7 +97,7 @@ const Bookshelf: React.FC = ({ libraryBooks, isSelectMode, onImp
{bookshelfItems.map((item, index) => ( -
+
{'format' in item ? (
= ({ libraryBooks, isSelectMode, onImp {bookshelfItems.length > 0 && (
- +
)}
{selectedBooks.length > 0 && ( -
+
+
diff --git a/apps/readest-app/src/app/library/page.tsx b/apps/readest-app/src/app/library/page.tsx index 1aa326d8..a39fb805 100644 --- a/apps/readest-app/src/app/library/page.tsx +++ b/apps/readest-app/src/app/library/page.tsx @@ -77,7 +77,7 @@ const LibraryPage = () => { } return ( -
+
{ />
{loading && ( -
+
)} diff --git a/apps/readest-app/src/app/reader/components/BookmarkToggler.tsx b/apps/readest-app/src/app/reader/components/BookmarkToggler.tsx index 2e0e2064..6d72e37c 100644 --- a/apps/readest-app/src/app/reader/components/BookmarkToggler.tsx +++ b/apps/readest-app/src/app/reader/components/BookmarkToggler.tsx @@ -76,7 +76,11 @@ const BookmarkToggler: React.FC = ({ bookKey }) => { return ( ); }; diff --git a/apps/readest-app/src/app/reader/components/FoliateViewer.tsx b/apps/readest-app/src/app/reader/components/FoliateViewer.tsx index ac16705a..ad92caf4 100644 --- a/apps/readest-app/src/app/reader/components/FoliateViewer.tsx +++ b/apps/readest-app/src/app/reader/components/FoliateViewer.tsx @@ -4,6 +4,7 @@ import { BookDoc } from '@/libs/document'; import { BookConfig, BookNote, BookSearchConfig, BookSearchResult } from '@/types/book'; import { useReaderStore } from '@/store/readerStore'; import { getStyles } from '@/utils/style'; +import { useTheme } from '@/hooks/useTheme'; import { ONE_COLUMN_MAX_INLINE_SIZE } from '@/services/constants'; import { handleKeydown, @@ -61,6 +62,7 @@ const FoliateViewer: React.FC<{ const [viewInited, setViewInited] = useState(false); const isViewCreated = useRef(false); const { setView: setFoliateView, setProgress, getViewSettings } = useReaderStore(); + const { themeCode } = useTheme(); const progressRelocateHandler = (event: Event) => { const detail = (event as CustomEvent).detail; @@ -118,7 +120,6 @@ const FoliateViewer: React.FC<{ await view.open(bookDoc); const viewSettings = getViewSettings(bookKey)!; - view.renderer.setStyles?.(getStyles(viewSettings)); const isScrolled = viewSettings.scrolled!; const marginPx = viewSettings.marginPx!; const gapPercent = viewSettings.gapPercent!; @@ -146,6 +147,7 @@ const FoliateViewer: React.FC<{ await view.goToFraction(0); } setViewInited(true); + view.renderer.setStyles?.(getStyles(viewSettings, themeCode)); window.addEventListener('message', handleClickTurnPage); }; diff --git a/apps/readest-app/src/app/reader/components/FooterBar.tsx b/apps/readest-app/src/app/reader/components/FooterBar.tsx index 1e4aa468..9b4db7a2 100644 --- a/apps/readest-app/src/app/reader/components/FooterBar.tsx +++ b/apps/readest-app/src/app/reader/components/FooterBar.tsx @@ -42,12 +42,12 @@ const FooterBar: React.FC = ({ bookKey, pageinfo, isHoveredAnim - + {pageinfoValid ? `${Math.round(progressFraction * 100)}%` : ''} = ({ bookKey }) => { return ( ); diff --git a/apps/readest-app/src/app/reader/components/PageInfo.tsx b/apps/readest-app/src/app/reader/components/PageInfo.tsx index d981eb9c..74d21160 100644 --- a/apps/readest-app/src/app/reader/components/PageInfo.tsx +++ b/apps/readest-app/src/app/reader/components/PageInfo.tsx @@ -23,7 +23,9 @@ const PageInfoView: React.FC = ({ bookFormat, section, pageinfo, className='pageinfo absolute bottom-0 left-0 right-0 flex h-12 items-center justify-end' style={{ paddingRight: gapRight }} > -

{pageInfo}

+

+ {pageInfo} +

); }; diff --git a/apps/readest-app/src/app/reader/components/ReaderContent.tsx b/apps/readest-app/src/app/reader/components/ReaderContent.tsx index 3258ec7f..50111a9f 100644 --- a/apps/readest-app/src/app/reader/components/ReaderContent.tsx +++ b/apps/readest-app/src/app/reader/components/ReaderContent.tsx @@ -90,7 +90,7 @@ const ReaderContent: React.FC<{ settings: SystemSettings }> = ({ settings }) => } return ( -
+
diff --git a/apps/readest-app/src/app/reader/components/SectionInfo.tsx b/apps/readest-app/src/app/reader/components/SectionInfo.tsx index a5803685..d7291357 100644 --- a/apps/readest-app/src/app/reader/components/SectionInfo.tsx +++ b/apps/readest-app/src/app/reader/components/SectionInfo.tsx @@ -20,7 +20,9 @@ const SectionInfo: React.FC = ({ section, gapLeft }) => { )} style={{ left: gapLeft }} > -

{section || ''}

+

+ {section || ''} +

); }; diff --git a/apps/readest-app/src/app/reader/components/SidebarToggler.tsx b/apps/readest-app/src/app/reader/components/SidebarToggler.tsx index 54cfa2b5..02bfc680 100644 --- a/apps/readest-app/src/app/reader/components/SidebarToggler.tsx +++ b/apps/readest-app/src/app/reader/components/SidebarToggler.tsx @@ -20,9 +20,9 @@ const SidebarToggler: React.FC = ({ bookKey }) => { return ( ); diff --git a/apps/readest-app/src/app/reader/components/ViewMenu.tsx b/apps/readest-app/src/app/reader/components/ViewMenu.tsx index a0a1c258..f61a1296 100644 --- a/apps/readest-app/src/app/reader/components/ViewMenu.tsx +++ b/apps/readest-app/src/app/reader/components/ViewMenu.tsx @@ -2,9 +2,12 @@ import clsx from 'clsx'; import React, { useEffect } from 'react'; import { useState } from 'react'; import { BiMoon, BiSun } from 'react-icons/bi'; +import { TbSunMoon } from 'react-icons/tb'; import { MdZoomOut, MdZoomIn, MdCheck } from 'react-icons/md'; +import MenuItem from '@/components/MenuItem'; import { useReaderStore } from '@/store/readerStore'; +import { useTheme, ThemeMode } from '@/hooks/useTheme'; import { getStyles } from '@/utils/style'; interface ViewMenuProps { @@ -21,7 +24,7 @@ const ViewMenu: React.FC = ({ const { getView, getViewSettings, setViewSettings } = useReaderStore(); const viewSettings = getViewSettings(bookKey); - const [isDarkMode, setDarkMode] = useState(viewSettings!.theme === 'dark'); + const { themeMode, isDarkMode, themeCode, updateThemeMode } = useTheme(); const [isScrolledMode, setScrolledMode] = useState(viewSettings!.scrolled); const [isInvertedColors, setInvertedColors] = useState(viewSettings!.invert); const [zoomLevel, setZoomLevel] = useState(viewSettings!.zoomLevel!); @@ -30,7 +33,6 @@ const ViewMenu: React.FC = ({ const zoomOut = () => setZoomLevel((prev) => Math.max(prev - 10, 50)); const resetZoom = () => setZoomLevel(100); const toggleScrolledMode = () => setScrolledMode(!isScrolledMode); - const toggleDarkMode = () => setDarkMode(!isDarkMode); const toggleInvertedColors = () => setInvertedColors(!isInvertedColors); const openFontLayoutMenu = () => { @@ -38,6 +40,16 @@ const ViewMenu: React.FC = ({ onSetSettingsDialogOpen(true); }; + const cycleThemeMode = () => { + const nextMode: ThemeMode = + themeMode === 'auto' ? 'light' : themeMode === 'light' ? 'dark' : 'auto'; + updateThemeMode(nextMode); + }; + + useEffect(() => { + getView(bookKey)?.renderer.setStyles?.(getStyles(viewSettings!, themeCode)); + }, [themeCode]); + useEffect(() => { getView(bookKey)?.renderer.setAttribute('flow', isScrolledMode ? 'scrolled' : 'paginated'); viewSettings!.scrolled = isScrolledMode; @@ -46,6 +58,7 @@ const ViewMenu: React.FC = ({ useEffect(() => { document.body.classList.toggle('invert', isInvertedColors); + getView(bookKey)?.renderer.setStyles?.(getStyles(viewSettings!, themeCode)); }, [isInvertedColors]); useEffect(() => { @@ -53,7 +66,7 @@ const ViewMenu: React.FC = ({ if (!view) return; // FIXME: zoom level is not working in paginated mode if (viewSettings?.scrolled) { - view.renderer.setStyles?.(getStyles(viewSettings!)); + view.renderer.setStyles?.(getStyles(viewSettings!, themeCode)); } viewSettings!.zoomLevel = zoomLevel; setViewSettings(bookKey, viewSettings!); @@ -63,7 +76,7 @@ const ViewMenu: React.FC = ({
= ({ >
-
+
- + - + /> -
+
- - + disabled={!isDarkMode} + />
); }; diff --git a/apps/readest-app/src/app/reader/components/notebook/Header.tsx b/apps/readest-app/src/app/reader/components/notebook/Header.tsx index 42a85c5e..dda5eac3 100644 --- a/apps/readest-app/src/app/reader/components/notebook/Header.tsx +++ b/apps/readest-app/src/app/reader/components/notebook/Header.tsx @@ -14,7 +14,7 @@ const NotebookHeader: React.FC<{
diff --git a/apps/readest-app/src/app/reader/components/notebook/NoteEditor.tsx b/apps/readest-app/src/app/reader/components/notebook/NoteEditor.tsx index 5fe23a81..50ac438b 100644 --- a/apps/readest-app/src/app/reader/components/notebook/NoteEditor.tsx +++ b/apps/readest-app/src/app/reader/components/notebook/NoteEditor.tsx @@ -48,7 +48,7 @@ const NoteEditor: React.FC = ({ onSave, onEdit }) => { }; return ( -
+