Files
lnreader/src/screens/source/SourceScreen.js
T
Marcin Majewski 33ceb60850 eslint quick-fix (#87)
* fix(github-check): Catch github connection errors

* fix(eslint): fixed eslint warnings and errors

Fixed every eslint warning and error that wasn't one of the following:
- react-hooks/exhaustive-deps
- no-console

Added .vscode to .gitignore
Added no-console:warn to eslintrc

* fix(gradlew): set file to runnable (chmod 755)

* remove .vscode
2021-10-15 18:42:40 +05:30

201 lines
5.0 KiB
JavaScript

import React, {useCallback, useState} from 'react';
import {StyleSheet, View, ActivityIndicator} from 'react-native';
import * as WebBrowser from 'expo-web-browser';
import {useDispatch} from 'react-redux';
import {useTheme, useLibrary, useSettings} from '../../hooks/reduxHooks';
import {setAppSettings} from '../../redux/settings/settings.actions';
import {getSource} from '../../sources/sources';
import {showToast} from '../../hooks/showToast';
import {Searchbar} from '../../components/Searchbar/Searchbar';
import {LoadingScreen} from '../../components/LoadingScreen/LoadingScreen';
import NovelCover from '../../components/NovelCover';
import NovelList from '../../components/NovelList';
import {ErrorView} from '../../components/ErrorView/ErrorView';
const Extension = ({navigation, route}) => {
const {sourceId, sourceName, url} = route.params;
const theme = useTheme();
const library = useLibrary();
const dispatch = useDispatch();
const settings = useSettings();
const {displayMode} = settings;
const [loading, setLoading] = useState(true);
const [novels, setNovels] = useState([]);
const [page, setPage] = useState(1);
const [error, setError] = useState();
const [totalPages, setTotalPages] = useState(1);
const [searchText, setSearchText] = useState('');
const incrementPage = () => setPage(prevState => prevState + 1);
const clearSearchbar = () => {
setNovels([]);
setPage(1);
setLoading(true);
setSearchText('');
};
const getNovels = useCallback(
async loadPage => {
try {
if (loadPage <= totalPages) {
const source = getSource(sourceId);
const res = await source.popularNovels(loadPage);
setNovels(prevState => [...prevState, ...res.novels]);
setTotalPages(res.totalPages);
setLoading(false);
}
} catch (e) {
setError(e.message);
showToast(e.message);
setNovels([]);
setLoading(false);
}
},
[sourceId, totalPages],
);
const getSearchResults = async () => {
try {
setLoading(true);
const source = getSource(sourceId);
const res = await source.searchNovels(searchText);
setNovels(res);
setLoading(false);
} catch (e) {
setError(e.message);
showToast(e.message);
setNovels([]);
setLoading(false);
}
};
const checkIFInLibrary = useCallback(
(id, novelUrl) =>
library.some(obj => obj.novelUrl === novelUrl && obj.sourceId === id),
[library],
);
useCallback(() => {
getNovels(page);
}, [page, getNovels]);
const getNextPage = () => {
if (!searchText) {
incrementPage();
}
};
const renderItem = ({item}) => (
<NovelCover
item={item}
onPress={() =>
navigation.navigate('Novel', {
novelName: item.novelName,
novelCover: item.novelCover,
novelUrl: item.novelUrl,
sourceId,
})
}
libraryStatus={checkIFInLibrary(item.sourceId, item.novelUrl)}
theme={theme}
/>
);
const listEmptyComponent = () => (
<ErrorView
errorName={error || 'No results found'}
actions={[
{
name: 'Retry',
onPress: () => {
getNovels();
setLoading(true);
setError();
},
icon: 'reload',
},
]}
theme={theme}
/>
);
const displayMenuIcon = () => {
const icons = {
0: 'view-module',
1: 'view-list',
2: 'view-module',
};
return icons[displayMode];
};
const getNextDisplayMode = () =>
displayMode === 0 ? 1 : displayMode === 1 ? 2 : displayMode === 2 && 0;
return (
<View style={[styles.container, {backgroundColor: theme.colorPrimaryDark}]}>
<Searchbar
theme={theme}
placeholder={`Search ${sourceName}`}
backAction="arrow-left"
onBackAction={() => navigation.goBack()}
searchText={searchText}
onChangeText={text => setSearchText(text)}
onSubmitEditing={getSearchResults}
clearSearchbar={clearSearchbar}
actions={[
{
icon: displayMenuIcon(),
onPress: () =>
dispatch(setAppSettings('displayMode', getNextDisplayMode())),
},
{
icon: 'earth',
onPress: () => WebBrowser.openBrowserAsync(url),
},
]}
/>
{loading ? (
<LoadingScreen theme={theme} />
) : (
<NovelList
data={novels}
renderItem={renderItem}
ListEmptyComponent={listEmptyComponent()}
onEndReached={getNextPage}
ListFooterComponent={
!searchText &&
page < totalPages &&
novels.length && (
<View style={{paddingVertical: 16}}>
<ActivityIndicator color={theme.colorAccent} />
</View>
)
}
/>
)}
</View>
);
};
export default Extension;
const styles = StyleSheet.create({
container: {
flex: 1,
},
contentContainer: {
flex: 1,
},
});