Refactor Chapter
This commit is contained in:
@@ -30,7 +30,11 @@
|
||||
},
|
||||
"package": "com.rajarsheechatterjee.LNReader"
|
||||
},
|
||||
|
||||
"androidStatusBar": {
|
||||
"barStyle": "light-content",
|
||||
"backgroundColor": "#00000000",
|
||||
"translucent": true
|
||||
},
|
||||
"androidNavigationBar": {
|
||||
"barStyle": "light-content",
|
||||
"backgroundColor": "#000000"
|
||||
|
||||
Generated
+5
@@ -3969,6 +3969,11 @@
|
||||
"resolved": "https://registry.npmjs.org/expo-sharing/-/expo-sharing-9.1.2.tgz",
|
||||
"integrity": "sha512-IFBQPimeZtdqtvmqQZEmiI0D4j9xE53tSZxLFrFPplNWzgDefk+dP+flof3duf9JgCQTsvOUU2h2/XwjD3vBTA=="
|
||||
},
|
||||
"expo-speech": {
|
||||
"version": "9.1.0",
|
||||
"resolved": "https://registry.npmjs.org/expo-speech/-/expo-speech-9.1.0.tgz",
|
||||
"integrity": "sha512-5yIMVo1auAwClVnlJnCRyJqKS82IeQXzTCamP4iP4LmHDR5+9sae/D/mD5mX7KV3brWf3n0sEyFhuU7WqgMQvg=="
|
||||
},
|
||||
"expo-splash-screen": {
|
||||
"version": "0.10.2",
|
||||
"resolved": "https://registry.npmjs.org/expo-splash-screen/-/expo-splash-screen-0.10.2.tgz",
|
||||
|
||||
+2
-1
@@ -54,7 +54,8 @@
|
||||
"redux-devtools-extension": "^2.13.9",
|
||||
"redux-persist": "^6.0.0",
|
||||
"redux-thunk": "^2.3.0",
|
||||
"rn-sliding-up-panel": "^2.4.4"
|
||||
"rn-sliding-up-panel": "^2.4.4",
|
||||
"expo-speech": "~9.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "~7.9.0"
|
||||
|
||||
@@ -56,7 +56,7 @@ export const getChapters = (novelId, sort, filter) => {
|
||||
|
||||
const getChapterQuery = `SELECT * FROM downloads WHERE downloadChapterId = ?`;
|
||||
|
||||
export const getChapter = async (chapterId) => {
|
||||
export const getChapterFromDB = async (chapterId) => {
|
||||
return new Promise((resolve, reject) =>
|
||||
db.transaction((tx) => {
|
||||
tx.executeSql(
|
||||
@@ -71,6 +71,36 @@ export const getChapter = async (chapterId) => {
|
||||
);
|
||||
};
|
||||
|
||||
export const getNextChapterFromDB = async (novelId, chapterId) => {
|
||||
return new Promise((resolve, reject) =>
|
||||
db.transaction((tx) => {
|
||||
tx.executeSql(
|
||||
`SELECT * FROM chapters WHERE novelId = ? AND chapterId > ?`,
|
||||
[novelId, chapterId],
|
||||
(tx, results) => {
|
||||
resolve(results.rows.item(0));
|
||||
},
|
||||
(txObj, error) => console.log("Error ", error)
|
||||
);
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
export const getPrevChapterFromDB = async (novelId, chapterId) => {
|
||||
return new Promise((resolve, reject) =>
|
||||
db.transaction((tx) => {
|
||||
tx.executeSql(
|
||||
`SELECT * FROM chapters WHERE novelId = ? AND chapterId < ?`,
|
||||
[novelId, chapterId],
|
||||
(tx, results) => {
|
||||
resolve(results.rows.item(results.rows.length - 1));
|
||||
},
|
||||
(txObj, error) => console.log("Error ", error)
|
||||
);
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
const markChapterReadQuery = `UPDATE chapters SET \`read\` = 1 WHERE chapterId = ?`;
|
||||
|
||||
export const markChapterRead = async (chapterId) => {
|
||||
|
||||
@@ -2,7 +2,7 @@ import * as SQLite from "expo-sqlite";
|
||||
const db = SQLite.openDatabase("lnreader.db");
|
||||
|
||||
const getUpdatesQuery = `
|
||||
SELECT chapters.chapterId, chapters.chapterUrl, chapters.chapterName, novels.novelUrl, novels.novelId, novels.novelCover, novels.novelName, novels.sourceId, updates.updateTime, updates.updateId
|
||||
SELECT chapters.chapterId, chapters.read, chapters.downloaded, chapters.chapterUrl, chapters.chapterName, novels.novelUrl, novels.novelId, novels.novelCover, novels.novelName, novels.sourceId, updates.updateTime, updates.updateId
|
||||
FROM updates
|
||||
JOIN chapters
|
||||
ON updates.chapterId = chapters.chapterId
|
||||
|
||||
@@ -89,6 +89,20 @@ const useContinueReading = (chapters, novelId) => {
|
||||
return { lastReadChapter, position };
|
||||
};
|
||||
|
||||
const usePosition = (novelId, chapterId) => {
|
||||
let novel, position;
|
||||
|
||||
novel = findNovel(novelId);
|
||||
|
||||
if (novel) {
|
||||
if (novel.position) {
|
||||
position = novel.position[chapterId] || null;
|
||||
}
|
||||
}
|
||||
|
||||
return position;
|
||||
};
|
||||
|
||||
const useTrackingStatus = () => {
|
||||
const tracker = useSelector((state) => state.trackerReducer);
|
||||
|
||||
@@ -113,4 +127,5 @@ export {
|
||||
useChapter,
|
||||
useSavedSettings,
|
||||
useLibraryFilters,
|
||||
usePosition,
|
||||
};
|
||||
|
||||
+103
-121
@@ -4,68 +4,95 @@ import {
|
||||
View,
|
||||
Text,
|
||||
ActivityIndicator,
|
||||
ScrollView,
|
||||
InteractionManager,
|
||||
Button,
|
||||
} from "react-native";
|
||||
import Constants from "expo-constants";
|
||||
|
||||
import { Appbar, Portal } from "react-native-paper";
|
||||
import { CollapsibleHeaderScrollView } from "react-native-collapsible-header-views";
|
||||
|
||||
import ReaderSheet from "./components/ReaderSheet";
|
||||
|
||||
import { insertHistoryAction } from "../../redux/history/history.actions";
|
||||
import {
|
||||
getChapterAction,
|
||||
saveScrollPosition,
|
||||
} from "../../redux/chapter/chapter.actions";
|
||||
import { markChapterReadAction } from "../../redux/novel/novel.actions";
|
||||
import { updateChaptersRead } from "../../redux/tracker/tracker.actions";
|
||||
|
||||
import { useDispatch } from "react-redux";
|
||||
import { parseChapterNumber } from "../../Services/updates";
|
||||
import Constants from "expo-constants";
|
||||
import { Portal } from "react-native-paper";
|
||||
import { CollapsibleHeaderScrollView } from "react-native-collapsible-header-views";
|
||||
|
||||
import { getChapterFromDB } from "../../Database/queries/ChapterQueries";
|
||||
import { fetchChapter } from "../../Services/Source/source";
|
||||
import { showToast } from "../../Hooks/showToast";
|
||||
import {
|
||||
useChapter,
|
||||
usePosition,
|
||||
useReaderSettings,
|
||||
useTheme,
|
||||
useTrackingStatus,
|
||||
} from "../../Hooks/reduxHooks";
|
||||
import { updateChaptersRead } from "../../redux/tracker/tracker.actions";
|
||||
import { insertHistoryAction } from "../../redux/history/history.actions";
|
||||
import {
|
||||
readerBackground,
|
||||
readerLineHeight,
|
||||
readerTextColor,
|
||||
} from "./readerStyleController";
|
||||
import { markChapterReadAction } from "../../redux/novel/novel.actions";
|
||||
import { saveScrollPosition } from "../../redux/preferences/preference.actions";
|
||||
import { parseChapterNumber } from "../../Services/updates";
|
||||
|
||||
import ChapterAppbar from "./components/ChapterAppbar";
|
||||
import ReaderSheet from "./components/ReaderSheet";
|
||||
|
||||
const Chapter = ({ route, navigation }) => {
|
||||
const { chapterId, sourceId, chapterUrl, novelUrl, novelId, position } =
|
||||
route.params;
|
||||
const {
|
||||
sourceId,
|
||||
chapterId,
|
||||
chapterUrl,
|
||||
novelId,
|
||||
novelUrl,
|
||||
novelName,
|
||||
chapterName,
|
||||
} = route.params;
|
||||
let scrollViewRef;
|
||||
let readerSheetRef = useRef(null);
|
||||
|
||||
const theme = useTheme();
|
||||
const reader = useReaderSettings();
|
||||
const dispatch = useDispatch();
|
||||
const reader = useReaderSettings();
|
||||
const { tracker, trackedNovels } = useTrackingStatus();
|
||||
const position = usePosition(novelId, chapterId);
|
||||
|
||||
const isTracked = trackedNovels.find((obj) => obj.novelId === novelId);
|
||||
|
||||
const { chapter, loading } = useChapter();
|
||||
const [chapter, setChapter] = useState({});
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
const [scrollPercentage, setScrollPercentage] = useState(0);
|
||||
const [firstLayout, setFirstLayout] = useState(true);
|
||||
|
||||
let scrollViewRef;
|
||||
const getChapter = async (chapterId) => {
|
||||
try {
|
||||
if (chapterId) {
|
||||
const chapterDownloaded = await getChapterFromDB(chapterId);
|
||||
|
||||
if (chapterDownloaded) {
|
||||
setChapter(chapterDownloaded);
|
||||
} else {
|
||||
const res = await fetchChapter(
|
||||
sourceId,
|
||||
novelUrl,
|
||||
chapterUrl
|
||||
);
|
||||
setChapter(res);
|
||||
}
|
||||
} else {
|
||||
const res = await fetchChapter(sourceId, novelUrl, chapterUrl);
|
||||
setChapter(res);
|
||||
}
|
||||
|
||||
setLoading(false);
|
||||
} catch (error) {
|
||||
showToast(error.message);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(getChapterAction(sourceId, novelUrl, chapterUrl, chapterId));
|
||||
getChapter(chapterId);
|
||||
dispatch(insertHistoryAction(novelId, chapterId));
|
||||
}, []);
|
||||
|
||||
let chapterNumber;
|
||||
|
||||
if (!loading) {
|
||||
chapterNumber = parseChapterNumber(chapter.chapterName);
|
||||
}
|
||||
|
||||
const isCloseToBottom = ({
|
||||
layoutMeasurement,
|
||||
contentOffset,
|
||||
@@ -78,39 +105,40 @@ const Chapter = ({ route, navigation }) => {
|
||||
);
|
||||
};
|
||||
|
||||
const updateTracker = () =>
|
||||
const updateTracker = () => {
|
||||
const chapterNumber = parseChapterNumber(chapterName);
|
||||
|
||||
isTracked &&
|
||||
chapterNumber &&
|
||||
chapterNumber > isTracked.my_list_status.num_chapters_read &&
|
||||
dispatch(
|
||||
updateChaptersRead(
|
||||
isTracked.id,
|
||||
tracker.access_token,
|
||||
chapterNumber
|
||||
)
|
||||
chapterNumber &&
|
||||
chapterNumber > isTracked.my_list_status.num_chapters_read &&
|
||||
dispatch(
|
||||
updateChaptersRead(
|
||||
isTracked.id,
|
||||
tracker.access_token,
|
||||
chapterNumber
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
const onScroll = ({ nativeEvent }) => {
|
||||
const offsetY = nativeEvent.contentOffset.y;
|
||||
const position =
|
||||
nativeEvent.contentOffset.y + nativeEvent.layoutMeasurement.height;
|
||||
|
||||
const percentage = Math.round(
|
||||
(position / nativeEvent.contentSize.height) * 100
|
||||
);
|
||||
|
||||
const navigateToPreviousChapter = () =>
|
||||
navigation.replace("Chapter", {
|
||||
chapterUrl: chapter.prevChapter,
|
||||
chapterId: chapterId - 1,
|
||||
sourceId,
|
||||
novelUrl,
|
||||
novelId,
|
||||
chapterName: chapter.chapterName,
|
||||
});
|
||||
setScrollPercentage(percentage);
|
||||
dispatch(saveScrollPosition(offsetY, percentage, chapterId, novelId));
|
||||
|
||||
const navigateToNextChapter = () =>
|
||||
navigation.replace("Chapter", {
|
||||
chapterUrl: chapter.nextChapter,
|
||||
sourceId,
|
||||
novelUrl,
|
||||
novelId,
|
||||
chapterId: chapterId + 1,
|
||||
chapterName: chapter.chapterName,
|
||||
});
|
||||
if (isCloseToBottom(nativeEvent)) {
|
||||
dispatch(markChapterReadAction(chapterId, novelId));
|
||||
updateTracker();
|
||||
}
|
||||
};
|
||||
|
||||
const scrollToInitialPosition = () => {
|
||||
const scrollToSavedProgress = () => {
|
||||
if (position && firstLayout) {
|
||||
position.percentage < 100 &&
|
||||
scrollViewRef.getNode().scrollTo({
|
||||
@@ -137,74 +165,28 @@ const Chapter = ({ route, navigation }) => {
|
||||
},
|
||||
];
|
||||
|
||||
const onScroll = ({ nativeEvent }) => {
|
||||
const offsetY = nativeEvent.contentOffset.y;
|
||||
const position =
|
||||
nativeEvent.contentOffset.y + nativeEvent.layoutMeasurement.height;
|
||||
|
||||
const percentage = Math.round(
|
||||
(position / nativeEvent.contentSize.height) * 100
|
||||
);
|
||||
|
||||
setScrollPercentage(percentage);
|
||||
dispatch(saveScrollPosition(offsetY, percentage, chapterId, novelId));
|
||||
|
||||
if (isCloseToBottom(nativeEvent)) {
|
||||
dispatch(markChapterReadAction(chapterId, novelId));
|
||||
updateTracker();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<CollapsibleHeaderScrollView
|
||||
headerContainerBackgroundColor="rgba(0,0,0,0.4)"
|
||||
ref={(ref) => {
|
||||
scrollViewRef = ref;
|
||||
}}
|
||||
ref={(ref) => (scrollViewRef = ref)}
|
||||
CollapsibleHeaderComponent={
|
||||
<Appbar.Header
|
||||
style={{ backgroundColor: "transparent", elevation: 0 }}
|
||||
>
|
||||
<Appbar.BackAction
|
||||
onPress={() => navigation.goBack()}
|
||||
color="#FFFFFF"
|
||||
size={26}
|
||||
style={{ marginRight: 0 }}
|
||||
/>
|
||||
<Appbar.Content
|
||||
title={loading ? "Chapter" : chapter.chapterName}
|
||||
titleStyle={{ color: "#FFFFFF" }}
|
||||
/>
|
||||
{!loading && (
|
||||
<>
|
||||
<Appbar.Action
|
||||
icon="chevron-left"
|
||||
size={26}
|
||||
disabled={!chapter.prevChapter}
|
||||
onPress={navigateToPreviousChapter}
|
||||
color="#FFFFFF"
|
||||
/>
|
||||
<Appbar.Action
|
||||
icon="chevron-right"
|
||||
size={26}
|
||||
disabled={!chapter.nextChapter}
|
||||
onPress={navigateToNextChapter}
|
||||
color="#FFFFFF"
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
<Appbar.Action
|
||||
icon="dots-vertical"
|
||||
size={26}
|
||||
onPress={() => readerSheetRef.current.show()}
|
||||
color="#FFFFFF"
|
||||
/>
|
||||
</Appbar.Header>
|
||||
<ChapterAppbar
|
||||
navigation={navigation}
|
||||
sourceId={sourceId}
|
||||
novelId={novelId}
|
||||
novelUrl={novelUrl}
|
||||
novelName={novelName}
|
||||
chapterName={chapterName}
|
||||
chapterId={chapterId}
|
||||
chapter={chapter}
|
||||
theme={theme}
|
||||
readerSheetRef={readerSheetRef}
|
||||
/>
|
||||
}
|
||||
headerHeight={Constants.statusBarHeight + 60}
|
||||
headerHeight={Constants.statusBarHeight + 56}
|
||||
contentContainerStyle={[
|
||||
styles.container,
|
||||
styles.screenContainer,
|
||||
{ backgroundColor: readerBackground(reader.theme) },
|
||||
]}
|
||||
onScroll={onScroll}
|
||||
@@ -219,7 +201,7 @@ const Chapter = ({ route, navigation }) => {
|
||||
) : (
|
||||
<Text
|
||||
style={readerStyles}
|
||||
onLayout={scrollToInitialPosition}
|
||||
onLayout={scrollToSavedProgress}
|
||||
selectable={true}
|
||||
>
|
||||
{chapter.chapterText.trim()}
|
||||
@@ -249,7 +231,7 @@ const Chapter = ({ route, navigation }) => {
|
||||
export default Chapter;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
screenContainer: {
|
||||
flexGrow: 1,
|
||||
paddingVertical: 10,
|
||||
},
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
|
||||
import { Appbar } from "react-native-paper";
|
||||
import {
|
||||
getNextChapterFromDB,
|
||||
getPrevChapterFromDB,
|
||||
} from "../../../Database/queries/ChapterQueries";
|
||||
|
||||
const ChapterAppbar = ({
|
||||
navigation,
|
||||
sourceId,
|
||||
novelId,
|
||||
novelName,
|
||||
novelUrl,
|
||||
chapterId,
|
||||
chapterName,
|
||||
theme,
|
||||
readerSheetRef,
|
||||
}) => {
|
||||
const [nextChapter, setNextChapter] = useState({});
|
||||
const [prevChapter, setPrevChapter] = useState({});
|
||||
|
||||
const setPrevAndNextChap = async () => {
|
||||
const nextChap = await getNextChapterFromDB(novelId, chapterId);
|
||||
const prevChap = await getPrevChapterFromDB(novelId, chapterId);
|
||||
|
||||
setNextChapter(nextChap);
|
||||
setPrevChapter(prevChap);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setPrevAndNextChap();
|
||||
}, []);
|
||||
|
||||
const navigateToPrevChapter = () =>
|
||||
navigation.replace("Chapter", {
|
||||
chapterUrl: prevChapter.chapterUrl,
|
||||
chapterId: prevChapter.chapterId,
|
||||
sourceId,
|
||||
novelUrl,
|
||||
novelId,
|
||||
chapterName: prevChapter.chapterName,
|
||||
novelName: novelName,
|
||||
});
|
||||
|
||||
const navigateToNextChapter = () =>
|
||||
navigation.replace("Chapter", {
|
||||
chapterUrl: nextChapter.nextChapter,
|
||||
sourceId,
|
||||
novelUrl,
|
||||
novelId,
|
||||
chapterId: nextChapter.chapterId,
|
||||
chapterName: nextChapter.chapterName,
|
||||
novelName: novelName,
|
||||
});
|
||||
|
||||
return (
|
||||
<Appbar.Header style={{ backgroundColor: "transparent", elevation: 0 }}>
|
||||
<Appbar.BackAction
|
||||
onPress={() => navigation.goBack()}
|
||||
color="#FFFFFF"
|
||||
size={26}
|
||||
style={{ marginRight: 0 }}
|
||||
/>
|
||||
<Appbar.Content
|
||||
title={novelName}
|
||||
titleStyle={{ color: theme.textColorPrimary }}
|
||||
subtitle={chapterName}
|
||||
subtitleStyle={{ color: theme.textColorSecondary }}
|
||||
/>
|
||||
<Appbar.Action
|
||||
icon="chevron-left"
|
||||
size={26}
|
||||
disabled={!prevChapter}
|
||||
onPress={navigateToPrevChapter}
|
||||
color="#FFFFFF"
|
||||
/>
|
||||
<Appbar.Action
|
||||
icon="chevron-right"
|
||||
size={26}
|
||||
disabled={!nextChapter}
|
||||
onPress={navigateToNextChapter}
|
||||
color="#FFFFFF"
|
||||
/>
|
||||
<Appbar.Action
|
||||
icon="dots-vertical"
|
||||
size={26}
|
||||
onPress={() => readerSheetRef.current.show()}
|
||||
color="#FFFFFF"
|
||||
/>
|
||||
</Appbar.Header>
|
||||
);
|
||||
};
|
||||
|
||||
export default ChapterAppbar;
|
||||
@@ -77,6 +77,7 @@ const HistoryCard = ({ item, deleteHistoryAction, navigation, theme }) => {
|
||||
novelUrl: item.novelUrl,
|
||||
novelId: item.novelId,
|
||||
chapterName: item.chapterName,
|
||||
novelName: item.novelName,
|
||||
})
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -13,11 +13,11 @@ const GridSizeModal = ({
|
||||
theme,
|
||||
}) => {
|
||||
const gridSizes = {
|
||||
1: "XS",
|
||||
2: "S",
|
||||
5: "XS",
|
||||
4: "S",
|
||||
3: "M",
|
||||
4: "L",
|
||||
5: "XL",
|
||||
2: "L",
|
||||
1: "XL",
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -81,6 +81,7 @@ const Novel = ({ route, navigation }) => {
|
||||
position={position}
|
||||
downloading={downloading}
|
||||
selected={selected}
|
||||
novelName={novelName}
|
||||
setSelected={setSelected}
|
||||
chapterActionsSheetRef={chapterActionsSheetRef}
|
||||
/>
|
||||
|
||||
@@ -43,6 +43,7 @@ const ChapterActionsSheet = ({
|
||||
paddingBottom: 8,
|
||||
fontSize: 16,
|
||||
}}
|
||||
numberOfLines={1}
|
||||
>
|
||||
{selected?.chapterName}
|
||||
</Text>
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
|
||||
const ChapterItem = ({
|
||||
novelUrl,
|
||||
novelName,
|
||||
chapter,
|
||||
sourceId,
|
||||
dispatch,
|
||||
@@ -31,9 +32,7 @@ const ChapterItem = ({
|
||||
chapterId: chapter.chapterId,
|
||||
chapterUrl: chapter.chapterUrl,
|
||||
chapterName: chapter.chapterName,
|
||||
position: !chapter.read
|
||||
? position && position[chapter.chapterId]
|
||||
: 0,
|
||||
novelName: novelName,
|
||||
});
|
||||
|
||||
const displayDownloadButton = () => {
|
||||
@@ -179,7 +178,7 @@ const ChapterItem = ({
|
||||
<Text
|
||||
style={[
|
||||
{
|
||||
color: theme.textColorSecondary,
|
||||
color: theme.textColorHint,
|
||||
fontSize: 12,
|
||||
marginLeft: 0,
|
||||
},
|
||||
|
||||
@@ -23,6 +23,7 @@ const ReadButton = ({ navigation, novel, chapters, theme, lastRead }) => {
|
||||
novelId: lastRead.novelId,
|
||||
sourceId: novel.sourceId,
|
||||
chapterName: lastRead.chapterName,
|
||||
novelName: novel.novelName,
|
||||
});
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -47,6 +47,7 @@ const Updates = ({ navigation }) => {
|
||||
novelUrl: item.novelUrl,
|
||||
chapterName: item.chapterName,
|
||||
novelId: item.novelId,
|
||||
novelName: item.novelName,
|
||||
});
|
||||
|
||||
const renderItem = ({ item }) => (
|
||||
|
||||
@@ -18,20 +18,24 @@ const UpdateCard = ({ item, theme, onPress }) => {
|
||||
/>
|
||||
<View style={styles.chapterDetails}>
|
||||
<Text
|
||||
style={{
|
||||
color: theme.textColorPrimary,
|
||||
fontSize: 14,
|
||||
}}
|
||||
style={[
|
||||
{ color: theme.textColorPrimary, fontSize: 14 },
|
||||
item.read && {
|
||||
color: theme.textColorHint,
|
||||
},
|
||||
]}
|
||||
numberOfLines={1}
|
||||
>
|
||||
{item.novelName}
|
||||
</Text>
|
||||
<View style={{ flexDirection: "row" }}>
|
||||
<Text
|
||||
style={{
|
||||
color: theme.textColorPrimary,
|
||||
fontSize: 12,
|
||||
}}
|
||||
style={[
|
||||
{ color: theme.textColorPrimary, fontSize: 12 },
|
||||
item.read && {
|
||||
color: theme.textColorHint,
|
||||
},
|
||||
]}
|
||||
numberOfLines={1}
|
||||
>
|
||||
{`${item.chapterName} · ${moment(
|
||||
|
||||
@@ -12,7 +12,6 @@ export const fetchSources = async () => {
|
||||
export const fetchNovel = async (sourceId, novelUrl) => {
|
||||
const url = `https://lnreader-extensions.vercel.app/api/${sourceId}/novel/${novelUrl}`;
|
||||
|
||||
console.log(url);
|
||||
let data = await fetch(url);
|
||||
let res = await data.json();
|
||||
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
import { getChapter } from "../../Database/queries/ChapterQueries";
|
||||
import { fetchChapter } from "../../Services/Source/source";
|
||||
import { SAVE_SCROLL_POSITION } from "../preferences/preference.types";
|
||||
import { CHAPTER_LOADING, GET_CHAPTER } from "./chapter.types";
|
||||
|
||||
export const getChapterAction =
|
||||
(sourceId, novelUrl, chapterUrl, chapterId) => async (dispatch) => {
|
||||
dispatch({ type: CHAPTER_LOADING });
|
||||
|
||||
/**
|
||||
* Check if chapter is downloaded.
|
||||
*/
|
||||
let chapter = await getChapter(chapterId);
|
||||
|
||||
if (!chapter) {
|
||||
/**
|
||||
* Fetch chapter from source.
|
||||
*/
|
||||
chapter = await fetchChapter(sourceId, novelUrl, chapterUrl);
|
||||
}
|
||||
|
||||
dispatch({ type: GET_CHAPTER, payload: chapter });
|
||||
};
|
||||
|
||||
export const saveScrollPosition =
|
||||
(position, percentage, chapterId, novelId) => async (dispatch) => {
|
||||
dispatch({
|
||||
type: SAVE_SCROLL_POSITION,
|
||||
payload: {
|
||||
position,
|
||||
percentage,
|
||||
chapterId,
|
||||
novelId,
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -1,21 +0,0 @@
|
||||
import { CHAPTER_LOADING, GET_CHAPTER } from "./chapter.types";
|
||||
|
||||
const initialState = {
|
||||
chapter: {},
|
||||
loading: true,
|
||||
};
|
||||
|
||||
const chapterReducer = (state = initialState, action) => {
|
||||
const { type, payload } = action;
|
||||
|
||||
switch (type) {
|
||||
case CHAPTER_LOADING:
|
||||
return { ...state, loading: true };
|
||||
case GET_CHAPTER:
|
||||
return { ...state, chapter: payload, loading: false };
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
export default chapterReducer;
|
||||
@@ -1,2 +0,0 @@
|
||||
export const GET_CHAPTER = "GET_CHAPTER";
|
||||
export const CHAPTER_LOADING = "CHAPTER_LOADING";
|
||||
@@ -0,0 +1,14 @@
|
||||
import { SAVE_SCROLL_POSITION } from "../preferences/preference.types";
|
||||
|
||||
export const saveScrollPosition =
|
||||
(position, percentage, chapterId, novelId) => async (dispatch) => {
|
||||
dispatch({
|
||||
type: SAVE_SCROLL_POSITION,
|
||||
payload: {
|
||||
position,
|
||||
percentage,
|
||||
chapterId,
|
||||
novelId,
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -11,9 +11,11 @@ export const getSourcesAction = () => async (dispatch) => {
|
||||
};
|
||||
|
||||
export const searchSourcesAction = (searchText) => async (dispatch) => {
|
||||
const res = searchText.toLowerCase();
|
||||
|
||||
dispatch({
|
||||
type: SEARCH_SOURCES,
|
||||
payload: searchText,
|
||||
payload: res,
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ const sourceReducer = (state = initialState, action) => {
|
||||
return {
|
||||
...state,
|
||||
search: state.sources.filter((source) =>
|
||||
source.sourceName.includes(payload)
|
||||
source.sourceName.toLowerCase().includes(payload)
|
||||
),
|
||||
};
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user