Fix NovelItem Select Query
This commit is contained in:
@@ -13,9 +13,7 @@ import Search from "../screens/Search";
|
||||
import NovelItem from "../screens/NovelItem";
|
||||
import ChapterItem from "../screens/ChapterItem";
|
||||
import About from "../screens/About";
|
||||
import LibraryNovelItem from "../screens/LibraryNovelItem";
|
||||
import { theme } from "../theming/theme";
|
||||
import NovelItemRewrite from "../screens/NovelItemRewrite";
|
||||
|
||||
const Stack = createStackNavigator();
|
||||
|
||||
@@ -173,15 +171,6 @@ const MainStack = () => {
|
||||
<Stack.Screen name="MainStack" component={Router} />
|
||||
<Stack.Screen name="ChapterItem" component={ChapterItem} />
|
||||
<Stack.Screen name="NovelItem" component={NovelItem} />
|
||||
<Stack.Screen
|
||||
name="NovelItemRewrite"
|
||||
component={NovelItemRewrite}
|
||||
/>
|
||||
|
||||
<Stack.Screen
|
||||
name="LibraryNovelItem"
|
||||
component={LibraryNovelItem}
|
||||
/>
|
||||
<Stack.Screen
|
||||
name="About"
|
||||
component={About}
|
||||
|
||||
@@ -89,6 +89,7 @@ const styles = StyleSheet.create({
|
||||
opac: {
|
||||
height: 190,
|
||||
flex: 1 / 3,
|
||||
margin: 3.2,
|
||||
marginHorizontal: 3.6,
|
||||
marginVertical: 3.2,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -118,10 +118,7 @@ const UpdatesScreen = ({ navigation }) => {
|
||||
rippleColor="rgba(256,256,256,0.3)"
|
||||
style={styles.opac}
|
||||
onPress={() =>
|
||||
navigation.navigate(
|
||||
"NovelItemRewrite",
|
||||
item
|
||||
)
|
||||
navigation.navigate("NovelItem", item)
|
||||
}
|
||||
>
|
||||
<NovelCover item={item} />
|
||||
|
||||
@@ -1,510 +0,0 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import {
|
||||
StyleSheet,
|
||||
View,
|
||||
Image,
|
||||
ImageBackground,
|
||||
Text,
|
||||
FlatList,
|
||||
ScrollView,
|
||||
RefreshControl,
|
||||
ToastAndroid,
|
||||
} from "react-native";
|
||||
import {
|
||||
Appbar,
|
||||
TouchableRipple,
|
||||
IconButton,
|
||||
Button,
|
||||
} from "react-native-paper";
|
||||
import { LinearGradient } from "expo-linear-gradient";
|
||||
|
||||
import { theme } from "../theming/theme";
|
||||
|
||||
import * as SQLite from "expo-sqlite";
|
||||
const db = SQLite.openDatabase("lnreader.db");
|
||||
|
||||
const NovelItem = ({ route, navigation }) => {
|
||||
const item = route.params;
|
||||
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [refreshing, setRefreshing] = useState(false);
|
||||
const [libraryStatus, setlibraryStatus] = useState();
|
||||
|
||||
const [novel, setNovel] = useState();
|
||||
const [chapters, setChapters] = useState();
|
||||
const [more, setMore] = useState(false);
|
||||
|
||||
const fetchNovel = () => {
|
||||
db.transaction((tx) => {
|
||||
tx.executeSql(
|
||||
"SELECT * FROM LibraryTable WHERE novelUrl=?",
|
||||
[item.novelUrl],
|
||||
(txObj, { rows: { _array } }) => {
|
||||
setNovel(_array);
|
||||
},
|
||||
(txObj, error) => console.log("Error ", error)
|
||||
);
|
||||
tx.executeSql(
|
||||
"SELECT * FROM ChapterTable WHERE novelUrl=?",
|
||||
[item.novelUrl],
|
||||
(txObj, { rows: { _array } }) => {
|
||||
setChapters(_array);
|
||||
// !_array.length && getChapters();
|
||||
setRefreshing(false);
|
||||
setLoading(false);
|
||||
},
|
||||
(txObj, error) => console.log("Error ", error)
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
// const getChapters = () => {
|
||||
// fetch(`http://192.168.1.39:5000/api/novel/${item.novelUrl}`)
|
||||
// .then((response) => response.json())
|
||||
// .then((json) => {
|
||||
// setChapters(json.novelChapters);
|
||||
// })
|
||||
// .catch((error) => console.error(error));
|
||||
// };
|
||||
|
||||
const checkIfExistsInLibrary = (id) => {
|
||||
db.transaction((tx) => {
|
||||
tx.executeSql(
|
||||
"SELECT * FROM LibraryTable WHERE novelUrl=?",
|
||||
[id],
|
||||
(txObj, res) => {
|
||||
// console.log(res.rows.length);
|
||||
if (res.rows.length === 0) {
|
||||
// console.log("Not In Library");
|
||||
setlibraryStatus(0);
|
||||
} else {
|
||||
// console.log("In Library");
|
||||
setlibraryStatus(1);
|
||||
}
|
||||
},
|
||||
(txObj, error) => console.log("Error ", error)
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
const sortChapters = () => {
|
||||
db.transaction((tx) => {
|
||||
tx.executeSql(
|
||||
"SELECT * FROM ChapterTable WHERE novelUrl=? ORDER BY chapterName ASC",
|
||||
[item.novelUrl],
|
||||
(txObj, { rows: { _array } }) => {
|
||||
setChapters(_array);
|
||||
setLoading(false);
|
||||
},
|
||||
(txObj, error) => console.log("Error ", error)
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
const insertToLibrary = () => {
|
||||
if (libraryStatus === 0) {
|
||||
db.transaction((tx) => {
|
||||
tx.executeSql(
|
||||
"INSERT INTO LibraryTable (novelUrl, novelName, novelCover, novelSummary, alternative, author, genre, type, releaseDate, status) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||||
[
|
||||
item.novelUrl,
|
||||
item.novelName,
|
||||
item.novelCover,
|
||||
item.novelSummary,
|
||||
item.Alternative,
|
||||
item["Author(s)"],
|
||||
item["Genres(s)"],
|
||||
item.Type,
|
||||
item.Release,
|
||||
item.Status,
|
||||
],
|
||||
(txObj, res) => {
|
||||
console.log("Novel Inserted");
|
||||
},
|
||||
(txObj, error) => console.log("Error ", error)
|
||||
);
|
||||
|
||||
chapters.map((chap) =>
|
||||
tx.executeSql(
|
||||
"INSERT INTO ChapterTable (chapterUrl, chapterName, releaseDate, novelUrl) values (?, ?, ?, ?)",
|
||||
[
|
||||
chap.chapterUrl,
|
||||
chap.chapterName,
|
||||
chap.releaseDate,
|
||||
item.novelUrl,
|
||||
],
|
||||
(txObj, res) => {
|
||||
// console.log("Chapters Inserted");
|
||||
},
|
||||
(txObj, error) => console.log("Error ", error)
|
||||
)
|
||||
);
|
||||
setlibraryStatus(1);
|
||||
ToastAndroid.show("Added to library", ToastAndroid.SHORT);
|
||||
});
|
||||
} else {
|
||||
db.transaction((tx) => {
|
||||
tx.executeSql(
|
||||
"DELETE FROM LibraryTable WHERE novelUrl=?",
|
||||
[item.novelUrl],
|
||||
(txObj, res) => {
|
||||
console.log("DELETED NOVEL FROM TABLE");
|
||||
},
|
||||
(txObj, error) => console.log("Error ", error)
|
||||
);
|
||||
tx.executeSql(
|
||||
"DELETE FROM ChapterTable WHERE novelUrl=?",
|
||||
[item.novelUrl],
|
||||
(txObj, res) => {
|
||||
console.log("DELETED Chapters FROM TABLE");
|
||||
},
|
||||
(txObj, error) => console.log("Error ", error)
|
||||
);
|
||||
console.log("Removed Novel");
|
||||
setlibraryStatus(0);
|
||||
ToastAndroid.show("Removed from library", ToastAndroid.SHORT);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchNovel();
|
||||
checkIfExistsInLibrary(item.novelUrl);
|
||||
}, []);
|
||||
|
||||
const onRefresh = async () => {
|
||||
setRefreshing(true);
|
||||
fetchNovel();
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Appbar.Header style={{ backgroundColor: theme.colorDarkPrimary }}>
|
||||
<Appbar.BackAction
|
||||
onPress={() => {
|
||||
navigation.goBack();
|
||||
}}
|
||||
color={"white"}
|
||||
size={26}
|
||||
style={{ marginRight: 0 }}
|
||||
/>
|
||||
<Appbar.Content
|
||||
title={item.novelName}
|
||||
titleStyle={{ color: theme.textColorPrimaryDark }}
|
||||
/>
|
||||
</Appbar.Header>
|
||||
|
||||
<ScrollView
|
||||
style={styles.container}
|
||||
refreshControl={
|
||||
<RefreshControl
|
||||
refreshing={refreshing}
|
||||
onRefresh={onRefresh}
|
||||
colors={["white"]}
|
||||
progressBackgroundColor={theme.colorAccentDark}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<ImageBackground
|
||||
source={{
|
||||
uri: item.novelCover,
|
||||
}}
|
||||
style={styles.background}
|
||||
>
|
||||
<LinearGradient
|
||||
colors={["transparent", "#000000"]}
|
||||
style={styles.linearGradient}
|
||||
>
|
||||
<View style={styles.detailsContainer}>
|
||||
<Image
|
||||
source={{
|
||||
uri: item.novelCover,
|
||||
}}
|
||||
style={styles.logo}
|
||||
/>
|
||||
<View style={styles.nameContainer}>
|
||||
<Text
|
||||
numberOfLines={4}
|
||||
style={[
|
||||
styles.name,
|
||||
{ color: theme.textColorPrimaryDark },
|
||||
]}
|
||||
>
|
||||
{item.novelName}
|
||||
</Text>
|
||||
{!loading && (
|
||||
<>
|
||||
<Text
|
||||
style={{
|
||||
color:
|
||||
theme.textColorSecondaryDark,
|
||||
marginVertical: 3,
|
||||
fontSize: 15,
|
||||
}}
|
||||
numberOfLines={1}
|
||||
>
|
||||
{item.Alternative.replace(
|
||||
",",
|
||||
", "
|
||||
)}
|
||||
</Text>
|
||||
<Text
|
||||
style={{
|
||||
color:
|
||||
theme.textColorSecondaryDark,
|
||||
marginVertical: 3,
|
||||
fontSize: 15,
|
||||
}}
|
||||
>
|
||||
{item["Author(s)"].replace(
|
||||
",",
|
||||
", "
|
||||
)}
|
||||
</Text>
|
||||
<Text
|
||||
style={{
|
||||
color:
|
||||
theme.textColorSecondaryDark,
|
||||
marginVertical: 3,
|
||||
fontSize: 15,
|
||||
}}
|
||||
>
|
||||
{item.Release}
|
||||
</Text>
|
||||
<Text
|
||||
style={{
|
||||
color:
|
||||
theme.textColorSecondaryDark,
|
||||
marginVertical: 3,
|
||||
fontSize: 15,
|
||||
}}
|
||||
>
|
||||
{item.Status + " • " + item.Type}
|
||||
</Text>
|
||||
</>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
</LinearGradient>
|
||||
</ImageBackground>
|
||||
{!loading && (
|
||||
<>
|
||||
<Button
|
||||
color={theme.textColorPrimaryDark}
|
||||
style={[
|
||||
{
|
||||
backgroundColor: theme.colorAccentDark,
|
||||
marginHorizontal: 15,
|
||||
},
|
||||
item.novelSummary.length === 0 && {
|
||||
marginBottom: 20,
|
||||
},
|
||||
]}
|
||||
uppercase={false}
|
||||
labelStyle={{ letterSpacing: 0 }}
|
||||
onPress={() => insertToLibrary()}
|
||||
>
|
||||
{libraryStatus === 0
|
||||
? "Add to library"
|
||||
: "In Library"}
|
||||
</Button>
|
||||
{item.novelSummary.length > 0 && (
|
||||
<View
|
||||
style={{
|
||||
paddingHorizontal: 15,
|
||||
marginBottom: 10,
|
||||
}}
|
||||
>
|
||||
<Text
|
||||
style={{
|
||||
color: theme.textColorPrimaryDark,
|
||||
marginTop: 5,
|
||||
paddingVertical: 5,
|
||||
fontSize: 15,
|
||||
}}
|
||||
>
|
||||
About
|
||||
</Text>
|
||||
<Text
|
||||
style={{
|
||||
color: theme.textColorSecondaryDark,
|
||||
lineHeight: 20,
|
||||
}}
|
||||
numberOfLines={more ? 100 : 2}
|
||||
onPress={() => setMore(!more)}
|
||||
ellipsizeMode="clip"
|
||||
>
|
||||
{item.novelSummary}
|
||||
</Text>
|
||||
<Text
|
||||
style={{
|
||||
color: theme.colorAccentDark,
|
||||
fontWeight: "bold",
|
||||
position: "absolute",
|
||||
bottom: 0,
|
||||
right: 15,
|
||||
}}
|
||||
onPress={() => setMore(!more)}
|
||||
>
|
||||
{more ? "Less" : "More"}
|
||||
</Text>
|
||||
</View>
|
||||
)}
|
||||
<FlatList
|
||||
contentContainerStyle={{
|
||||
paddingHorizontal: 15,
|
||||
marginBottom: 15,
|
||||
}}
|
||||
horizontal
|
||||
data={item["Genre(s)"].split(",")}
|
||||
keyExtractor={(item) => item}
|
||||
renderItem={({ item }) => (
|
||||
<Text
|
||||
style={[
|
||||
styles.genre,
|
||||
{
|
||||
color: theme.colorAccentDark,
|
||||
borderColor: theme.colorAccentDark,
|
||||
},
|
||||
]}
|
||||
>
|
||||
{item}
|
||||
</Text>
|
||||
)}
|
||||
/>
|
||||
|
||||
<TouchableRipple
|
||||
style={{
|
||||
flex: 1,
|
||||
flexDirection: "row",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
}}
|
||||
onPress={() =>
|
||||
setChapters((chapters) => chapters.reverse())
|
||||
}
|
||||
rippleColor={theme.rippleColorDark}
|
||||
>
|
||||
<>
|
||||
<Text
|
||||
style={{
|
||||
color: theme.textColorPrimaryDark,
|
||||
paddingHorizontal: 15,
|
||||
paddingVertical: 5,
|
||||
fontSize: 15,
|
||||
}}
|
||||
>
|
||||
{chapters.length + " Chapters"}
|
||||
</Text>
|
||||
<IconButton
|
||||
icon="filter-variant"
|
||||
color={theme.textColorPrimaryDark}
|
||||
size={20}
|
||||
onPress={() => sortChapters()}
|
||||
/>
|
||||
</>
|
||||
</TouchableRipple>
|
||||
<FlatList
|
||||
data={chapters}
|
||||
extraData={chapters}
|
||||
showsVerticalScrollIndicator={false}
|
||||
keyExtractor={(item) =>
|
||||
item.chapterUrl
|
||||
? item.chapterUrl
|
||||
: item.chapterUrl
|
||||
}
|
||||
removeClippedSubviews={true}
|
||||
maxToRenderPerBatch={10}
|
||||
initialNumToRender={10}
|
||||
renderItem={({ item }) => (
|
||||
<TouchableRipple
|
||||
style={{
|
||||
paddingHorizontal: 15,
|
||||
paddingVertical: 12,
|
||||
}}
|
||||
onPress={() =>
|
||||
navigation.navigate("ChapterItem", {
|
||||
chapterUrl: item.chapterUrl,
|
||||
})
|
||||
}
|
||||
rippleColor={theme.rippleColorDark}
|
||||
>
|
||||
<>
|
||||
<Text
|
||||
style={{
|
||||
color:
|
||||
theme.textColorPrimaryDark,
|
||||
}}
|
||||
numberOfLines={1}
|
||||
>
|
||||
{item.chapterName}
|
||||
</Text>
|
||||
<Text
|
||||
style={{
|
||||
color:
|
||||
theme.textColorSecondaryDark,
|
||||
marginTop: 5,
|
||||
fontSize: 13,
|
||||
}}
|
||||
numberOfLines={1}
|
||||
>
|
||||
{item.releaseDate}
|
||||
</Text>
|
||||
</>
|
||||
</TouchableRipple>
|
||||
)}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</ScrollView>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default NovelItem;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
// backgroundColor: "#202125",
|
||||
backgroundColor: "#000000",
|
||||
},
|
||||
nameContainer: {
|
||||
flex: 1,
|
||||
width: "100%",
|
||||
marginHorizontal: 15,
|
||||
// justifyContent: "center",
|
||||
},
|
||||
background: {
|
||||
height: 240,
|
||||
},
|
||||
linearGradient: {
|
||||
height: "100%",
|
||||
backgroundColor: "rgba(256, 256, 256, 0.5)",
|
||||
},
|
||||
detailsContainer: {
|
||||
flex: 1,
|
||||
flexDirection: "row",
|
||||
margin: 15,
|
||||
},
|
||||
logo: {
|
||||
height: 180,
|
||||
width: 120,
|
||||
margin: 3.2,
|
||||
borderRadius: 6,
|
||||
},
|
||||
genre: {
|
||||
borderRadius: 24,
|
||||
borderWidth: 1,
|
||||
paddingHorizontal: 10,
|
||||
marginHorizontal: 2,
|
||||
fontSize: 13,
|
||||
paddingVertical: 2,
|
||||
justifyContent: "center",
|
||||
flex: 1,
|
||||
},
|
||||
name: {
|
||||
fontWeight: "bold",
|
||||
fontSize: 20,
|
||||
},
|
||||
});
|
||||
+75
-42
@@ -26,13 +26,14 @@ const NovelItem = ({ route, navigation }) => {
|
||||
const item = route.params;
|
||||
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [refreshing, setRefreshing] = useState(true);
|
||||
const [refreshing, setRefreshing] = useState(false);
|
||||
|
||||
const [novel, setNovel] = useState();
|
||||
const [novel, setNovel] = useState(item);
|
||||
const [chapters, setChapters] = useState();
|
||||
const [more, setMore] = useState(false);
|
||||
|
||||
const [libraryStatus, setlibraryStatus] = useState();
|
||||
// const [dbFlag, setDbFlag] = useState(0);
|
||||
|
||||
const getNovel = () => {
|
||||
fetch(`http://192.168.1.39:5000/api/novel/${item.novelUrl}`)
|
||||
@@ -40,7 +41,6 @@ const NovelItem = ({ route, navigation }) => {
|
||||
.then((json) => {
|
||||
setNovel(json);
|
||||
setChapters(json.novelChapters);
|
||||
checkIfExistsInLibrary(json.novelUrl);
|
||||
})
|
||||
.catch((error) => console.error(error))
|
||||
.finally(() => {
|
||||
@@ -49,34 +49,62 @@ const NovelItem = ({ route, navigation }) => {
|
||||
});
|
||||
};
|
||||
|
||||
const getNovelFromDb = () => {
|
||||
db.transaction((tx) => {
|
||||
tx.executeSql(
|
||||
"SELECT * FROM LibraryTable WHERE novelUrl=?",
|
||||
[item.novelUrl],
|
||||
(txObj, results) => {
|
||||
let len = results.rows.length;
|
||||
for (let i = 0; i < len; i++) {
|
||||
let row = results.rows.item(i);
|
||||
setNovel(row);
|
||||
}
|
||||
},
|
||||
(txObj, error) => console.log("Error ", error)
|
||||
);
|
||||
tx.executeSql(
|
||||
"SELECT * FROM ChapterTable WHERE novelUrl=?",
|
||||
[item.novelUrl],
|
||||
(txObj, { rows: { _array } }) => {
|
||||
setChapters(_array);
|
||||
setRefreshing(false);
|
||||
setLoading(false);
|
||||
},
|
||||
(txObj, error) => console.log("Error ", error)
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
const insertToLibrary = () => {
|
||||
if (libraryStatus === 0) {
|
||||
db.transaction((tx) => {
|
||||
tx.executeSql(
|
||||
"INSERT INTO LibraryTable (novelId, novelName, novelCover, novelSummary, alternative, author, genre, type, releaseDate, status) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||||
"INSERT INTO LibraryTable (novelUrl, novelName, novelCover, novelSummary, Alternative, `Author(s)`, `Genre(s)`, Type, `Release`, Status) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||||
[
|
||||
novel.novelUrl,
|
||||
item.novelUrl,
|
||||
novel.novelName,
|
||||
novel.novelCover,
|
||||
novel.novelSummary,
|
||||
novel.novelDetails.Alternative,
|
||||
novel.novelDetails["Author(s)"],
|
||||
novel.novelDetails["Genre(s)"],
|
||||
novel.novelDetails.Type,
|
||||
novel.novelDetails.Release,
|
||||
novel.novelDetails.Status,
|
||||
]
|
||||
novel.Alternative,
|
||||
novel["Author(s)"],
|
||||
novel["Genre(s)"],
|
||||
novel.Type,
|
||||
novel.Release,
|
||||
novel.Status,
|
||||
],
|
||||
(tx, res) => console.log("Inserted Novel"),
|
||||
(txObj, error) => console.log("Error ", error)
|
||||
);
|
||||
console.log("Inserted Novel");
|
||||
|
||||
novel.novelChapters.map((chap) =>
|
||||
chapters.map((chap) =>
|
||||
tx.executeSql(
|
||||
"INSERT INTO ChapterTable (chapterId, chapterName, releaseDate, novelId) values (?, ?, ?, ?)",
|
||||
"INSERT INTO ChapterTable (chapterUrl, chapterName, releaseDate, novelUrl) values (?, ?, ?, ?)",
|
||||
[
|
||||
chap.chapterUrl,
|
||||
chap.chapterName,
|
||||
chap.releaseDate,
|
||||
novel.novelUrl,
|
||||
item.novelUrl,
|
||||
]
|
||||
)
|
||||
);
|
||||
@@ -85,15 +113,15 @@ const NovelItem = ({ route, navigation }) => {
|
||||
} else {
|
||||
db.transaction((tx) => {
|
||||
tx.executeSql(
|
||||
"DELETE FROM LibraryTable WHERE novelId=?",
|
||||
[novel.novelUrl],
|
||||
"DELETE FROM LibraryTable WHERE novelUrl=?",
|
||||
[item.novelUrl],
|
||||
(txObj, res) => {
|
||||
console.log("DELETED NOVEL FROM TABLE");
|
||||
},
|
||||
(txObj, error) => console.log("Error ", error)
|
||||
);
|
||||
tx.executeSql("DELETE FROM ChapterTable WHERE novelId=?", [
|
||||
novel.novelUrl,
|
||||
tx.executeSql("DELETE FROM ChapterTable WHERE novelUrl=?", [
|
||||
item.novelUrl,
|
||||
]);
|
||||
console.log("Removed Novel");
|
||||
setlibraryStatus(0);
|
||||
@@ -104,15 +132,18 @@ const NovelItem = ({ route, navigation }) => {
|
||||
const checkIfExistsInLibrary = (id) => {
|
||||
db.transaction((tx) => {
|
||||
tx.executeSql(
|
||||
"SELECT * FROM LibraryTable WHERE novelId=?",
|
||||
"SELECT * FROM LibraryTable WHERE novelUrl=?",
|
||||
[id],
|
||||
(txObj, res) => {
|
||||
console.log(res.rows.length);
|
||||
if (res.rows.length === 0) {
|
||||
setRefreshing(true);
|
||||
console.log("Not In Library");
|
||||
getNovel();
|
||||
setlibraryStatus(0);
|
||||
} else {
|
||||
console.log("In Library");
|
||||
getNovelFromDb();
|
||||
setlibraryStatus(1);
|
||||
}
|
||||
},
|
||||
@@ -122,12 +153,12 @@ const NovelItem = ({ route, navigation }) => {
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
getNovel();
|
||||
checkIfExistsInLibrary(item.novelUrl);
|
||||
}, []);
|
||||
|
||||
const onRefresh = async () => {
|
||||
setRefreshing(true);
|
||||
getNovel();
|
||||
checkIfExistsInLibrary(item.novelUrl);
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -196,9 +227,10 @@ const NovelItem = ({ route, navigation }) => {
|
||||
}}
|
||||
numberOfLines={1}
|
||||
>
|
||||
{novel.novelDetails[
|
||||
"Alternative"
|
||||
].replace(",", ", ")}
|
||||
{novel.Alternative.replace(
|
||||
",",
|
||||
", "
|
||||
)}
|
||||
</Text>
|
||||
<Text
|
||||
style={{
|
||||
@@ -208,9 +240,10 @@ const NovelItem = ({ route, navigation }) => {
|
||||
fontSize: 15,
|
||||
}}
|
||||
>
|
||||
{novel.novelDetails[
|
||||
"Author(s)"
|
||||
].replace(",", ", ")}
|
||||
{novel["Author(s)"].replace(
|
||||
",",
|
||||
", "
|
||||
)}
|
||||
</Text>
|
||||
<Text
|
||||
style={{
|
||||
@@ -220,7 +253,7 @@ const NovelItem = ({ route, navigation }) => {
|
||||
fontSize: 15,
|
||||
}}
|
||||
>
|
||||
{novel.novelDetails["Release"]}
|
||||
{novel["Release"]}
|
||||
</Text>
|
||||
<Text
|
||||
style={{
|
||||
@@ -230,9 +263,9 @@ const NovelItem = ({ route, navigation }) => {
|
||||
fontSize: 15,
|
||||
}}
|
||||
>
|
||||
{novel.novelDetails["Status"] +
|
||||
{novel["Status"] +
|
||||
" • " +
|
||||
novel.novelDetails["Type"]}
|
||||
novel["Type"]}
|
||||
</Text>
|
||||
</>
|
||||
)}
|
||||
@@ -323,7 +356,7 @@ const NovelItem = ({ route, navigation }) => {
|
||||
marginBottom: 15,
|
||||
}}
|
||||
horizontal
|
||||
data={novel.novelDetails["Genre(s)"].split(",")}
|
||||
data={novel["Genre(s)"].split(",")}
|
||||
keyExtractor={(item) => item}
|
||||
renderItem={({ item }) => (
|
||||
<Text
|
||||
@@ -347,9 +380,9 @@ const NovelItem = ({ route, navigation }) => {
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
}}
|
||||
onPress={() =>
|
||||
setChapters((chapters) => chapters.reverse())
|
||||
}
|
||||
// onPress={() =>
|
||||
// setChapters((chapters) => chapters.reverse())
|
||||
// }
|
||||
rippleColor={theme.rippleColorDark}
|
||||
>
|
||||
<>
|
||||
@@ -367,11 +400,11 @@ const NovelItem = ({ route, navigation }) => {
|
||||
icon="filter-variant"
|
||||
color={theme.textColorPrimaryDark}
|
||||
size={20}
|
||||
onPress={() =>
|
||||
setChapters((chapters) =>
|
||||
chapters.reverse()
|
||||
)
|
||||
}
|
||||
// onPress={() =>
|
||||
// setChapters((chapters) =>
|
||||
// chapters.reverse()
|
||||
// )
|
||||
// }
|
||||
/>
|
||||
</>
|
||||
</TouchableRipple>
|
||||
@@ -379,7 +412,7 @@ const NovelItem = ({ route, navigation }) => {
|
||||
data={chapters}
|
||||
extraData={chapters}
|
||||
showsVerticalScrollIndicator={false}
|
||||
keyExtractor={(item) => item.chapterUrl}
|
||||
keyExtractor={(item) => novel.chapterUrl}
|
||||
removeClippedSubviews={true}
|
||||
maxToRenderPerBatch={10}
|
||||
initialNumToRender={10}
|
||||
|
||||
@@ -1,507 +0,0 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import {
|
||||
StyleSheet,
|
||||
View,
|
||||
Image,
|
||||
ImageBackground,
|
||||
Text,
|
||||
FlatList,
|
||||
ScrollView,
|
||||
RefreshControl,
|
||||
} from "react-native";
|
||||
import {
|
||||
Appbar,
|
||||
TouchableRipple,
|
||||
IconButton,
|
||||
Button,
|
||||
} from "react-native-paper";
|
||||
import { LinearGradient } from "expo-linear-gradient";
|
||||
|
||||
import { theme } from "../theming/theme";
|
||||
|
||||
import * as SQLite from "expo-sqlite";
|
||||
const db = SQLite.openDatabase("lnreader.db");
|
||||
|
||||
const NovelItem = ({ route, navigation }) => {
|
||||
const item = route.params;
|
||||
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [refreshing, setRefreshing] = useState(false);
|
||||
|
||||
const [novel, setNovel] = useState(item);
|
||||
const [chapters, setChapters] = useState();
|
||||
const [more, setMore] = useState(false);
|
||||
|
||||
const [libraryStatus, setlibraryStatus] = useState();
|
||||
// const [dbFlag, setDbFlag] = useState(0);
|
||||
|
||||
const getNovel = () => {
|
||||
fetch(`http://192.168.1.39:5000/api/novel/${item.novelUrl}`)
|
||||
.then((response) => response.json())
|
||||
.then((json) => {
|
||||
setNovel(json);
|
||||
setChapters(json.novelChapters);
|
||||
})
|
||||
.catch((error) => console.error(error))
|
||||
.finally(() => {
|
||||
setRefreshing(false);
|
||||
setLoading(false);
|
||||
});
|
||||
};
|
||||
|
||||
const getNovelFromDb = () => {
|
||||
db.transaction((tx) => {
|
||||
// tx.executeSql(
|
||||
// "SELECT * FROM LibraryTable WHERE novelUrl=?",
|
||||
// [item.novelUrl],
|
||||
// (txObj, { rows: _array }) => {
|
||||
// // setNovel(_array);
|
||||
// // console.log(_array);
|
||||
// },
|
||||
// (txObj, error) => console.log("Error ", error)
|
||||
// );
|
||||
tx.executeSql(
|
||||
"SELECT * FROM ChapterTable WHERE novelUrl=?",
|
||||
[item.novelUrl],
|
||||
(txObj, { rows: { _array } }) => {
|
||||
setChapters(_array);
|
||||
// console.log(_array);
|
||||
setRefreshing(false);
|
||||
setLoading(false);
|
||||
},
|
||||
(txObj, error) => console.log("Error ", error)
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
const insertToLibrary = () => {
|
||||
if (libraryStatus === 0) {
|
||||
db.transaction((tx) => {
|
||||
tx.executeSql(
|
||||
"INSERT INTO LibraryTable (novelUrl, novelName, novelCover, novelSummary, Alternative, `Author(s)`, `Genre(s)`, Type, `Release`, Status) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||||
[
|
||||
item.novelUrl,
|
||||
novel.novelName,
|
||||
novel.novelCover,
|
||||
novel.novelSummary,
|
||||
novel.Alternative,
|
||||
novel["Author(s)"],
|
||||
novel["Genre(s)"],
|
||||
novel.Type,
|
||||
novel.Release,
|
||||
novel.Status,
|
||||
],
|
||||
(tx, res) => console.log("Inserted Novel"),
|
||||
(txObj, error) => console.log("Error ", error)
|
||||
);
|
||||
|
||||
chapters.map((chap) =>
|
||||
tx.executeSql(
|
||||
"INSERT INTO ChapterTable (chapterUrl, chapterName, releaseDate, novelUrl) values (?, ?, ?, ?)",
|
||||
[
|
||||
chap.chapterUrl,
|
||||
chap.chapterName,
|
||||
chap.releaseDate,
|
||||
item.novelUrl,
|
||||
]
|
||||
)
|
||||
);
|
||||
setlibraryStatus(1);
|
||||
});
|
||||
} else {
|
||||
db.transaction((tx) => {
|
||||
tx.executeSql(
|
||||
"DELETE FROM LibraryTable WHERE novelUrl=?",
|
||||
[item.novelUrl],
|
||||
(txObj, res) => {
|
||||
console.log("DELETED NOVEL FROM TABLE");
|
||||
},
|
||||
(txObj, error) => console.log("Error ", error)
|
||||
);
|
||||
tx.executeSql("DELETE FROM ChapterTable WHERE novelUrl=?", [
|
||||
item.novelUrl,
|
||||
]);
|
||||
console.log("Removed Novel");
|
||||
setlibraryStatus(0);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const checkIfExistsInLibrary = (id) => {
|
||||
db.transaction((tx) => {
|
||||
tx.executeSql(
|
||||
"SELECT * FROM LibraryTable WHERE novelUrl=?",
|
||||
[id],
|
||||
(txObj, res) => {
|
||||
console.log(res.rows.length);
|
||||
if (res.rows.length === 0) {
|
||||
console.log("Not In Library");
|
||||
getNovel();
|
||||
setlibraryStatus(0);
|
||||
} else {
|
||||
console.log("In Library");
|
||||
getNovelFromDb();
|
||||
setlibraryStatus(1);
|
||||
}
|
||||
},
|
||||
(txObj, error) => console.log("Error ", error)
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
checkIfExistsInLibrary(item.novelUrl);
|
||||
}, []);
|
||||
|
||||
const onRefresh = async () => {
|
||||
setRefreshing(true);
|
||||
checkIfExistsInLibrary(item.novelUrl);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Appbar.Header style={{ backgroundColor: theme.colorDarkPrimary }}>
|
||||
<Appbar.BackAction
|
||||
onPress={() => {
|
||||
navigation.goBack();
|
||||
}}
|
||||
color={"white"}
|
||||
size={26}
|
||||
style={{ marginRight: 0 }}
|
||||
/>
|
||||
<Appbar.Content
|
||||
title={item.novelName}
|
||||
titleStyle={{ color: theme.textColorPrimaryDark }}
|
||||
/>
|
||||
</Appbar.Header>
|
||||
|
||||
<ScrollView
|
||||
style={styles.container}
|
||||
refreshControl={
|
||||
<RefreshControl
|
||||
refreshing={refreshing}
|
||||
onRefresh={onRefresh}
|
||||
colors={["white"]}
|
||||
progressBackgroundColor={theme.colorAccentDark}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<ImageBackground
|
||||
source={{
|
||||
uri: item.novelCover,
|
||||
}}
|
||||
style={styles.background}
|
||||
>
|
||||
<LinearGradient
|
||||
colors={["transparent", "#000000"]}
|
||||
style={styles.linearGradient}
|
||||
>
|
||||
<View style={styles.detailsContainer}>
|
||||
<Image
|
||||
source={{
|
||||
uri: item.novelCover,
|
||||
}}
|
||||
style={styles.logo}
|
||||
/>
|
||||
<View style={styles.nameContainer}>
|
||||
<Text
|
||||
numberOfLines={4}
|
||||
style={[
|
||||
styles.name,
|
||||
{ color: theme.textColorPrimaryDark },
|
||||
]}
|
||||
>
|
||||
{item.novelName}
|
||||
</Text>
|
||||
{!loading && (
|
||||
<>
|
||||
<Text
|
||||
style={{
|
||||
color:
|
||||
theme.textColorSecondaryDark,
|
||||
marginVertical: 3,
|
||||
fontSize: 15,
|
||||
}}
|
||||
numberOfLines={1}
|
||||
>
|
||||
{novel.Alternative.replace(
|
||||
",",
|
||||
", "
|
||||
)}
|
||||
</Text>
|
||||
<Text
|
||||
style={{
|
||||
color:
|
||||
theme.textColorSecondaryDark,
|
||||
marginVertical: 3,
|
||||
fontSize: 15,
|
||||
}}
|
||||
>
|
||||
{novel["Author(s)"].replace(
|
||||
",",
|
||||
", "
|
||||
)}
|
||||
</Text>
|
||||
<Text
|
||||
style={{
|
||||
color:
|
||||
theme.textColorSecondaryDark,
|
||||
marginVertical: 3,
|
||||
fontSize: 15,
|
||||
}}
|
||||
>
|
||||
{novel["Release"]}
|
||||
</Text>
|
||||
<Text
|
||||
style={{
|
||||
color:
|
||||
theme.textColorSecondaryDark,
|
||||
marginVertical: 3,
|
||||
fontSize: 15,
|
||||
}}
|
||||
>
|
||||
{novel["Status"] +
|
||||
" • " +
|
||||
novel["Type"]}
|
||||
</Text>
|
||||
</>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
</LinearGradient>
|
||||
</ImageBackground>
|
||||
{!loading && (
|
||||
<>
|
||||
<Button
|
||||
color={theme.textColorPrimaryDark}
|
||||
style={[
|
||||
{
|
||||
backgroundColor: theme.colorAccentDark,
|
||||
marginHorizontal: 15,
|
||||
},
|
||||
novel.novelSummary.length === 0 && {
|
||||
marginBottom: 20,
|
||||
},
|
||||
]}
|
||||
uppercase={false}
|
||||
labelStyle={{ letterSpacing: 0 }}
|
||||
onPress={() => insertToLibrary()}
|
||||
>
|
||||
{libraryStatus === 0
|
||||
? "Add to library"
|
||||
: "In Library"}
|
||||
</Button>
|
||||
{/* <Button
|
||||
color={theme.textColorPrimaryDark}
|
||||
style={{
|
||||
backgroundColor: theme.colorAccentDark,
|
||||
marginHorizontal: 15,
|
||||
}}
|
||||
uppercase={false}
|
||||
labelStyle={{ letterSpacing: 0 }}
|
||||
onPress={() =>
|
||||
checkIfExistsInLibrary(novel.novelUrl)
|
||||
}
|
||||
>
|
||||
Check
|
||||
</Button> */}
|
||||
{novel.novelSummary.length > 0 && (
|
||||
<View
|
||||
style={{
|
||||
paddingHorizontal: 15,
|
||||
marginBottom: 10,
|
||||
}}
|
||||
>
|
||||
<Text
|
||||
style={{
|
||||
color: theme.textColorPrimaryDark,
|
||||
marginTop: 5,
|
||||
paddingVertical: 5,
|
||||
fontSize: 15,
|
||||
}}
|
||||
>
|
||||
About
|
||||
</Text>
|
||||
<Text
|
||||
style={{
|
||||
color: theme.textColorSecondaryDark,
|
||||
lineHeight: 20,
|
||||
}}
|
||||
numberOfLines={more ? 100 : 2}
|
||||
onPress={() => setMore(!more)}
|
||||
ellipsizeMode="clip"
|
||||
>
|
||||
{novel.novelSummary}
|
||||
</Text>
|
||||
<Text
|
||||
style={{
|
||||
color: theme.colorAccentDark,
|
||||
fontWeight: "bold",
|
||||
position: "absolute",
|
||||
bottom: 0,
|
||||
right: 15,
|
||||
}}
|
||||
onPress={() => setMore(!more)}
|
||||
>
|
||||
{more ? "Less" : "More"}
|
||||
</Text>
|
||||
</View>
|
||||
)}
|
||||
<FlatList
|
||||
contentContainerStyle={{
|
||||
paddingHorizontal: 15,
|
||||
marginBottom: 15,
|
||||
}}
|
||||
horizontal
|
||||
data={novel["Genre(s)"].split(",")}
|
||||
keyExtractor={(item) => item}
|
||||
renderItem={({ item }) => (
|
||||
<Text
|
||||
style={[
|
||||
styles.genre,
|
||||
{
|
||||
color: theme.colorAccentDark,
|
||||
borderColor: theme.colorAccentDark,
|
||||
},
|
||||
]}
|
||||
>
|
||||
{item}
|
||||
</Text>
|
||||
)}
|
||||
/>
|
||||
|
||||
<TouchableRipple
|
||||
style={{
|
||||
flex: 1,
|
||||
flexDirection: "row",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
}}
|
||||
// onPress={() =>
|
||||
// setChapters((chapters) => chapters.reverse())
|
||||
// }
|
||||
rippleColor={theme.rippleColorDark}
|
||||
>
|
||||
<>
|
||||
<Text
|
||||
style={{
|
||||
color: theme.textColorPrimaryDark,
|
||||
paddingHorizontal: 15,
|
||||
paddingVertical: 5,
|
||||
fontSize: 15,
|
||||
}}
|
||||
>
|
||||
{chapters.length + " Chapters"}
|
||||
</Text>
|
||||
<IconButton
|
||||
icon="filter-variant"
|
||||
color={theme.textColorPrimaryDark}
|
||||
size={20}
|
||||
// onPress={() =>
|
||||
// setChapters((chapters) =>
|
||||
// chapters.reverse()
|
||||
// )
|
||||
// }
|
||||
/>
|
||||
</>
|
||||
</TouchableRipple>
|
||||
<FlatList
|
||||
data={chapters}
|
||||
extraData={chapters}
|
||||
showsVerticalScrollIndicator={false}
|
||||
keyExtractor={(item) => novel.chapterUrl}
|
||||
removeClippedSubviews={true}
|
||||
maxToRenderPerBatch={10}
|
||||
initialNumToRender={10}
|
||||
renderItem={({ item }) => (
|
||||
<TouchableRipple
|
||||
style={{
|
||||
paddingHorizontal: 15,
|
||||
paddingVertical: 12,
|
||||
}}
|
||||
onPress={() =>
|
||||
navigation.navigate("ChapterItem", {
|
||||
chapterUrl: item.chapterUrl,
|
||||
})
|
||||
}
|
||||
rippleColor={theme.rippleColorDark}
|
||||
>
|
||||
<>
|
||||
<Text
|
||||
style={{
|
||||
color:
|
||||
theme.textColorPrimaryDark,
|
||||
}}
|
||||
numberOfLines={1}
|
||||
>
|
||||
{item.chapterName}
|
||||
</Text>
|
||||
<Text
|
||||
style={{
|
||||
color:
|
||||
theme.textColorSecondaryDark,
|
||||
marginTop: 5,
|
||||
fontSize: 13,
|
||||
}}
|
||||
numberOfLines={1}
|
||||
>
|
||||
{item.releaseDate}
|
||||
</Text>
|
||||
</>
|
||||
</TouchableRipple>
|
||||
)}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</ScrollView>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default NovelItem;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
// backgroundColor: "#202125",
|
||||
backgroundColor: "#000000",
|
||||
},
|
||||
nameContainer: {
|
||||
flex: 1,
|
||||
width: "100%",
|
||||
marginHorizontal: 15,
|
||||
// justifyContent: "center",
|
||||
},
|
||||
background: {
|
||||
height: 240,
|
||||
},
|
||||
linearGradient: {
|
||||
height: "100%",
|
||||
backgroundColor: "rgba(256, 256, 256, 0.5)",
|
||||
},
|
||||
detailsContainer: {
|
||||
flex: 1,
|
||||
flexDirection: "row",
|
||||
margin: 15,
|
||||
},
|
||||
logo: {
|
||||
height: 180,
|
||||
width: 120,
|
||||
margin: 3.2,
|
||||
borderRadius: 6,
|
||||
},
|
||||
genre: {
|
||||
borderRadius: 24,
|
||||
borderWidth: 1,
|
||||
paddingHorizontal: 10,
|
||||
marginHorizontal: 2,
|
||||
fontSize: 13,
|
||||
paddingVertical: 2,
|
||||
justifyContent: "center",
|
||||
flex: 1,
|
||||
},
|
||||
name: {
|
||||
fontWeight: "bold",
|
||||
fontSize: 20,
|
||||
},
|
||||
});
|
||||
@@ -116,10 +116,7 @@ const AllNovels = ({ navigation }) => {
|
||||
rippleColor="rgba(256,256,256,0.3)"
|
||||
style={styles.opac}
|
||||
onPress={() =>
|
||||
navigation.navigate(
|
||||
"NovelItemRewrite",
|
||||
item
|
||||
)
|
||||
navigation.navigate("NovelItem", item)
|
||||
}
|
||||
>
|
||||
<NovelCover item={item} />
|
||||
|
||||
Reference in New Issue
Block a user