Add multi sources

This commit is contained in:
Rajarshee Chatterjee
2020-12-27 16:07:28 +05:30
parent 3dd7278042
commit c35df16bdb
11 changed files with 331 additions and 189 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

+40 -40
View File
@@ -1,42 +1,42 @@
{
"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-community/masked-view": "0.1.10",
"@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",
"cheerio-without-node-native": "^0.20.2",
"expo": "~40.0.0",
"expo-app-loading": "^1.0.1",
"expo-font": "^8.4.0",
"expo-linear-gradient": "^8.4.0",
"expo-status-bar": "~1.0.3",
"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-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-sqlite-storage": "^5.0.0",
"react-native-vector-icons": "^7.1.0",
"react-native-web": "~0.13.12",
"rn-sliding-up-panel": "^2.4.4",
"expo-sqlite": "~8.5.0"
},
"devDependencies": {
"@babel/core": "~7.9.0"
},
"private": true,
"proxy": "http://192.168.1.38:5000"
"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-community/masked-view": "0.1.10",
"@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",
"cheerio-without-node-native": "^0.20.2",
"expo": "~40.0.0",
"expo-app-loading": "^1.0.1",
"expo-font": "^8.4.0",
"expo-linear-gradient": "^8.4.0",
"expo-status-bar": "~1.0.3",
"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-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-sqlite-storage": "^5.0.0",
"react-native-vector-icons": "^7.1.0",
"react-native-web": "~0.13.12",
"rn-sliding-up-panel": "^2.4.4",
"expo-sqlite": "~8.5.0"
},
"devDependencies": {
"@babel/core": "~7.9.0"
},
"private": true,
"proxy": "http://192.168.1.42:5000"
}
+30 -7
View File
@@ -9,10 +9,11 @@ import Library from "../screens/Library";
import Browse from "../screens/Browse";
import Latest from "../screens/Latest";
import More from "../screens/More";
import Search from "../screens/Search";
import BoxNovelSearch from "../screens/Search";
import NovelItem from "../screens/NovelItem";
import ChapterItem from "../screens/ChapterItem";
import About from "../screens/About";
import BoxNovel from "../screens/Sources/BoxNovel";
import { theme } from "../theming/theme";
const Stack = createStackNavigator();
@@ -61,11 +62,16 @@ const SearchStack = () => {
const BrowseStack = () => {
return (
<Stack.Navigator>
<Stack.Navigator
screenOptions={{
headerTintColor: theme.textColorPrimaryDark,
headerStyle: { backgroundColor: theme.colorDarkPrimary },
}}
>
<Stack.Screen
name="Browse"
component={Browse}
options={{ headerShown: false }}
// options={{ headerShown: false }}
/>
</Stack.Navigator>
);
@@ -83,6 +89,22 @@ const MoreStack = () => {
);
};
const BoxNovelStack = () => {
return (
<Stack.Navigator
screenOptions={{
// headerTintColor: theme.textColorPrimaryDark,
// headerStyle: { backgroundColor: theme.colorDarkPrimary },
headerShown: false,
}}
>
<Stack.Screen name="BoxNovel" component={BoxNovel} />
<Stack.Screen name="BoxNovelSearch" component={BoxNovelSearch} />
{/* <Stack.Screen name="WuxiaWorld" component={WuxiaWorld} /> */}
</Stack.Navigator>
);
};
const Router = () => {
return (
<Tab.Navigator
@@ -104,7 +126,7 @@ const Router = () => {
}}
/>
<Tab.Screen
{/* <Tab.Screen
name="Latest"
component={LatestStack}
options={{
@@ -116,8 +138,8 @@ const Router = () => {
/>
),
}}
/>
<Tab.Screen
/> */}
{/* <Tab.Screen
name="Search"
component={SearchStack}
options={{
@@ -129,7 +151,7 @@ const Router = () => {
/>
),
}}
/>
/> */}
<Tab.Screen
name="Browse"
component={BrowseStack}
@@ -180,6 +202,7 @@ const MainStack = () => {
headerStyle: { backgroundColor: theme.colorDarkPrimary },
}}
/>
<Stack.Screen name="BoxNovelStack" component={BoxNovelStack} />
</Stack.Navigator>
);
};
+57 -133
View File
@@ -2,7 +2,9 @@ import React, { useEffect, useState } from "react";
import {
StyleSheet,
View,
Text,
FlatList,
Image,
ActivityIndicator,
RefreshControl,
} from "react-native";
@@ -13,139 +15,61 @@ import {
Portal,
Button,
} from "react-native-paper";
import NovelCover from "../components/NovelCover";
import { theme } from "../theming/theme";
import { BottomSheet } from "../components/BottomSheet";
const AllNovels = ({ navigation }) => {
const [loading, setLoading] = useState(true);
const [refreshing, setRefreshing] = useState(true);
const [novels, setNovels] = useState();
const [sort, setSort] = useState("rating");
const [pageNo, setPageNo] = useState(2);
const getNovels = () => {
fetch(`http://192.168.1.42:5000/api/novels/1/?o=${sort}`)
.then((response) => response.json())
.then((json) => setNovels(json))
.catch((error) => console.error(error))
.finally(() => {
setPageNo(2);
setRefreshing(false);
setLoading(false);
});
};
const loadMore = () => {
setRefreshing(true);
fetch(`http://192.168.1.42:5000/api/novels/${pageNo}/?o=${sort}`)
.then((response) => response.json())
.then((json) => setNovels((novels) => novels.concat(json)))
.catch((error) => console.error(error))
.finally(() => {
setRefreshing(false);
setLoading(false);
setPageNo(pageNo + 1);
});
};
useEffect(() => {
getNovels();
}, [sort]);
const onRefresh = () => {
setRefreshing(true);
setPageNo(2);
getNovels();
};
import { sources } from "../utils/sources";
const Browse = ({ navigation }) => {
return (
<Provider>
<Appbar.Header style={{ backgroundColor: theme.colorDarkPrimary }}>
<Appbar.Content
title="Browse"
titleStyle={{ color: theme.textColorPrimaryDark }}
/>
<Appbar.Action
icon="filter-variant"
onPress={() => _panel.show({ velocity: -1.5 })}
/>
<Appbar.Action icon="refresh" onPress={() => onRefresh()} />
</Appbar.Header>
<View style={styles.container}>
{loading ? (
<View style={{ flex: 1, justifyContent: "center" }}>
<ActivityIndicator
size="large"
color={theme.colorAccentDark}
/>
</View>
) : (
<FlatList
contentContainerStyle={styles.list}
numColumns={3}
data={novels}
showsVerticalScrollIndicator={false}
keyExtractor={(item) => item.novelUrl}
ListFooterComponent={() => (
<View
style={{
width: 120,
alignSelf: "center",
marginVertical: 10,
}}
>
<Button
mode="contained"
color={theme.colorAccentDark}
uppercase={false}
labelStyle={{
color: theme.textColorPrimaryDark,
letterSpacing: 0,
}}
onPress={() => loadMore()}
>
Load More
</Button>
</View>
)}
renderItem={({ item }) => (
<TouchableRipple
borderless
centered
rippleColor="rgba(256,256,256,0.3)"
style={styles.opac}
onPress={() =>
navigation.navigate("NovelItem", item)
}
>
<NovelCover item={item} />
</TouchableRipple>
)}
refreshControl={
<RefreshControl
refreshing={refreshing}
onRefresh={onRefresh}
colors={["white"]}
progressBackgroundColor={theme.colorAccentDark}
/>
<View style={styles.container}>
<FlatList
data={sources}
keyExtractor={(item) => item.sourceId.toString()}
renderItem={({ item }) => (
<TouchableRipple
style={styles.sourceCard}
onPress={() =>
navigation.navigate(item.sourceName + "Stack")
}
/>
rippleColor={theme.rippleColorDark}
>
<>
<Image
source={{
uri: item.sourceCover,
}}
style={{
width: 60,
height: 60,
borderRadius: 6,
}}
resizeMode="contain"
/>
<View style={{ marginLeft: 15 }}>
<Text
style={{
color: theme.textColorPrimaryDark,
fontSize: 16,
}}
>
{item.sourceName}
</Text>
<Text
style={{
color: theme.textColorSecondaryDark,
}}
>
{item.sourceLanguage}
</Text>
</View>
</>
</TouchableRipple>
)}
</View>
<Portal>
<BottomSheet
bottomSheetRef={(c) => (_panel = c)}
setSort={setSort}
sort={sort}
setRefreshing={setRefreshing}
/>
</Portal>
</Provider>
/>
</View>
);
};
export default AllNovels;
export default Browse;
const styles = StyleSheet.create({
container: {
@@ -153,13 +77,13 @@ const styles = StyleSheet.create({
// backgroundColor: "#202125",
backgroundColor: "#000000",
},
opac: {
height: 190,
flex: 1 / 3,
marginHorizontal: 3.6,
marginVertical: 3.2,
},
contentContainer: {
flex: 1,
sourceCard: {
// backgroundColor: "pink",
paddingVertical: 10,
marginVertical: 5,
paddingHorizontal: 20,
borderRadius: 6,
flexDirection: "row",
alignItems: "center",
},
});
+11 -4
View File
@@ -1,5 +1,11 @@
import React, { useState, useEffect } from "react";
import { StyleSheet, View, Text, ActivityIndicator } from "react-native";
import {
StyleSheet,
View,
Text,
ActivityIndicator,
StatusBar,
} from "react-native";
import BottomSheet from "../components/ChapterBottomSheet";
import { Appbar, Provider, Portal } from "react-native-paper";
@@ -14,7 +20,7 @@ const ChapterItem = ({ route, navigation }) => {
const [chapter, setChapter] = useState();
const [size, setSize] = useState(14);
const [size, setSize] = useState(16);
const [readerTheme, setReaderTheme] = useState(1);
@@ -23,7 +29,7 @@ const ChapterItem = ({ route, navigation }) => {
}, []);
const getChapter = () => {
fetch(`http://192.168.1.42:5000/api/${chapterUrl}`)
fetch(`http://192.168.1.42:5000/api/1/${chapterUrl}`)
.then((response) => response.json())
.then((json) => setChapter(json))
.catch((error) => console.error(error))
@@ -34,6 +40,7 @@ const ChapterItem = ({ route, navigation }) => {
return (
<Provider>
<StatusBar backgroundColor="transparent" />
<CollapsibleHeaderScrollView
headerContainerBackgroundColor={"rgba(0,0,0,0)"}
// statusBarHeight={60}
@@ -123,7 +130,7 @@ const ChapterItem = ({ route, navigation }) => {
? { color: theme.textColorSecondaryDark }
: { color: "black" },
size === 16
? { lineHeight: 20 }
? { lineHeight: 25 }
: size === 20
? { lineHeight: 25 }
: size === 12 && { lineHeight: 20 },
+1 -1
View File
@@ -16,7 +16,7 @@ const LatestScreen = ({ navigation }) => {
const [novels, setNovels] = useState();
const getNovels = () => {
fetch("http://192.168.1.42:5000/api/latest")
fetch("http://192.168.1.42:5000/api/1/latest")
.then((response) => response.json())
.then((json) => setNovels(json))
.catch((error) => console.error(error))
+3 -3
View File
@@ -35,10 +35,10 @@ const NovelItem = ({ route, navigation }) => {
const [more, setMore] = useState(false);
const [libraryStatus, setlibraryStatus] = useState();
const [sort, setSort] = useState("DESC");
// const [sort, setSort] = useState("DESC");
const getNovel = () => {
fetch(`http://192.168.1.42:5000/api/novel/${item.novelUrl}`)
fetch(`http://192.168.1.42:5000/api/1/novel/${item.novelUrl}`)
.then((response) => response.json())
.then((json) => {
setNovel(json);
@@ -212,7 +212,7 @@ const NovelItem = ({ route, navigation }) => {
data={chapters}
extraData={chapters}
showsVerticalScrollIndicator={false}
keyExtractor={(item) => item.chapterId}
keyExtractor={(item) => item.chapterUrl}
removeClippedSubviews={true}
maxToRenderPerBatch={10}
initialNumToRender={10}
+3 -1
View File
@@ -18,7 +18,9 @@ const SearchScreen = ({ navigation }) => {
const getNovels = (searchText) => {
setLoading(true);
fetch(`http://192.168.1.42:5000/api/search/?s=${searchText}&?o=rating`)
fetch(
`http://192.168.1.42:5000/api/1/search/?s=${searchText}&?o=rating`
)
.then((response) => response.json())
.then((json) => setNovels(json))
.catch((error) => console.error(error))
+171
View File
@@ -0,0 +1,171 @@
import React, { useEffect, useState } from "react";
import {
StyleSheet,
View,
FlatList,
ActivityIndicator,
RefreshControl,
} from "react-native";
import {
TouchableRipple,
Appbar,
Provider,
Portal,
Button,
} from "react-native-paper";
import NovelCover from "../../components/NovelCover";
import { theme } from "../../theming/theme";
import { BottomSheet } from "../../components/BottomSheet";
const AllNovels = ({ navigation }) => {
const [loading, setLoading] = useState(true);
const [refreshing, setRefreshing] = useState(true);
const [novels, setNovels] = useState();
const [sort, setSort] = useState("rating");
const [pageNo, setPageNo] = useState(2);
const getNovels = () => {
fetch(`http://192.168.1.42:5000/api/1/novels/1/?o=${sort}`)
.then((response) => response.json())
.then((json) => setNovels(json))
.catch((error) => console.error(error))
.finally(() => {
setPageNo(2);
setRefreshing(false);
setLoading(false);
});
};
const loadMore = () => {
setRefreshing(true);
fetch(`http://192.168.1.42:5000/api/1/novels/${pageNo}/?o=${sort}`)
.then((response) => response.json())
.then((json) => setNovels((novels) => novels.concat(json)))
.catch((error) => console.error(error))
.finally(() => {
setRefreshing(false);
setLoading(false);
setPageNo(pageNo + 1);
});
};
useEffect(() => {
getNovels();
}, [sort]);
const onRefresh = () => {
setRefreshing(true);
setPageNo(2);
getNovels();
};
return (
<Provider>
<Appbar.Header style={{ backgroundColor: theme.colorDarkPrimary }}>
<Appbar.BackAction onPress={() => navigation.goBack()} />
<Appbar.Content
title="Box Novel"
titleStyle={{ color: theme.textColorPrimaryDark }}
/>
<Appbar.Action
icon="magnify"
onPress={() => navigation.navigate("BoxNovelSearch")}
/>
<Appbar.Action
icon="filter-variant"
onPress={() => _panel.show({ velocity: -1.5 })}
/>
<Appbar.Action icon="refresh" onPress={() => onRefresh()} />
</Appbar.Header>
<View style={styles.container}>
{loading ? (
<View style={{ flex: 1, justifyContent: "center" }}>
<ActivityIndicator
size="large"
color={theme.colorAccentDark}
/>
</View>
) : (
<FlatList
contentContainerStyle={styles.list}
numColumns={3}
data={novels}
showsVerticalScrollIndicator={false}
keyExtractor={(item) => item.novelUrl}
ListFooterComponent={() => (
<View
style={{
width: 120,
alignSelf: "center",
marginVertical: 10,
}}
>
<Button
mode="contained"
color={theme.colorAccentDark}
uppercase={false}
labelStyle={{
color: theme.textColorPrimaryDark,
letterSpacing: 0,
}}
onPress={() => loadMore()}
>
Load More
</Button>
</View>
)}
renderItem={({ item }) => (
<TouchableRipple
borderless
centered
rippleColor="rgba(256,256,256,0.3)"
style={styles.opac}
onPress={() =>
navigation.navigate("NovelItem", item)
}
>
<NovelCover item={item} />
</TouchableRipple>
)}
refreshControl={
<RefreshControl
refreshing={refreshing}
onRefresh={onRefresh}
colors={["white"]}
progressBackgroundColor={theme.colorAccentDark}
/>
}
/>
)}
</View>
<Portal>
<BottomSheet
bottomSheetRef={(c) => (_panel = c)}
setSort={setSort}
sort={sort}
setRefreshing={setRefreshing}
/>
</Portal>
</Provider>
);
};
export default AllNovels;
const styles = StyleSheet.create({
container: {
flex: 1,
// backgroundColor: "#202125",
backgroundColor: "#000000",
},
opac: {
height: 190,
flex: 1 / 3,
marginHorizontal: 3.6,
marginVertical: 3.2,
},
contentContainer: {
flex: 1,
},
});
+15
View File
@@ -0,0 +1,15 @@
export const sources = [
{
sourceId: 1,
sourceName: "BoxNovel",
sourceCover:
"https://boxnovel.com/wp-content/uploads/2018/04/BoxNovel-1.png",
sourceLanguage: "English",
},
{
sourceId: 2,
sourceName: "WuxiaWorld",
sourceCover: "https://www.wuxiaworld.com/Wu-Black-192.jpg",
sourceLanguage: "English",
},
];