Compare commits

..

11 Commits

Author SHA1 Message Date
Rajarshee Chatterjee a870442022 Remove unused dependencies 2021-04-26 20:43:48 +05:30
Rajarshee Chatterjee a9a176297e Use single screen for all extensions 2021-04-26 18:34:12 +05:30
Rajarshee Chatterjee f4c0a647fb Add fonts in reader 2021-04-26 17:02:36 +05:30
Rajarshee Chatterjee 06e7e45df0 Fix theme name 2021-04-26 12:07:19 +05:30
Rajarshee Chatterjee c538bf4956 Add logo in more screen 2021-04-26 12:06:59 +05:30
Rajarshee Chatterjee e1679a41f1 Fix navigating to chapter from history screen 2021-04-26 12:05:35 +05:30
Rajarshee Chatterjee 3c2f4a59b7 Refactor settings screen 2021-04-26 11:34:04 +05:30
Rajarshee Chatterjee 8c13b1ff12 Add discord link 2021-04-25 19:59:48 +05:30
Rajarshee Chatterjee 45083e5fd1 Fix menu color in light theme 2021-04-25 19:48:49 +05:30
Rajarshee Chatterjee 3b37c1cb33 Disable OTA updates 2021-04-25 08:25:53 +05:30
Rajarshee Chatterjee 48187d7d54 Fix reader padding and update version 2021-04-24 21:55:19 +05:30
47 changed files with 765 additions and 1896 deletions
Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

+6 -1
View File
@@ -15,13 +15,18 @@ import { createDB, deleteDb } from "./src/database/DBHelper";
const getFonts = () =>
Font.loadAsync({
"pt-sans-bold": require("./assets/fonts/PTSansNarrow-Bold.ttf"),
"arbutus-slab": require("./assets/fonts/ArbutusSlab-Regular.ttf"),
domine: require("./assets/fonts/Domine-VariableFont_wght.ttf"),
lato: require("./assets/fonts/Lato-Regular.ttf"),
"noto-sans": require("./assets/fonts/NotoSans-Regular.ttf"),
"open-sans": require("./assets/fonts/OpenSans-Regular.ttf"),
"pt-serif": require("./assets/fonts/PTSerif-Regular.ttf"),
});
const App = () => {
const [fontsLoaded, setFontsLoaded] = useState(false);
useEffect(() => {
// deleteDb();
createDB();
}, []);
+2 -1
View File
@@ -11,7 +11,8 @@
"backgroundColor": "#000000"
},
"updates": {
"fallbackToCacheTimeout": 0
"fallbackToCacheTimeout": 0,
"enabled": false
},
"assetBundlePatterns": ["**/*"],
"ios": {
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

-778
View File
File diff suppressed because it is too large Load Diff
+51 -54
View File
@@ -1,56 +1,53 @@
{
"main": "node_modules/expo/AppEntry.js",
"scripts": {
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"web": "expo start --web",
"eject": "expo eject"
},
"dependencies": {
"@react-native-async-storage/async-storage": "^1.13.2",
"@react-native-community/masked-view": "0.1.10",
"@react-native-community/netinfo": "^5.9.7",
"@react-native-community/slider": "^3.0.3",
"@react-navigation/material-bottom-tabs": "^5.3.10",
"@react-navigation/native": "^5.8.10",
"@react-navigation/stack": "^5.12.8",
"expo": "~40.0.0",
"expo-app-loading": "^1.0.1",
"expo-font": "^8.4.0",
"expo-linear-gradient": "^8.4.0",
"expo-sharing": "~8.5.0",
"expo-sqlite": "~8.5.0",
"expo-status-bar": "~1.0.3",
"expo-web-browser": "~8.6.0",
"moment": "^2.29.1",
"react": "16.13.1",
"react-color-extractor": "^1.1.2",
"react-dom": "16.13.1",
"react-native": "https://github.com/expo/react-native/archive/sdk-40.0.1.tar.gz",
"react-native-collapsible-header-views": "^1.1.2",
"react-native-gesture-handler": "^1.8.0",
"react-native-input-spinner": "^1.7.7",
"react-native-offline": "^5.7.0",
"react-native-paper": "^4.5.0",
"react-native-reanimated": "^1.13.2",
"react-native-safe-area-context": "3.1.9",
"react-native-screens": "~2.15.0",
"react-native-vector-icons": "^7.1.0",
"react-native-web": "~0.13.12",
"react-native-webview": "11.0.0",
"react-redux": "^7.2.2",
"redux": "^4.0.5",
"redux-devtools-extension": "^2.13.9",
"redux-persist": "^6.0.0",
"redux-thunk": "^2.3.0",
"reflect-metadata": "^0.1.13",
"rn-sliding-up-panel": "^2.4.4",
"typeorm": "^0.2.31"
},
"devDependencies": {
"@babel/core": "~7.9.0",
"@types/node": "^14.14.35"
},
"private": true
"main": "node_modules/expo/AppEntry.js",
"scripts": {
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"web": "expo start --web",
"eject": "expo eject"
},
"dependencies": {
"@react-native-async-storage/async-storage": "^1.13.2",
"@react-native-community/masked-view": "0.1.10",
"@react-native-community/netinfo": "^5.9.7",
"@react-native-community/slider": "^3.0.3",
"@react-navigation/material-bottom-tabs": "^5.3.10",
"@react-navigation/native": "^5.8.10",
"@react-navigation/stack": "^5.12.8",
"expo": "~40.0.0",
"expo-app-loading": "^1.0.1",
"expo-font": "^8.4.0",
"expo-linear-gradient": "^8.4.0",
"expo-sharing": "~8.5.0",
"expo-sqlite": "~8.5.0",
"expo-status-bar": "~1.0.3",
"expo-web-browser": "~8.6.0",
"moment": "^2.29.1",
"react": "16.13.1",
"react-dom": "16.13.1",
"react-native": "https://github.com/expo/react-native/archive/sdk-40.0.1.tar.gz",
"react-native-collapsible-header-views": "^1.1.2",
"react-native-gesture-handler": "^1.8.0",
"react-native-offline": "^5.7.0",
"react-native-paper": "^4.5.0",
"react-native-reanimated": "^1.13.2",
"react-native-safe-area-context": "3.1.9",
"react-native-screens": "~2.15.0",
"react-native-vector-icons": "^7.1.0",
"react-native-web": "~0.13.12",
"react-native-webview": "11.0.0",
"react-redux": "^7.2.2",
"redux": "^4.0.5",
"redux-devtools-extension": "^2.13.9",
"redux-persist": "^6.0.0",
"redux-thunk": "^2.3.0",
"reflect-metadata": "^0.1.13",
"rn-sliding-up-panel": "^2.4.4"
},
"devDependencies": {
"@babel/core": "~7.9.0",
"@types/node": "^14.14.35"
},
"private": true
}
@@ -10,11 +10,13 @@ import Constants from "expo-constants";
import { useNavigation } from "@react-navigation/native";
import { useSelector } from "react-redux";
export const Appbar = ({ title, onBackAction }) => {
export const Appbar = ({ title, onBackAction, style }) => {
const theme = useSelector((state) => state.themeReducer.theme);
return (
<MaterialAppbar.Header style={{ backgroundColor: theme.colorPrimary }}>
<MaterialAppbar.Header
style={[{ backgroundColor: theme.colorPrimary }, style]}
>
{onBackAction && (
<MaterialAppbar.BackAction onPress={onBackAction} />
)}
@@ -34,7 +36,7 @@ export const SearchAppbar = ({
getNovels,
setLoading,
screen,
onFilter,
openWebView,
}) => {
const searchRef = useRef(null);
@@ -110,17 +112,15 @@ export const SearchAppbar = ({
}}
/>
)}
<IconButton
icon="filter-variant"
color={theme.textColorSecondary}
style={{ marginRight: 0 }}
size={23}
disabled={typeof onFilter === "function" ? false : true}
/**
* TODO
*/
onPress={() => onFilter?.()}
/>
{openWebView && (
<IconButton
icon="earth"
color={theme.textColorSecondary}
style={{ marginRight: 0 }}
size={23}
onPress={openWebView}
/>
)}
</View>
</TouchableRipple>
);
@@ -10,9 +10,7 @@ const EmptyView = ({ icon, description }) => {
<Text
style={[
styles.emptyViewIcon,
{
color: theme.textColorSecondary,
},
{ color: theme.textColorSecondary },
]}
>
{icon}
@@ -20,9 +18,7 @@ const EmptyView = ({ icon, description }) => {
<Text
style={[
styles.emptyViewText,
{
color: theme.textColorSecondary,
},
{ color: theme.textColorSecondary },
]}
>
{description}
+57
View File
@@ -0,0 +1,57 @@
import React from "react";
import { StyleSheet } from "react-native";
import { List, Divider as PaperDivider } from "react-native-paper";
const ListSection = ({ children }) => (
<List.Section style={styles.listSection}>{children}</List.Section>
);
const ListSubHeader = ({ children, theme }) => (
<List.Subheader
style={[styles.listSubHeader, { color: theme.colorAccentDark }]}
>
{children}
</List.Subheader>
);
const ListItem = ({ title, description, icon, onPress, theme }) => (
<List.Item
title={title}
titleStyle={{ color: theme.textColorPrimary }}
description={description}
descriptionStyle={{ color: theme.textColorSecondary }}
descriptionNumberOfLines={1}
left={() =>
icon && (
<List.Icon
color={theme.colorAccentDark}
icon={icon}
style={{ marginVertical: 0 }}
/>
)
}
onPress={onPress}
rippleColor={theme.rippleColor}
/>
);
const Divider = ({ theme }) => (
<PaperDivider
style={{
backgroundColor: theme.dividerColor,
height: 1,
}}
/>
);
export { ListSection, ListSubHeader, ListItem, Divider };
const styles = StyleSheet.create({
listSection: {
flex: 1,
marginVertical: 0,
},
listSubHeader: {
paddingBottom: 5,
},
});
-41
View File
@@ -1,41 +0,0 @@
import React from "react";
import { Checkbox } from "react-native-paper";
import { useSelector } from "react-redux";
export const DisplayCheckbox = ({ displayMode, onPress, value }) => {
const theme = useSelector((state) => state.themeReducer.theme);
const label = {
0: "Compact Grid",
1: "Comfortable Grid",
2: "List",
};
return (
<Checkbox.Item
label={label[value]}
labelStyle={{ color: theme.textColorPrimary }}
status={displayMode === value ? "checked" : "unchecked"}
mode="ios"
uncheckedColor={theme.textColorSecondary}
color={theme.colorAccentDark}
onPress={onPress}
/>
);
};
export const ThemeCheckbox = ({ onPress, label, checked }) => {
const theme = useSelector((state) => state.themeReducer.theme);
return (
<Checkbox.Item
label={label}
labelStyle={{ color: theme.textColorPrimary }}
status={checked ? "checked" : "unchecked"}
mode="ios"
uncheckedColor={theme.textColorSecondary}
color={theme.colorAccentDark}
onPress={onPress}
/>
);
};
+6 -20
View File
@@ -21,11 +21,7 @@ import Settings from "../screens/More/Settings";
import NovelItem from "../screens/Novel/Novel";
import ChapterItem from "../screens/Chapter/Chapter";
// Extensions
import BoxNovel from "../screens/extensions/boxnovel/BoxNovel";
import ReadLightNovel from "../screens/extensions/readlightnovel/ReadLightNovel";
import FastNovel from "../screens/extensions/fastnovel/FastNovel";
import ReadNovelFull from "../screens/extensions/readnovelfull/ReadNovelFull";
import Extension from "../screens/Extension/Extension";
const Stack = createStackNavigator();
@@ -45,17 +41,6 @@ const SettingsStack = () => {
);
};
const ExtensionStack = () => {
return (
<Stack.Navigator screenOptions={stackNavigatorConfig}>
<Stack.Screen name="BoxNovel" component={BoxNovel} />
<Stack.Screen name="ReadLightNovel" component={ReadLightNovel} />
<Stack.Screen name="FastNovel" component={FastNovel} />
<Stack.Screen name="ReadNovelFull" component={ReadNovelFull} />
</Stack.Navigator>
);
};
import { useSelector } from "react-redux";
const BottomNavigator = () => {
@@ -138,9 +123,9 @@ const BottomNavigator = () => {
};
const Router = () => {
const themeCode = useSelector((state) => state.themeReducer.themeCode);
const theme = useSelector((state) => state.themeReducer.theme);
useEffect(() => setStatusBarStyle(themeCode === 1 ? "dark" : "light"), []);
useEffect(() => setStatusBarStyle(theme.id === 1 ? "dark" : "light"), []);
return (
<Provider>
@@ -162,10 +147,11 @@ const Router = () => {
}}
/>
<Stack.Screen name="SettingsStack" component={SettingsStack} />
<Stack.Screen
<Stack.Screen name="Extension" component={Extension} />
{/* <Stack.Screen
name="ExtensionStack"
component={ExtensionStack}
/>
/> */}
</Stack.Navigator>
</Provider>
);
+8
View File
@@ -5,6 +5,7 @@ import {
UPDATE_READER_THEME,
UPDATE_READER_TEXT_ALIGN,
UPDATE_READER_PADDING,
SET_READER_FONT,
} from "./settings.types";
export const setDisplayMode = (val) => (dispatch) => {
@@ -48,3 +49,10 @@ export const updateReaderPadding = (val) => (dispatch) => {
payload: val,
});
};
export const setReaderFont = (val) => (dispatch) => {
dispatch({
type: SET_READER_FONT,
payload: val,
});
};
+8 -1
View File
@@ -1,6 +1,7 @@
import {
SET_DISPLAY_MODE,
SET_ITEMS_PER_ROW,
SET_READER_FONT,
UPDATE_READER_PADDING,
UPDATE_READER_TEXT_ALIGN,
UPDATE_READER_TEXT_SIZE,
@@ -14,7 +15,8 @@ const initialState = {
theme: 1,
textSize: 16,
textAlign: "left",
padding: "5",
padding: 5,
fontFamily: null,
},
};
@@ -62,6 +64,11 @@ const settingsReducer = (state = initialState, action) => {
...state,
reader: { ...state.reader, padding: payload },
};
case SET_READER_FONT:
return {
...state,
reader: { ...state.reader, fontFamily: payload },
};
default:
return state;
}
+1
View File
@@ -4,3 +4,4 @@ export const UPDATE_READER_THEME = "UPDATE_READER_THEME";
export const UPDATE_READER_TEXT_SIZE = "UPDATE_READER_TEXT_SIZE";
export const UPDATE_READER_TEXT_ALIGN = "UPDATE_READER_TEXT_ALIGN";
export const UPDATE_READER_PADDING = "UPDATE_READER_PADDING";
export const SET_READER_FONT = "SET_READER_FONT";
-7
View File
@@ -1,12 +1,5 @@
import { SWITCH_THEME } from "./theme.types";
/**
* 0 -> Amoled Dark Theme
* 1 -> Light Theme
* 2 -> Dark Theme
* 3 -> Midnight Dusk Theme
*/
export const switchTheme = (val) => (dispatch) => {
dispatch({
type: SWITCH_THEME,
+1 -2
View File
@@ -13,7 +13,6 @@ const themes = {
};
const initialState = {
themeCode: 0,
theme: themes[0],
};
@@ -22,7 +21,7 @@ const themeReducer = (state = initialState, action) => {
switch (type) {
case "SWITCH_THEME":
return { ...state, themeCode: payload, theme: themes[payload] };
return { ...state, theme: themes[payload] };
default:
return state;
}
+1 -2
View File
@@ -1,6 +1,6 @@
import React, { useEffect } from "react";
import { StyleSheet, View, FlatList, ActivityIndicator } from "react-native";
import { Appbar } from "../../components/common/Appbar";
import { Appbar } from "../../components/Appbar";
import { connect } from "react-redux";
import { getSourcesAction } from "../../redux/source/source.actions";
@@ -51,6 +51,5 @@ export default connect(mapStateToProps, { getSourcesAction })(Browse);
const styles = StyleSheet.create({
container: {
flex: 1,
paddingHorizontal: 4,
},
});
+11 -10
View File
@@ -6,7 +6,7 @@ import { useNavigation } from "@react-navigation/native";
import { useSelector } from "react-redux";
const ExtensionCard = ({ item }) => {
const { sourceId, sourceName, sourceCover, sourceLanguage } = item;
const { sourceName, sourceCover, sourceLanguage, status } = item;
const navigation = useNavigation();
@@ -16,8 +16,10 @@ const ExtensionCard = ({ item }) => {
<TouchableRipple
style={styles.extensionCard}
onPress={() =>
navigation.navigate("ExtensionStack", {
screen: sourceName,
navigation.navigate("Extension", {
sourceId: item.sourceId,
sourceName: item.sourceName,
sourceUrl: item.sourceUrl,
})
}
rippleColor={theme.rippleColor}
@@ -25,9 +27,7 @@ const ExtensionCard = ({ item }) => {
>
<>
<Image
source={{
uri: sourceCover,
}}
source={{ uri: sourceCover }}
style={styles.extensionIcon}
resizeMode="contain"
/>
@@ -57,7 +57,7 @@ const ExtensionCard = ({ item }) => {
marginLeft: 5,
}}
>
{sourceId === 3 && "(Not Working)"}
{status === 0 && "(Not Working)"}
</Text>
</View>
</View>
@@ -69,8 +69,10 @@ const ExtensionCard = ({ item }) => {
uppercase={false}
color={theme.colorAccentDark}
onPress={() =>
navigation.navigate("ExtensionStack", {
screen: sourceName,
navigation.navigate("Extension", {
sourceId: item.sourceId,
sourceName: item.sourceName,
sourceUrl: item.sourceUrl,
})
}
>
@@ -92,7 +94,6 @@ const styles = StyleSheet.create({
marginVertical: 4,
paddingVertical: 8,
paddingHorizontal: 20,
borderRadius: 4,
},
extensionIcon: {
width: 40,
+5
View File
@@ -59,7 +59,9 @@ const ChapterItem = ({
const readerLineHeight = (val) => {
const lineHeight = {
12: 20,
14: 22,
16: 25,
18: 26,
20: 28,
};
return lineHeight[val];
@@ -173,6 +175,9 @@ const ChapterItem = ({
textAlign: reader.textAlign,
paddingHorizontal: `${reader.padding}%`,
},
reader.fontFamily && {
fontFamily: reader.fontFamily,
},
]}
>
{chapter.chapterText.trim()}
+147 -86
View File
@@ -1,19 +1,20 @@
import React from "react";
import { Animated, StyleSheet, View, Text, Dimensions } from "react-native";
import { ToggleButton, IconButton } from "react-native-paper";
import { ToggleButton, IconButton, Chip } from "react-native-paper";
import Slider from "@react-native-community/slider";
import Bottomsheet from "rn-sliding-up-panel";
import { fonts } from "../../../utils/constants";
import { connect } from "react-redux";
import {
setReaderFont,
updateReaderPadding,
updateReaderTextAlign,
updateReaderTextSize,
updateReaderTheme,
} from "../../../redux/settings/settings.actions";
import BottomSheetHandle from "../../../components/common/BottomSheetHandle";
import BottomSheetHandle from "../../../components/BottomSheetHandle";
const ChapterBottomSheet = ({
bottomSheetRef,
@@ -23,13 +24,14 @@ const ChapterBottomSheet = ({
updateReaderTheme,
updateReaderTextAlign,
updateReaderPadding,
setReaderFont,
}) => {
return (
<Bottomsheet
animatedValue={new Animated.Value(0)}
ref={bottomSheetRef}
draggableRange={{ top: 360, bottom: 0 }}
snappingPoints={[0, 360]}
draggableRange={{ top: 400, bottom: 0 }}
snappingPoints={[0, 400]}
showBackdrop={false}
>
<View style={styles.contentContainer}>
@@ -37,7 +39,7 @@ const ChapterBottomSheet = ({
<View style={styles.readerSettingsContainer}>
<Text
style={{
color: theme.textColorPrimary,
color: "#FFFFFF",
fontWeight: "bold",
}}
>
@@ -57,94 +59,116 @@ const ChapterBottomSheet = ({
thumbTintColor={theme.colorAccentDark}
onValueChange={(value) => updateReaderTextSize(value)}
/>
<Text
<View
style={{
color: theme.textColorPrimary,
fontWeight: "bold",
flexDirection: "row",
justifyContent: "center",
}}
>
Reader Theme
</Text>
<ToggleButton.Row
onValueChange={(value) => updateReaderTheme(value)}
value={reader.theme}
style={{ marginTop: 10 }}
>
<ToggleButton
icon="format-text"
color="#FFFFFF"
value={1}
<View
style={{
backgroundColor: "#000000",
marginHorizontal: 10,
justifyContent: "center",
alignItems: "center",
}}
/>
<ToggleButton
icon="format-text"
color="#000000"
value={2}
>
<Text
style={{
color: "#FFFFFF",
fontWeight: "bold",
}}
>
Reader Theme
</Text>
<ToggleButton.Row
onValueChange={(value) =>
updateReaderTheme(value)
}
value={reader.theme}
style={{ marginTop: 10 }}
>
<ToggleButton
icon="format-text"
color="#FFFFFF"
value={1}
style={{
backgroundColor: "#000000",
marginHorizontal: 10,
}}
/>
<ToggleButton
icon="format-text"
color="#000000"
value={2}
style={{
backgroundColor: "#FFFFFF",
marginHorizontal: 10,
}}
/>
<ToggleButton
icon="format-text"
color="#000000"
value={3}
style={{
backgroundColor: "#F4ECD8",
marginHorizontal: 10,
}}
/>
</ToggleButton.Row>
</View>
<View
style={{
backgroundColor: "#FFFFFF",
marginHorizontal: 10,
justifyContent: "center",
alignItems: "center",
}}
/>
<ToggleButton
icon="format-text"
color="#000000"
value={3}
style={{
backgroundColor: "#F4ECD8",
marginHorizontal: 10,
}}
/>
</ToggleButton.Row>
>
<Text
style={{
color: "#FFFFFF",
fontWeight: "bold",
}}
>
Text Align
</Text>
<ToggleButton.Row
onValueChange={(value) =>
updateReaderTextAlign(value ?? "left")
}
value={reader.textAlign}
style={{ marginTop: 10 }}
>
<ToggleButton
icon="format-align-left"
color="#000000"
value="left"
style={{
backgroundColor: "#FFFFFF",
marginHorizontal: 10,
}}
/>
<ToggleButton
icon="format-align-justify"
color="#000000"
value="justify"
style={{
backgroundColor: "#FFFFFF",
marginHorizontal: 10,
}}
/>
<ToggleButton
icon="format-align-right"
color="#000000"
value="right"
style={{
backgroundColor: "#FFFFFF",
marginHorizontal: 10,
}}
/>
</ToggleButton.Row>
</View>
</View>
<Text
style={{
color: theme.textColorPrimary,
fontWeight: "bold",
marginTop: 10,
}}
>
Text Align
</Text>
<ToggleButton.Row
onValueChange={(value) =>
updateReaderTextAlign(value ?? "left")
}
value={reader.textAlign}
style={{ marginTop: 10 }}
>
<ToggleButton
icon="format-align-left"
color="#000000"
value="left"
style={{
backgroundColor: "#FFFFFF",
marginHorizontal: 10,
}}
/>
<ToggleButton
icon="format-align-justify"
color="#000000"
value="justify"
style={{
backgroundColor: "#FFFFFF",
marginHorizontal: 10,
}}
/>
<ToggleButton
icon="format-align-right"
color="#000000"
value="right"
style={{
backgroundColor: "#FFFFFF",
marginHorizontal: 10,
}}
/>
</ToggleButton.Row>
<Text
style={{
color: theme.textColorPrimary,
color: "#FFFFFF",
fontWeight: "bold",
marginTop: 10,
}}
@@ -170,7 +194,7 @@ const ChapterBottomSheet = ({
/>
<Text
style={{
color: theme.textColorPrimary,
color: "#FFFFFF",
paddingHorizontal: 50,
}}
>
@@ -186,6 +210,42 @@ const ChapterBottomSheet = ({
}
/>
</View>
<Text
style={{
color: "#FFFFFF",
fontWeight: "bold",
marginTop: 10,
}}
>
Font Style
</Text>
<View
style={{
flexDirection: "row",
flexWrap: "wrap",
justifyContent: "center",
}}
>
{fonts.map((font, index) => (
<Chip
key={index}
onPress={() => setReaderFont(font.fontFamily)}
textStyle={{ fontFamily: font.fontFamily }}
style={{
borderWidth: 0,
marginHorizontal: 5,
marginVertical: 5,
}}
selected={
reader.fontFamily === font.fontFamily
? true
: false
}
>
{font.name}
</Chip>
))}
</View>
</View>
</View>
</Bottomsheet>
@@ -202,6 +262,7 @@ export default connect(mapStateToProps, {
updateReaderTheme,
updateReaderTextAlign,
updateReaderPadding,
setReaderFont,
})(ChapterBottomSheet);
const styles = StyleSheet.create({
@@ -1,14 +1,17 @@
import React, { useEffect, useState } from "react";
import { StyleSheet, View, FlatList, ActivityIndicator } from "react-native";
import { Provider } from "react-native-paper";
import * as WebBrowser from "expo-web-browser";
import NovelCover from "../../../components/common/NovelCover";
import EmptyView from "../../../components/common/EmptyView";
import { SearchAppbar } from "../../../components/common/Appbar";
import NovelCover from "../../components/NovelCover";
import EmptyView from "../../components/EmptyView";
import { SearchAppbar } from "../../components/Appbar";
import { useSelector } from "react-redux";
const ReadLightNovel = ({ navigation }) => {
const Extension = ({ navigation, route }) => {
const { sourceId, sourceName, sourceUrl } = route.params;
const theme = useSelector((state) => state.themeReducer.theme);
const library = useSelector((state) => state.libraryReducer.novels);
const itemsPerRow = useSelector(
@@ -16,13 +19,28 @@ const ReadLightNovel = ({ navigation }) => {
);
const [loading, setLoading] = useState(true);
const [novels, setNovels] = useState();
const [searchText, setSearchText] = useState("");
const getSourceUrl = () => {
if (sourceId === 1) {
return `https://lnreader-extensions.herokuapp.com/api/1/novels/1/?o=rating`;
} else {
return `https://lnreader-extensions.herokuapp.com/api/${sourceId}/novels/`;
}
};
const getSearchUrl = () => {
if (sourceId === 1) {
return `https://lnreader-extensions.herokuapp.com/api/1/search/?s=${searchText}&?o=rating`;
} else {
return `https://lnreader-extensions.herokuapp.com/api/${sourceId}/search/?s=${searchText}`;
}
};
const getNovels = () => {
fetch(`https://lnreader-extensions.herokuapp.com/api/2/novels/`)
fetch(getSourceUrl())
.then((response) => response.json())
.then((json) => {
setNovels(json);
@@ -32,9 +50,7 @@ const ReadLightNovel = ({ navigation }) => {
const getSearchResults = (searchText) => {
setLoading(true);
fetch(
`https://lnreader-extensions.herokuapp.com/api/2/search/?s=${searchText}`
)
fetch(getSearchUrl())
.then((response) => response.json())
.then((json) => {
setNovels(json);
@@ -60,12 +76,13 @@ const ReadLightNovel = ({ navigation }) => {
>
<SearchAppbar
screen="Extension"
placeholder="Search ReadLightNovel"
placeholder={`Search ${sourceName}`}
searchText={searchText}
setSearchText={setSearchText}
getSearchResults={getSearchResults}
getNovels={getNovels}
setLoading={setLoading}
openWebView={() => WebBrowser.openBrowserAsync(sourceUrl)}
/>
{loading ? (
@@ -98,7 +115,6 @@ const ReadLightNovel = ({ navigation }) => {
/>
)}
ListEmptyComponent={
searchText !== "" &&
novels.length === 0 && (
<EmptyView
icon="(; ̄Д ̄)"
@@ -113,7 +129,7 @@ const ReadLightNovel = ({ navigation }) => {
);
};
export default ReadLightNovel;
export default Extension;
const styles = StyleSheet.create({
container: {
+2 -2
View File
@@ -3,11 +3,11 @@ import { useFocusEffect } from "@react-navigation/native";
import { StyleSheet, View, FlatList, ActivityIndicator } from "react-native";
import { Appbar } from "../../components/common/Appbar";
import { Appbar } from "../../components/Appbar";
import HistoryCard from "./components/HistoryCard";
import { connect } from "react-redux";
import EmptyView from "../../components/common/EmptyView";
import EmptyView from "../../components/EmptyView";
import {
getHistoryAction,
@@ -75,11 +75,11 @@ const HistoryCard = ({ item, deleteHistoryAction, navigation }) => {
style={{ marginRight: 10 }}
onPress={() =>
navigation.navigate("ChapterItem", {
chapterId: item.historyChapterId,
chapterUrl: item.chapterUrl,
extensionId: item.extensionId,
extensionId: item.sourceId,
novelUrl: item.novelUrl,
novelName: item.novelName,
novelCover: item.novelCover,
novelId: item.novelId,
chapterName: item.chapterName,
})
}
+3 -3
View File
@@ -11,14 +11,14 @@ import { FlatList } from "react-native-gesture-handler";
import { useFocusEffect } from "@react-navigation/native";
import { connect } from "react-redux";
import NovelCover from "../../components/common/NovelCover";
import EmptyView from "../../components/common/EmptyView";
import NovelCover from "../../components/NovelCover";
import EmptyView from "../../components/EmptyView";
import {
getLibraryAction,
searchLibraryAction,
} from "../../redux/library/library.actions";
import { SearchAppbar } from "../../components/common/Appbar";
import { SearchAppbar } from "../../components/Appbar";
import { setNovel } from "../../redux/novel/novel.actions";
import { updateAllNovels } from "../../services/updates";
+55 -61
View File
@@ -1,10 +1,11 @@
import React from "react";
import { View } from "react-native";
import * as Linking from "expo-linking";
import { List, Divider } from "react-native-paper";
import { Appbar } from "../../components/common/Appbar";
import { Appbar } from "../../components/Appbar";
import { useSelector } from "react-redux";
import { Divider, ListItem, ListSection } from "../../components/List";
const AboutScreen = ({ navigation }) => {
const theme = useSelector((state) => state.themeReducer.theme);
@@ -12,65 +13,58 @@ const AboutScreen = ({ navigation }) => {
return (
<>
<Appbar title="About" onBackAction={() => navigation.goBack()} />
<List.Section
style={{
flex: 1,
marginTop: 0,
backgroundColor: theme.colorPrimaryDark,
marginBottom: 0,
}}
>
<List.Item
titleStyle={{ color: theme.textColorPrimary }}
title="Version"
descriptionStyle={{ color: theme.textColorSecondary }}
description="Stable 1.0.12"
/>
<List.Item
titleStyle={{ color: theme.textColorPrimary }}
title="Build Time"
descriptionStyle={{ color: theme.textColorSecondary }}
description="08-04-21 08:00 AM"
/>
<List.Item
titleStyle={{ color: theme.textColorPrimary }}
title="What's new"
onPress={() =>
Linking.openURL(
"https://github.com/rajarsheechatterjee/lnreader/commits/main"
)
}
rippleColor={theme.rippleColor}
/>
<Divider />
<List.Item
titleStyle={{ color: theme.textColorPrimary }}
descriptionStyle={{ color: theme.textColorSecondary }}
title="Github"
description="https://github.com/rajarsheechatterjee/lnreader"
onPress={() =>
Linking.openURL(
"https://github.com/rajarsheechatterjee/lnreader"
)
}
rippleColor={theme.rippleColor}
/>
<List.Item
titleStyle={{ color: theme.textColorPrimary }}
descriptionStyle={{ color: theme.textColorSecondary }}
title="Extensions"
description="https://github.com/rajarsheechatterjee/lnreader-extensions"
descriptionNumberOfLines={1}
onPress={() =>
Linking.openURL(
"https://github.com/rajarsheechatterjee/lnreader-extensions"
)
}
rippleColor={theme.rippleColor}
/>
</List.Section>
<View style={{ flex: 1, backgroundColor: theme.colorPrimaryDark }}>
<ListSection>
<ListItem
title="Version"
description="Stable 1.0.13"
theme={theme}
/>
<ListItem
title="Build Time"
description="24-04-21 21:00 PM"
theme={theme}
/>
<ListItem
title="What's new"
onPress={() =>
Linking.openURL(
"https://github.com/rajarsheechatterjee/lnreader/commits/main"
)
}
theme={theme}
/>
<Divider theme={theme} />
<ListItem
title="Discord"
description="https://discord.gg/QdcWN4MD63"
onPress={() =>
Linking.openURL("https://discord.gg/QdcWN4MD63")
}
theme={theme}
/>
<ListItem
title="Github"
description="https://github.com/rajarsheechatterjee/lnreader"
onPress={() =>
Linking.openURL(
"https://github.com/rajarsheechatterjee/lnreader"
)
}
theme={theme}
/>
<ListItem
title="Extensions"
description="https://github.com/rajarsheechatterjee/lnreader-extensions"
onPress={() =>
Linking.openURL(
"https://github.com/rajarsheechatterjee/lnreader-extensions"
)
}
theme={theme}
/>
</ListSection>
</View>
</>
);
};
+48 -45
View File
@@ -1,57 +1,60 @@
import React from "react";
import { StyleSheet } from "react-native";
import { List } from "react-native-paper";
import { Appbar } from "../../components/common/Appbar";
import { StyleSheet, View, Image } from "react-native";
import { useSelector } from "react-redux";
import { Appbar } from "../../components/Appbar";
import { ListItem, ListSection } from "../../components/List";
const MoreScreen = ({ navigation }) => {
const theme = useSelector((state) => state.themeReducer.theme);
return (
<>
<Appbar title="More" />
<List.Section
style={{
flex: 1,
backgroundColor: theme.colorPrimaryDark,
marginTop: 0,
marginBottom: 0,
}}
>
<List.Item
titleStyle={{ color: theme.textColorPrimary }}
title="Settings"
left={() => (
<List.Icon
color={theme.colorAccentDark}
icon="cog-outline"
<Appbar title="More" style={{ elevation: 0 }} />
<View style={{ flex: 1, backgroundColor: theme.colorPrimaryDark }}>
<View style={{ overflow: "hidden", paddingBottom: 4 }}>
<View
style={{
paddingTop: 20,
paddingBottom: 30,
alignItems: "center",
backgroundColor: theme.colorPrimary,
elevation: 4,
}}
>
<Image
source={require("../../../assets/logo.png")}
style={{
height: 60,
width: 60,
tintColor: theme.textColorPrimary,
}}
/>
)}
onPress={() =>
navigation.navigate("SettingsStack", {
screen: "Settings",
})
}
/>
<List.Item
titleStyle={{ color: theme.textColorPrimary }}
title="About"
left={() => (
<List.Icon
color={theme.colorAccentDark}
icon="information-outline"
/>
)}
onPress={() =>
navigation.navigate("SettingsStack", {
screen: "About",
})
}
/>
</List.Section>
</View>
</View>
<ListSection>
<ListItem
title="Settings"
icon="cog-outline"
onPress={() =>
navigation.navigate("SettingsStack", {
screen: "Settings",
})
}
theme={theme}
/>
<ListItem
title="About"
icon="information-outline"
onPress={() =>
navigation.navigate("SettingsStack", {
screen: "About",
})
}
theme={theme}
/>
</ListSection>
</View>
</>
);
};
+75 -238
View File
@@ -1,26 +1,25 @@
import React, { useState } from "react";
import { View, Text, Dimensions } from "react-native";
import { setStatusBarStyle } from "expo-status-bar";
import { List, Modal, Portal } from "react-native-paper";
import Slider from "@react-native-community/slider";
import InputSpinner from "react-native-input-spinner";
import { View } from "react-native";
import { connect } from "react-redux";
import { switchTheme } from "../../redux/theme/theme.actions";
import {
setDisplayMode,
setItemsPerRow,
} from "../../redux/settings/settings.actions";
import { Appbar } from "../../components/common/Appbar";
import {
DisplayCheckbox,
ThemeCheckbox,
} from "../../components/settings/Checkbox";
import { deleteAllHistory } from "../../database/queries/HistoryQueries";
import { deleteNovelCache } from "../../database/queries/NovelQueries";
// import { deleteDb } from "../../database/DBHelper";
import { Appbar } from "../../components/Appbar";
import {
Divider,
ListItem,
ListSection,
ListSubHeader,
} from "../../components/List";
import DisplayModeModal from "./components/DisplayModeModal";
import GridSizeModal from "./components/GridSizeModal";
import ThemeModal from "./components/ThemeModal";
const SettingsScreen = ({
navigation,
@@ -32,266 +31,104 @@ const SettingsScreen = ({
setDisplayMode,
setItemsPerRow,
}) => {
const display = {
0: "Compact Grid",
1: "Comfortable Grid",
2: "List",
const displayModeLabel = (displayMode) => {
const label = {
0: "Compact Grid",
1: "Comfortable Grid",
2: "List",
};
return label[displayMode];
};
const themes = [
{ themeCode: 0, label: "AMOLED Dark Theme", statusBar: "light" },
{ themeCode: 1, label: "Light Theme", statusBar: "dark" },
{ themeCode: 2, label: "Dark Theme", statusBar: "light" },
{ themeCode: 3, label: "Midnight Dusk Theme", statusBar: "light" },
];
const desciptionStyles = {
color: theme.textColorSecondary,
};
const titleStyles = { color: theme.textColorPrimary };
/**
* Display Mode Modal
*/
// Display Mode Modal
const [displayModalVisible, setDisplayModalVisible] = useState(false);
const showDisplayModal = () => setDisplayModalVisible(true);
const hideDisplayModal = () => setDisplayModalVisible(false);
/**
* Change Theme Modal
*/
// Theme Modal
const [themeModalVisible, setthemeModalVisible] = useState(false);
const showthemeModal = () => setthemeModalVisible(true);
const hidethemeModal = () => setthemeModalVisible(false);
const [itemsModalVisible, setitemsModalVisible] = useState(false);
const showitemsModal = () => setitemsModalVisible(true);
const hideitemsModal = () => setitemsModalVisible(false);
// Grid Size Modal
const [gridSizeModalVisible, setGridSizeModalVisible] = useState(false);
const showGridSizeModal = () => setGridSizeModalVisible(true);
const hideGridSizeModal = () => setGridSizeModalVisible(false);
return (
<>
<Appbar title="Settings" onBackAction={() => navigation.goBack()} />
<View style={{ flex: 1, backgroundColor: theme.colorPrimaryDark }}>
<List.Section
style={{
flex: 1,
backgroundColor: theme.colorPrimaryDark,
}}
>
<List.Subheader
style={{
color: theme.colorAccentDark,
paddingBottom: 5,
}}
>
Data
</List.Subheader>
<List.Item
titleStyle={titleStyles}
<View
style={{
flex: 1,
backgroundColor: theme.colorPrimaryDark,
paddingVertical: 8,
}}
>
<ListSection>
<ListSubHeader theme={theme}>Data</ListSubHeader>
<ListItem
title="Clear database"
descriptionStyle={desciptionStyles}
description="Delete history for novels not in your library"
onPress={() => deleteNovelCache()}
rippleColor={theme.rippleColor}
theme={theme}
/>
<List.Item
titleStyle={titleStyles}
<ListItem
title="Clear history"
descriptionStyle={desciptionStyles}
description="Delete reading history for all novels"
onPress={() => deleteAllHistory()}
rippleColor={theme.rippleColor}
theme={theme}
/>
<List.Subheader
style={{
color: theme.colorAccentDark,
paddingBottom: 5,
}}
>
Display
</List.Subheader>
<List.Item
titleStyle={titleStyles}
<Divider theme={theme} />
<ListSubHeader theme={theme}>Display</ListSubHeader>
<ListItem
title="Display Mode"
descriptionStyle={desciptionStyles}
description={display[displayMode]}
description={displayModeLabel(displayMode)}
onPress={showDisplayModal}
rippleColor={theme.rippleColor}
theme={theme}
/>
<Portal>
<Modal
visible={displayModalVisible}
onDismiss={hideDisplayModal}
contentContainerStyle={{
backgroundColor: theme.colorPrimaryDark,
padding: 20,
margin: 20,
borderRadius: 6,
}}
>
<DisplayCheckbox
value={1}
displayMode={displayMode}
onPress={() => setDisplayMode(1)}
/>
<DisplayCheckbox
value={0}
displayMode={displayMode}
onPress={() => setDisplayMode(0)}
/>
<DisplayCheckbox
value={2}
displayMode={displayMode}
onPress={() => setDisplayMode(2)}
/>
</Modal>
</Portal>
<List.Item
titleStyle={titleStyles}
<ListItem
title="Items per row in library"
descriptionStyle={desciptionStyles}
description={itemsPerRow}
onPress={showitemsModal}
rippleColor={theme.rippleColor}
description={`${itemsPerRow} items per row`}
onPress={showGridSizeModal}
theme={theme}
/>
<Portal>
<Modal
visible={itemsModalVisible}
onDismiss={hideitemsModal}
contentContainerStyle={{
backgroundColor: theme.colorPrimaryDark,
padding: 20,
margin: 20,
borderRadius: 6,
}}
>
<Text
style={{
color: theme.textColorPrimary,
fontSize: 18,
marginBottom: 10,
}}
>
Grid size
</Text>
<Text
style={{
color: theme.textColorSecondary,
marginBottom: 4,
}}
>
{itemsPerRow} per row
</Text>
{/* <InputSpinner
style={{
paddingHorizontal: 16,
paddingVertical: 16,
elevation: 0,
}}
max={10}
min={1}
skin="paper"
background={theme.colorPrimaryDark}
colorMax={theme.colorAccentDark}
colorLeft={theme.colorAccentDark}
colorRight={theme.colorAccentDark}
buttonTextColor={theme.textColorPrimary}
colorPress={"white"}
colorMin={theme.colorAccentDark}
value={itemsPerRow}
onChange={(num) => setItemsPerRow(num)}
inputStyle={{
color: theme.textColorPrimary,
}}
/> */}
<Slider
style={{
width: "100%",
height: 40,
// backgroundColor: "red",
}}
value={itemsPerRow}
minimumValue={1}
maximumValue={5}
step={1}
minimumTrackTintColor={theme.colorAccentDark}
maximumTrackTintColor="#000000"
thumbTintColor={theme.colorAccentDark}
onValueChange={(value) => setItemsPerRow(value)}
/>
</Modal>
</Portal>
{/* <List.Subheader
style={{
color: theme.colorAccentDark,
paddingBottom: 5,
}}
>
Devloper options
</List.Subheader>
<List.Item
titleStyle={titleStyles}
title="Delete database"
descriptionStyle={desciptionStyles}
description="Delete entire database"
rippleColor={theme.rippleColor}
onPress={() => deleteDb()}
/> */}
<List.Subheader
style={{
color: theme.colorAccentDark,
paddingBottom: 5,
}}
>
Theme
</List.Subheader>
<List.Item
titleStyle={titleStyles}
<Divider theme={theme} />
<ListSubHeader theme={theme}>Theme</ListSubHeader>
<ListItem
title="Theme"
descriptionStyle={desciptionStyles}
description={themes[themeCode].label}
description={theme.name}
onPress={showthemeModal}
rippleColor={theme.rippleColor}
theme={theme}
/>
<Portal>
<Modal
visible={themeModalVisible}
onDismiss={hidethemeModal}
contentContainerStyle={{
backgroundColor: theme.colorPrimaryDark,
padding: 20,
margin: 20,
borderRadius: 6,
}}
>
{themes.map((item, index) => (
<ThemeCheckbox
key={index}
label={themes[item.themeCode].label}
checked={
themeCode === item.themeCode
? true
: false
}
onPress={() => {
switchTheme(item.themeCode);
setStatusBarStyle(item.statusBar);
}}
/>
))}
</Modal>
</Portal>
</List.Section>
</ListSection>
<DisplayModeModal
displayMode={displayMode}
displayModalVisible={displayModalVisible}
hideDisplayModal={hideDisplayModal}
setDisplayMode={setDisplayMode}
theme={theme}
/>
<GridSizeModal
itemsPerRow={itemsPerRow}
gridSizeModalVisible={gridSizeModalVisible}
hideGridSizeModal={hideGridSizeModal}
setItemsPerRow={setItemsPerRow}
theme={theme}
/>
<ThemeModal
themeModalVisible={themeModalVisible}
hidethemeModal={hidethemeModal}
switchTheme={switchTheme}
theme={theme}
/>
</View>
</>
);
};
const mapStateToProps = (state) => ({
themeCode: state.themeReducer.themeCode,
theme: state.themeReducer.theme,
displayMode: state.settingsReducer.displayMode,
itemsPerRow: state.settingsReducer.itemsPerRow,
@@ -0,0 +1,59 @@
import React from "react";
import { StyleSheet } from "react-native";
import { Portal, Modal, Checkbox } from "react-native-paper";
const DisplayModeModal = ({
displayMode,
displayModalVisible,
setDisplayMode,
hideDisplayModal,
theme,
}) => {
const displayModes = [
{ displayMode: 0, label: "Compact Grid" },
{ displayMode: 1, label: "Comfortable Grid" },
{ displayMode: 2, label: "List" },
];
const renderCheckboxes = () => {
return displayModes.map((mode) => (
<Checkbox.Item
key={mode.displayMode}
label={mode.label}
labelStyle={{ color: theme.textColorPrimary }}
status={
displayMode === mode.displayMode ? "checked" : "unchecked"
}
mode="ios"
uncheckedColor={theme.textColorSecondary}
color={theme.colorAccentDark}
onPress={() => setDisplayMode(mode.displayMode)}
/>
));
};
return (
<Portal>
<Modal
visible={displayModalVisible}
onDismiss={hideDisplayModal}
contentContainerStyle={[
styles.containerStyle,
{ backgroundColor: theme.colorPrimaryDark },
]}
>
{renderCheckboxes()}
</Modal>
</Portal>
);
};
export default DisplayModeModal;
const styles = StyleSheet.create({
containerStyle: {
padding: 20,
margin: 20,
borderRadius: 6,
},
});
@@ -0,0 +1,74 @@
import React from "react";
import { Text, StyleSheet } from "react-native";
import { Portal, Modal } from "react-native-paper";
import Slider from "@react-native-community/slider";
const GridSizeModal = ({
itemsPerRow,
gridSizeModalVisible,
hideGridSizeModal,
setItemsPerRow,
theme,
}) => {
return (
<Portal>
<Modal
visible={gridSizeModalVisible}
onDismiss={hideGridSizeModal}
contentContainerStyle={[
styles.containerStyle,
{ backgroundColor: theme.colorPrimaryDark },
]}
>
<Text
style={[
styles.modalHeader,
{ color: theme.textColorPrimary },
]}
>
Grid size
</Text>
<Text
style={[
styles.modalDescription,
{ color: theme.textColorSecondary },
]}
>
{`${itemsPerRow} per row`}
</Text>
<Slider
style={styles.slider}
value={itemsPerRow}
minimumValue={1}
maximumValue={5}
step={1}
minimumTrackTintColor={theme.colorAccentDark}
maximumTrackTintColor="#000000"
thumbTintColor={theme.colorAccentDark}
onValueChange={(value) => setItemsPerRow(value)}
/>
</Modal>
</Portal>
);
};
export default GridSizeModal;
const styles = StyleSheet.create({
containerStyle: {
padding: 20,
margin: 20,
borderRadius: 6,
},
modalHeader: {
fontSize: 18,
marginBottom: 10,
},
modalDescription: {
marginBottom: 4,
},
slider: {
width: "100%",
height: 40,
},
});
+60
View File
@@ -0,0 +1,60 @@
import React from "react";
import { StyleSheet } from "react-native";
import { Portal, Modal, Checkbox } from "react-native-paper";
import { setStatusBarStyle } from "expo-status-bar";
const ThemeModal = ({
themeModalVisible,
hidethemeModal,
switchTheme,
theme,
}) => {
const themes = [
{ id: 0, name: "AMOLED Dark", statusBar: "light" },
{ id: 1, name: "Light", statusBar: "dark" },
{ id: 2, name: "Dark", statusBar: "light" },
{ id: 3, name: "Midnight Dusk", statusBar: "light" },
];
const renderThemeCheckboxes = () =>
themes.map((item) => (
<Checkbox.Item
key={item.id}
label={item.name}
labelStyle={{ color: theme.textColorPrimary }}
status={theme.id === item.id ? "checked" : "unchecked"}
mode="ios"
color={theme.colorAccentDark}
onPress={() => {
switchTheme(item.id);
setStatusBarStyle(item.statusBar);
}}
/>
));
return (
<Portal>
<Modal
visible={themeModalVisible}
onDismiss={hidethemeModal}
contentContainerStyle={[
styles.containerStyle,
{ backgroundColor: theme.colorPrimaryDark },
]}
>
{renderThemeCheckboxes()}
</Modal>
</Portal>
);
};
export default ThemeModal;
const styles = StyleSheet.create({
containerStyle: {
padding: 20,
margin: 20,
borderRadius: 6,
},
});
+1 -1
View File
@@ -48,7 +48,7 @@ const ChapterCard = ({
style={{ margin: 2 }}
/>
}
contentStyle={{ backgroundColor: "#242529" }}
contentStyle={{ backgroundColor: theme.menuColor }}
>
<Menu.Item
onPress={() =>
+5 -9
View File
@@ -155,9 +155,7 @@ const NovelInfoHeader = ({
<IconButton
onPress={() =>
WebBrowser.openBrowserAsync(
novel.sourceUrl && novel.sourceUrl
)
WebBrowser.openBrowserAsync(novel.sourceUrl)
}
icon="earth"
color={theme.colorAccentDark}
@@ -165,9 +163,7 @@ const NovelInfoHeader = ({
/>
<IconButton
onPress={() =>
Share.share({
message: novel.sourceUrl,
})
Share.share({ message: novel.sourceUrl })
}
icon="share-variant"
color={theme.colorAccentDark}
@@ -185,17 +181,17 @@ const NovelInfoHeader = ({
onPress={openMenu}
/>
}
contentStyle={{ backgroundColor: "#242529" }}
contentStyle={{ backgroundColor: theme.menuColor }}
>
<Menu.Item
title="Download all"
style={{ backgroundColor: "#242529" }}
style={{ backgroundColor: theme.menuColor }}
titleStyle={{ color: theme.textColorPrimary }}
onPress={downloadAllChapters}
/>
<Menu.Item
title="Delete downloads"
style={{ backgroundColor: "#242529" }}
style={{ backgroundColor: theme.menuColor }}
titleStyle={{ color: theme.textColorPrimary }}
onPress={deleteAllChapters}
/>
+1 -1
View File
@@ -3,7 +3,7 @@ import { useFocusEffect } from "@react-navigation/native";
import { StyleSheet, View, FlatList, ActivityIndicator } from "react-native";
import { connect } from "react-redux";
import EmptyView from "../../components/common/EmptyView";
import EmptyView from "../../components/EmptyView";
import { getUpdatesAction } from "../../redux/updates/updates.actions";
import { Appbar } from "./components/Appbar";
import UpdateCard from "./components/UpdateCard";
-146
View File
@@ -1,146 +0,0 @@
import React, { useEffect, useState, useRef } from "react";
import { StyleSheet, View, FlatList, ActivityIndicator } from "react-native";
import { Provider, Portal } from "react-native-paper";
import NovelCover from "../../../components/common/NovelCover";
import { SearchAppbar } from "../../../components/common/Appbar";
import { BottomSheet } from "./filters/BottomSheet";
import { useSelector } from "react-redux";
const BoxNovel = ({ navigation }) => {
const theme = useSelector((state) => state.themeReducer.theme);
const itemsPerRow = useSelector(
(state) => state.settingsReducer.itemsPerRow
);
const library = useSelector((state) => state.libraryReducer.novels);
const [loading, setLoading] = useState(true);
const [novels, setNovels] = useState([]);
const [sort, setSort] = useState("rating");
const [searchText, setSearchText] = useState("");
let bottomSheetRef = useRef(null);
const getNovels = () => {
fetch(
`https://lnreader-extensions.herokuapp.com/api/1/novels/1/?o=${sort}`
)
.then((response) => response.json())
.then((json) => {
setNovels(json);
setLoading(false);
});
};
const getSearchResults = (searchText) => {
setLoading(true);
fetch(
`https://lnreader-extensions.herokuapp.com/api/1/search/?s=${searchText}&?o=${sort}`
)
.then((response) => response.json())
.then((json) => {
setNovels(json);
setLoading(false);
});
};
const checkIFInLibrary = (id) => {
return library.some((obj) => obj.novelUrl === id);
};
useEffect(() => {
getNovels();
}, [sort]);
return (
<Provider>
<View
style={[
styles.container,
{ backgroundColor: theme.colorPrimaryDark },
]}
>
<SearchAppbar
screen="Extension"
placeholder="Search BoxNovel"
searchText={searchText}
setSearchText={setSearchText}
getSearchResults={getSearchResults}
getNovels={getNovels}
setLoading={setLoading}
onFilter={() =>
bottomSheetRef.current.show({ velocity: -1.5 })
}
/>
{loading ? (
<View style={{ flex: 1, justifyContent: "center" }}>
<ActivityIndicator
size={60}
color={theme.colorAccentDark}
/>
</View>
) : (
<FlatList
contentContainerStyle={styles.list}
numColumns={itemsPerRow}
key={itemsPerRow}
data={novels}
showsVerticalScrollIndicator={false}
keyExtractor={(item) => item.novelUrl}
renderItem={({ item }) => (
<NovelCover
item={item}
onPress={() => {
navigation.navigate("NovelItem", {
novelName: item.novelName,
novelCover: item.novelCover,
novelUrl: item.novelUrl,
sourceId: item.extensionId,
});
}}
libraryStatus={
checkIFInLibrary(item.novelUrl)
? true
: false
}
/>
)}
ListEmptyComponent={
novels.length === 0 && (
<EmptyView
icon="(; ̄Д ̄)"
description="No results found"
/>
)
}
/>
)}
</View>
<Portal>
<BottomSheet
bottomSheetRef={bottomSheetRef}
setSort={setSort}
sort={sort}
setLoading={setLoading}
/>
</Portal>
</Provider>
);
};
export default BoxNovel;
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 4,
},
contentContainer: {
flex: 1,
},
});
@@ -1,94 +0,0 @@
import React from "react";
import { StyleSheet, View } from "react-native";
import { List } from "react-native-paper";
import Bottomsheet from "rn-sliding-up-panel";
import { useSelector } from "react-redux";
export const BottomSheet = ({ bottomSheetRef, setSort, sort, setLoading }) => {
const theme = useSelector((state) => state.themeReducer.theme);
const sorting = [
{ label: "Latest", sortFlag: "latest" },
{ label: "A-Z", sortFlag: "aplhabet" },
{ label: "Rating", sortFlag: "rating" },
{ label: "Trending", sortFlag: "trending" },
{ label: "Most Views", sortFlag: "views" },
{ label: "New", sortFlag: "new-manga" },
];
return (
<Bottomsheet
ref={bottomSheetRef}
draggableRange={{ top: 370, bottom: 0 }}
snappingPoints={[0, 370]}
>
<View
style={[
styles.contentContainer,
{ backgroundColor: theme.colorPrimary },
]}
>
<View
style={[
styles.bottomSheetHandle,
{ backgroundColor: theme.textColorPrimary },
]}
/>
<List.Section
title="Sort"
titleStyle={{
color: theme.colorAccentDark,
fontWeight: "bold",
}}
style={{ color: theme.colorAccentDark }}
expanded
>
{sorting.map((item, index) => (
<List.Item
key={index}
right={() =>
sort === item.sortFlag && (
<List.Icon
icon="arrow-up"
color={theme.colorAccentDark}
style={styles.sortArrow}
/>
)
}
title={item.label}
titleStyle={{
fontSize: 15,
color: theme.textColorPrimary,
}}
onPress={() => {
setLoading(true);
setSort(item.sortFlag);
}}
/>
))}
</List.Section>
</View>
</Bottomsheet>
);
};
const styles = StyleSheet.create({
contentContainer: {
flex: 1,
borderTopRightRadius: 8,
borderTopLeftRadius: 8,
},
bottomSheetHandle: {
opacity: 0.5,
height: 4,
width: 32,
borderRadius: 50,
top: 8,
alignSelf: "center",
},
sortArrow: {
marginVertical: 0,
paddingVertical: 0,
},
});
@@ -1,129 +0,0 @@
import React, { useEffect, useState } from "react";
import { StyleSheet, View, FlatList, ActivityIndicator } from "react-native";
import { Provider } from "react-native-paper";
import NovelCover from "../../../components/common/NovelCover";
import { SearchAppbar } from "../../../components/common/Appbar";
import { useSelector } from "react-redux";
import EmptyView from "../../../components/common/EmptyView";
const FastNovel = ({ navigation }) => {
const theme = useSelector((state) => state.themeReducer.theme);
const library = useSelector((state) => state.libraryReducer.novels);
const itemsPerRow = useSelector(
(state) => state.settingsReducer.itemsPerRow
);
const [loading, setLoading] = useState(true);
const [novels, setNovels] = useState();
const [searchText, setSearchText] = useState("");
const getNovels = () => {
fetch(`https://lnreader-extensions.herokuapp.com/api/3/novels/`)
.then((response) => response.json())
.then((json) => {
setNovels(json);
setLoading(false);
});
};
const getSearchResults = (searchText) => {
setLoading(true);
fetch(
`https://lnreader-extensions.herokuapp.com/api/3/search/?s=${searchText}`
)
.then((response) => response.json())
.then((json) => {
setNovels(json);
setLoading(false);
});
};
const checkIFInLibrary = (id) => {
return library.some((obj) => obj.novelUrl === id);
};
useEffect(() => {
getNovels();
}, []);
return (
<Provider>
<View
style={[
styles.container,
{ backgroundColor: theme.colorPrimaryDark },
]}
>
<SearchAppbar
screen="Extension"
placeholder="Search FastNovel"
searchText={searchText}
setSearchText={setSearchText}
getSearchResults={getSearchResults}
getNovels={getNovels}
setLoading={setLoading}
/>
{loading ? (
<View style={{ flex: 1, justifyContent: "center" }}>
<ActivityIndicator
size={60}
color={theme.colorAccentDark}
/>
</View>
) : (
<FlatList
contentContainerStyle={{ flexGrow: 1 }}
numColumns={itemsPerRow}
key={itemsPerRow}
data={novels}
showsVerticalScrollIndicator={false}
keyExtractor={(item) => item.novelUrl}
renderItem={({ item }) => (
<NovelCover
item={item}
onPress={() =>
navigation.navigate("NovelItem", {
novelName: item.novelName,
novelCover: item.novelCover,
novelUrl: item.novelUrl,
sourceId: item.extensionId,
})
}
libraryStatus={
checkIFInLibrary(item.novelUrl)
? true
: false
}
/>
)}
ListEmptyComponent={
novels.length === 0 && (
<EmptyView
icon="(; ̄Д ̄)"
description="No results found"
/>
)
}
/>
)}
</View>
</Provider>
);
};
export default FastNovel;
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 4,
},
contentContainer: {
flex: 1,
},
});
@@ -1,129 +0,0 @@
import React, { useEffect, useState } from "react";
import { StyleSheet, View, FlatList, ActivityIndicator } from "react-native";
import { Provider } from "react-native-paper";
import NovelCover from "../../../components/common/NovelCover";
import { SearchAppbar } from "../../../components/common/Appbar";
import { useSelector } from "react-redux";
import EmptyView from "../../../components/common/EmptyView";
const FastNovel = ({ navigation }) => {
const theme = useSelector((state) => state.themeReducer.theme);
const library = useSelector((state) => state.libraryReducer.novels);
const itemsPerRow = useSelector(
(state) => state.settingsReducer.itemsPerRow
);
const [loading, setLoading] = useState(true);
const [novels, setNovels] = useState();
const [searchText, setSearchText] = useState("");
const getNovels = () => {
fetch(`https://lnreader-extensions.herokuapp.com/api/4/novels/`)
.then((response) => response.json())
.then((json) => {
setNovels(json);
setLoading(false);
});
};
const getSearchResults = (searchText) => {
setLoading(true);
fetch(
`https://lnreader-extensions.herokuapp.com/api/4/search/?s=${searchText}`
)
.then((response) => response.json())
.then((json) => {
setNovels(json);
setLoading(false);
});
};
const checkIFInLibrary = (id) => {
return library.some((obj) => obj.novelUrl === id);
};
useEffect(() => {
getNovels();
}, []);
return (
<Provider>
<View
style={[
styles.container,
{ backgroundColor: theme.colorPrimaryDark },
]}
>
<SearchAppbar
screen="Extension"
placeholder="Search ReadNovelFull"
searchText={searchText}
setSearchText={setSearchText}
getSearchResults={getSearchResults}
getNovels={getNovels}
setLoading={setLoading}
/>
{loading ? (
<View style={{ flex: 1, justifyContent: "center" }}>
<ActivityIndicator
size={60}
color={theme.colorAccentDark}
/>
</View>
) : (
<FlatList
contentContainerStyle={{ flexGrow: 1 }}
numColumns={itemsPerRow}
key={itemsPerRow}
data={novels}
showsVerticalScrollIndicator={false}
keyExtractor={(item) => item.novelUrl}
renderItem={({ item }) => (
<NovelCover
item={item}
onPress={() =>
navigation.navigate("NovelItem", {
novelName: item.novelName,
novelCover: item.novelCover,
novelUrl: item.novelUrl,
sourceId: item.extensionId,
})
}
libraryStatus={
checkIFInLibrary(item.novelUrl)
? true
: false
}
/>
)}
ListEmptyComponent={
novels.length === 0 && (
<EmptyView
icon="(; ̄Д ̄)"
description="No results found"
/>
)
}
/>
)}
</View>
</Provider>
);
};
export default FastNovel;
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 4,
},
contentContainer: {
flex: 1,
},
});
+20
View File
@@ -15,6 +15,8 @@ export const theme = {
* Light Theme
*/
export const lightTheme = {
id: 1,
name: "Light",
colorPrimary: "#FFFFFF",
colorPrimaryDark: "#FAFAFA",
colorAccentDark: "#2979FF",
@@ -23,12 +25,17 @@ export const lightTheme = {
textColorHintDark: "rgba(0,0,0,0.38)",
rippleColor: "rgba(0,0,0,0.12)",
searchBarColor: "#FFFFFF",
menuColor: "#FFFFFF",
dividerColor: "rgba(0,0,0,0.1)",
statusBar: "dark",
};
/**
* Dark Theme
*/
export const darkTheme = {
id: 2,
name: "Dark",
colorPrimary: "#242529",
colorPrimaryDark: "#202125",
colorAccentDark: "#3399FF",
@@ -37,12 +44,17 @@ export const darkTheme = {
textColorHintDark: "rgba(255,255,255,0.5)",
rippleColor: "rgba(255,255,255,0.2)",
searchBarColor: "#303135",
menuColor: "#242529",
dividerColor: "rgba(255,255,255,0.1)",
statusBar: "light",
};
/**
* Amoled Dark Theme
*/
export const amoledDarkTheme = {
id: 0,
name: "AMOLED Dark",
colorPrimary: "#000000",
colorPrimaryDark: "#000000",
colorAccentDark: "#3399FF",
@@ -51,12 +63,17 @@ export const amoledDarkTheme = {
textColorHintDark: "rgba(255,255,255,0.5)",
rippleColor: "rgba(255,255,255,0.2)",
searchBarColor: "#1F1F1F",
menuColor: "#242529",
dividerColor: "rgba(255,255,255,0.15)",
statusBar: "light",
};
/**
* Midnight Dusk Theme
*/
export const midnightDuskTheme = {
id: 3,
name: "Midnight Dusk",
colorPrimary: "#201F27",
colorPrimaryDark: "#16151D",
colorAccentDark: "#F02475",
@@ -65,4 +82,7 @@ export const midnightDuskTheme = {
textColorHintDark: "rgba(255,255,255,0.5)",
rippleColor: "rgba(255,255,255,0.2)",
searchBarColor: "#201F27",
menuColor: "#201F27",
dividerColor: "rgba(255,255,255,0.1)",
statusBar: "light",
};
+11
View File
@@ -0,0 +1,11 @@
const fonts = [
{ fontFamily: "", name: "Original" },
{ fontFamily: "arbutus-slab", name: "Arbutus Slab" },
{ fontFamily: "domine", name: "Domine" },
{ fontFamily: "lato", name: "Lato" },
{ fontFamily: "noto-sans", name: "Noto Sans" },
{ fontFamily: "open-sans", name: "Open Sans" },
{ fontFamily: "pt-serif", name: "PT Serif" },
];
export { fonts };