From 59cec59f7818be99b6f5bc6cb794e805b7fb52c5 Mon Sep 17 00:00:00 2001 From: chrox Date: Sun, 3 Nov 2024 14:31:21 +0100 Subject: [PATCH] Add user custom style in MiscPanel --- apps/readest-app/package.json | 2 + .../reader/components/settings/ColorPanel.tsx | 26 +++---- .../reader/components/settings/FontPanel.tsx | 8 +-- .../components/settings/LayoutPanel.tsx | 4 +- .../reader/components/settings/MiscPanel.tsx | 69 ++++++++++++++++++- .../components/settings/NumberInput.tsx | 6 +- pnpm-lock.yaml | 17 +++++ 7 files changed, 110 insertions(+), 22 deletions(-) diff --git a/apps/readest-app/package.json b/apps/readest-app/package.json index abda1948..39eee759 100644 --- a/apps/readest-app/package.json +++ b/apps/readest-app/package.json @@ -24,6 +24,7 @@ "@tauri-apps/plugin-os": "^2.0.0", "@zip.js/zip.js": "^2.7.52", "clsx": "^2.1.1", + "cssbeautify": "^0.3.1", "epubjs": "^0.3.93", "foliate-js": "workspace:*", "js-md5": "^0.8.3", @@ -36,6 +37,7 @@ }, "devDependencies": { "@tauri-apps/cli": "2.0.4", + "@types/cssbeautify": "^0.3.5", "@types/node": "^20", "@types/react": "18.3.12", "@types/react-dom": "18.3.1", 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 ce198392..d584926c 100644 --- a/apps/readest-app/src/app/reader/components/settings/ColorPanel.tsx +++ b/apps/readest-app/src/app/reader/components/settings/ColorPanel.tsx @@ -15,18 +15,20 @@ const ColorPanel: React.FC<{ bookKey: string }> = () => { ]; return ( -
-

Color Settings

-
- {themes.map((theme) => ( - - ))} +
+
+

Color Settings

+
+ {themes.map((theme) => ( + + ))} +
); diff --git a/apps/readest-app/src/app/reader/components/settings/FontPanel.tsx b/apps/readest-app/src/app/reader/components/settings/FontPanel.tsx index 9d7936e5..b3b3213e 100644 --- a/apps/readest-app/src/app/reader/components/settings/FontPanel.tsx +++ b/apps/readest-app/src/app/reader/components/settings/FontPanel.tsx @@ -134,7 +134,7 @@ const FontPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => { return (
-
+

Font Size

@@ -143,7 +143,7 @@ const FontPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => { label='Default Font Size' value={defaultFontSize} onChange={setDefaultFontSize} - min={1} + min={minFontSize} max={120} /> = ({ bookKey }) => {
-
+

Font Family

@@ -185,7 +185,7 @@ const FontPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => {
-
+

Font Face

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 82b3836f..e0ecfd7b 100644 --- a/apps/readest-app/src/app/reader/components/settings/LayoutPanel.tsx +++ b/apps/readest-app/src/app/reader/components/settings/LayoutPanel.tsx @@ -92,7 +92,7 @@ const LayoutPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => { return (
-
+

Paragraph

@@ -127,7 +127,7 @@ const LayoutPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => {
-
+

Page

diff --git a/apps/readest-app/src/app/reader/components/settings/MiscPanel.tsx b/apps/readest-app/src/app/reader/components/settings/MiscPanel.tsx index b34acd4c..1de6ae10 100644 --- a/apps/readest-app/src/app/reader/components/settings/MiscPanel.tsx +++ b/apps/readest-app/src/app/reader/components/settings/MiscPanel.tsx @@ -1,5 +1,10 @@ import React, { useEffect, useState } from 'react'; import { useReaderStore } from '@/store/readerStore'; +import cssbeautify from 'cssbeautify'; +import { getStyles } from '@/utils/style'; + +const cssRegex = + /((?:\s*)([\w#.@*,:\-.:>+~\[\]\"=(),*\s]+)\s*{(?:[\s]*)((?:[A-Za-z\- \s]+[:]\s*['"0-9\w .,\/\()\-!#%]+;?)*)*\s*}(?:\s*))/gim; const MiscPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => { const { books, settings, setSettings, setConfig, getFoliateView } = useReaderStore(); @@ -8,6 +13,48 @@ const MiscPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => { const config = bookState.config!; const [animated, setAnimated] = useState(config.viewSettings!.animated!); + const [userStylesheet, setUserStylesheet] = useState(config.viewSettings!.userStylesheet!); + const [error, setError] = useState(null); + + let cssInput = userStylesheet; + + const validateCSS = (css: string) => { + return cssRegex.test(css); + }; + + const handleUserStylesheetChange = (e: React.ChangeEvent) => { + cssInput = e.target.value; + + try { + const formattedCSS = cssbeautify(cssInput, { + indent: ' ', + openbrace: 'end-of-line', + autosemicolon: true, + }); + setUserStylesheet(formattedCSS); + + if (cssInput && !validateCSS(cssInput)) { + throw new Error('Invalid CSS'); + } + setError(null); + + config.viewSettings!.userStylesheet = formattedCSS; + setConfig(bookKey, config); + if (isFontLayoutSettingsGlobal) { + settings.globalViewSettings.userStylesheet = formattedCSS; + setSettings(settings); + } + getFoliateView(bookKey)?.renderer.setStyles?.(getStyles(config)); + } catch (err) { + setError('Invalid CSS: Please check your input.'); + console.log('CSS Error:', err); + } + }; + + const handleInput = (e: React.FormEvent) => { + e.stopPropagation(); + e.nativeEvent.stopImmediatePropagation(); + }; useEffect(() => { config.viewSettings!.animated = animated; @@ -25,7 +72,7 @@ const MiscPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => { return (
-
+

Animation

@@ -41,6 +88,26 @@ const MiscPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => {
+ +
+

Custom CSS

+
+
+
+