feat: Custom CSS
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
import { shallowEqual, useSelector } from "react-redux";
|
||||
import { showChapterTitlesAction } from "../redux/novel/novel.actions";
|
||||
import { useSelector } from "react-redux";
|
||||
import { darkTheme } from "../theme/theme";
|
||||
|
||||
const useTheme = () => {
|
||||
|
||||
@@ -54,6 +54,7 @@ const initialState = {
|
||||
padding: 5,
|
||||
fontFamily: "",
|
||||
lineHeight: 1.5,
|
||||
customCSS: null,
|
||||
},
|
||||
showDownloadBadges: true,
|
||||
showUnreadBadges: true,
|
||||
|
||||
@@ -6,16 +6,15 @@ import {
|
||||
StatusBar,
|
||||
ScrollView,
|
||||
TouchableWithoutFeedback,
|
||||
Dimensions,
|
||||
Pressable,
|
||||
} from "react-native";
|
||||
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { IconButton, Portal } from "react-native-paper";
|
||||
import {
|
||||
hideNavigationBar,
|
||||
showNavigationBar,
|
||||
} from "react-native-navigation-bar-color";
|
||||
import WebView from "react-native-webview";
|
||||
|
||||
import {
|
||||
getChapterFromDB,
|
||||
@@ -51,7 +50,6 @@ import GestureRecognizer from "react-native-swipe-gestures";
|
||||
import { LoadingScreen } from "../../components/LoadingScreen/LoadingScreen";
|
||||
import { insertHistory } from "../../database/queries/HistoryQueries";
|
||||
import { SET_LAST_READ } from "../../redux/preferences/preference.types";
|
||||
import WebView from "react-native-webview";
|
||||
import { htmlToText } from "../../sources/helpers/htmlToText";
|
||||
import { setAppSettings } from "../../redux/settings/settings.actions";
|
||||
import { cleanHtml } from "../../sources/helpers/cleanHtml";
|
||||
@@ -275,13 +273,6 @@ const Chapter = ({ route, navigation }) => {
|
||||
})
|
||||
: showToast("There's no next chapter");
|
||||
|
||||
const onPressLink = async (link) => {
|
||||
setLoading(true);
|
||||
const res = await fetchChapter(sourceId, novelUrl, link);
|
||||
setChapter(res);
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
const enableSwipeGestures = () => {
|
||||
dispatch(setAppSettings("swipeGestures", !swipeGestures));
|
||||
showToast(
|
||||
@@ -419,9 +410,6 @@ const Chapter = ({ route, navigation }) => {
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
span[style] {
|
||||
color: ${reader.textColor} !important;
|
||||
}
|
||||
a {
|
||||
color: ${theme.colorAccent};
|
||||
}
|
||||
@@ -437,6 +425,8 @@ const Chapter = ({ route, navigation }) => {
|
||||
reader.fontFamily
|
||||
}.ttf");
|
||||
}
|
||||
|
||||
${reader.customCSS}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
import React, { useState } from "react";
|
||||
import { Pressable, ScrollView, StyleSheet, Text, View } from "react-native";
|
||||
import {
|
||||
Pressable,
|
||||
ScrollView,
|
||||
StyleSheet,
|
||||
Text,
|
||||
TextInput,
|
||||
View,
|
||||
} from "react-native";
|
||||
import { Button } from "react-native-paper";
|
||||
import WebView from "react-native-webview";
|
||||
import { useDispatch } from "react-redux";
|
||||
|
||||
import { Appbar } from "../../components/Appbar";
|
||||
@@ -84,31 +93,67 @@ const ReaderSettings = ({ navigation }) => {
|
||||
{ value: "right", icon: "format-align-right" },
|
||||
];
|
||||
|
||||
const [customHtmlCSS, setcustomHtmlCSS] = useState(reader.customCSS);
|
||||
|
||||
return (
|
||||
<ScreenContainer theme={theme}>
|
||||
<Appbar title="Reader" onBackAction={navigation.goBack} />
|
||||
<View style={{ height: 360 }}>
|
||||
<WebView
|
||||
originWhitelist={["*"]}
|
||||
style={{
|
||||
backgroundColor: readerBackground(reader.theme),
|
||||
}}
|
||||
source={{
|
||||
html: `
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
|
||||
<style>
|
||||
@font-face {
|
||||
font-family: ${reader.fontFamily};
|
||||
src: url("file:///android_asset/fonts/${reader.fontFamily}.ttf");
|
||||
}
|
||||
body {
|
||||
padding-top: 8px;
|
||||
padding-bottom: 8px;
|
||||
padding-left: ${reader.padding}%;
|
||||
padding-right: ${reader.padding}%;
|
||||
font-family: ${reader.fontFamily};
|
||||
text-align: ${reader.textAlign};
|
||||
line-height: ${reader.lineHeight};
|
||||
font-size: ${reader.textSize}px;
|
||||
color: ${reader.textColor};
|
||||
}
|
||||
${reader.customCSS}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
Ut lobortis nunc id nisl tempor, sed tristique sem
|
||||
sagittis. Mauris consequat orci egestas volutpat
|
||||
vestibulum. Nullam convallis, leo in porttitor
|
||||
fringilla, ex mi finibus felis, non molestie ligula
|
||||
ligula facilisis ligula. Nam eu est a turpis porttitor
|
||||
aliquet sed vel risus. Ut ac scelerisque diam. Nulla
|
||||
fringilla enim non ex rhoncus faucibus. Integer eget
|
||||
lacus justo.
|
||||
</p>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
Ut lobortis nunc id nisl tempor, sed tristique sem
|
||||
sagittis. Mauris consequat orci egestas volutpat
|
||||
vestibulum. Nullam convallis, leo in porttitor
|
||||
fringilla, ex mi finibus felis, non molestie ligula
|
||||
ligula facilisis ligula.
|
||||
</body>
|
||||
</html>
|
||||
`,
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
<ScrollView>
|
||||
<View
|
||||
style={{ backgroundColor: readerBackground(reader.theme) }}
|
||||
>
|
||||
<Text style={readerStyles}>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
Ut lobortis nunc id nisl tempor, sed tristique sem
|
||||
sagittis. Mauris consequat orci egestas volutpat
|
||||
vestibulum. Nullam convallis, leo in porttitor
|
||||
fringilla, ex mi finibus felis, non molestie ligula
|
||||
ligula facilisis ligula. Nam eu est a turpis porttitor
|
||||
aliquet sed vel risus. Ut ac scelerisque diam. Nulla
|
||||
fringilla enim non ex rhoncus faucibus. Integer eget
|
||||
lacus justo. Lorem ipsum dolor sit amet, consectetur
|
||||
adipiscing elit. Ut vitae tempor metus. Morbi nec nisl
|
||||
cursus, gravida ex vitae, laoreet leo. Pellentesque in
|
||||
lectus ante. Aliquam porta suscipit pretium. Sed ut
|
||||
ligula at dolor pretium egestas quis vitae urna. In
|
||||
ullamcorper venenatis orci, eu pulvinar nibh venenatis
|
||||
sit amet.
|
||||
</Text>
|
||||
</View>
|
||||
<List.Section>
|
||||
<List.SubHeader theme={theme}>Preset</List.SubHeader>
|
||||
<View style={styles.pressableListItem}>
|
||||
@@ -215,8 +260,52 @@ const ReaderSettings = ({ navigation }) => {
|
||||
))}
|
||||
</Row>
|
||||
</Pressable>
|
||||
<List.Divider theme={theme} />
|
||||
<List.SubHeader theme={theme}>CSS</List.SubHeader>
|
||||
<View style={{ paddingHorizontal: 16, paddingBottom: 8 }}>
|
||||
<TextInput
|
||||
style={{
|
||||
color: theme.textColorPrimary,
|
||||
fontSize: 16,
|
||||
}}
|
||||
value={customHtmlCSS}
|
||||
onChangeText={(text) => setcustomHtmlCSS(text)}
|
||||
placeholderTextColor={theme.textColorSecondary}
|
||||
placeholder="Example: body { color: red; }"
|
||||
multiline={true}
|
||||
/>
|
||||
<View style={{ flexDirection: "row-reverse" }}>
|
||||
<Button
|
||||
uppercase={false}
|
||||
color={theme.colorAccent}
|
||||
onPress={() =>
|
||||
dispatch(
|
||||
setReaderSettings(
|
||||
"customCSS",
|
||||
customHtmlCSS
|
||||
)
|
||||
)
|
||||
}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
<Button
|
||||
uppercase={false}
|
||||
color={theme.colorAccent}
|
||||
onPress={() => {
|
||||
setcustomHtmlCSS("");
|
||||
dispatch(
|
||||
setReaderSettings("customCSS", "")
|
||||
);
|
||||
}}
|
||||
>
|
||||
Clear
|
||||
</Button>
|
||||
</View>
|
||||
</View>
|
||||
</List.Section>
|
||||
</ScrollView>
|
||||
|
||||
<ColorPickerModal
|
||||
title="Reader background color"
|
||||
modalVisible={readerBackgroundColorModal}
|
||||
|
||||
@@ -2,7 +2,10 @@ export const cleanHtml = (html) => {
|
||||
let text = html;
|
||||
|
||||
text = text
|
||||
.replace(/(font-family|line-height|font-size|text-align):.*?;/gi, "")
|
||||
.replace(
|
||||
/style="((?:color|font-family|line-height|font-size|text-align).*?)"/gi,
|
||||
""
|
||||
)
|
||||
.replace(/class=".*?"/gi, "")
|
||||
.replace(/id=".*?"/gi, "")
|
||||
.replace(/<!--.*?-->/gim, "")
|
||||
|
||||
Reference in New Issue
Block a user