diff --git a/src/components/List.js b/src/components/List.js
index d09bc965..f356337f 100644
--- a/src/components/List.js
+++ b/src/components/List.js
@@ -72,13 +72,7 @@ const InfoItem = ({title, icon, theme}) => (
titleStyle={{color: theme.textColorSecondary, fontSize: 14}}
titleNumberOfLines={5}
left={() =>
- icon && (
-
- )
+ icon &&
}
/>
);
diff --git a/src/screens/browse/SettingsBrowseScreen.js b/src/screens/browse/SettingsBrowseScreen.js
index b69174f7..5def40cd 100644
--- a/src/screens/browse/SettingsBrowseScreen.js
+++ b/src/screens/browse/SettingsBrowseScreen.js
@@ -89,6 +89,11 @@ const BrowseSettings = ({navigation}) => {
}
/>
+
Browse
{
);
const {searchAllSources = false} = useSettings();
- const [loading, setLoading] = useState(false);
const [searchText, setSearchText] = useState(novelName);
const [searchResults, setSearchResults] = useState([]);
const [progress, setProgress] = useState(0);
@@ -51,7 +45,6 @@ const GlobalSearch = ({route, navigation}) => {
if (novelName) {
onSubmitEditing();
}
-
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
@@ -65,47 +58,51 @@ const GlobalSearch = ({route, navigation}) => {
const onChangeText = text => setSearchText(text);
const onSubmitEditing = async () => {
- setSearchResults([]);
setProgress(0);
let globalSearchSources = searchAllSources ? sources : pinnedSources;
- for (let i = 0; i < globalSearchSources.length; i++) {
- if (isMounted.current === false) {
- break;
+ setSearchResults(
+ globalSearchSources.map(item => ({
+ sourceId: item.sourceId,
+ sourceName: item.sourceName,
+ lang: item.lang,
+ loading: true,
+ novels: [],
+ error: null,
+ })),
+ );
+
+ globalSearchSources.map(async item => {
+ if (isMounted.current === true) {
+ try {
+ const source = getSource(item.sourceId);
+ const data = await source.searchNovels(encodeURI(searchText));
+
+ setSearchResults(prevState =>
+ prevState.map(sourceItem =>
+ sourceItem.sourceId === item.sourceId
+ ? {...sourceItem, novels: data, loading: false}
+ : {...sourceItem},
+ ),
+ );
+ } catch (e) {
+ setSearchResults(prevState =>
+ prevState.map(sourceItem =>
+ sourceItem.sourceId === item.sourceId
+ ? {
+ ...sourceItem,
+ loading: false,
+ error: e.message,
+ }
+ : sourceItem,
+ ),
+ );
+ }
+
+ setProgress(before => before + 1 / globalSearchSources.length);
}
-
- try {
- setLoading(true);
-
- const source = getSource(globalSearchSources[i].sourceId);
- const data = await source.searchNovels(encodeURI(searchText));
-
- setSearchResults(before => [
- ...before,
- {
- sourceId: globalSearchSources[i].sourceId,
- sourceName: globalSearchSources[i].sourceName,
- lang: globalSearchSources[i].lang,
- novels: data,
- },
- ]);
- setLoading(false);
- } catch (error) {
- showToast(globalSearchSources[i].sourceName + ': ' + error.message);
- setSearchResults(before => [
- ...before,
- {
- sourceId: globalSearchSources[i].sourceId,
- sourceName: globalSearchSources[i].sourceName,
- lang: globalSearchSources[i].lang,
- novels: [],
- },
- ]);
- setLoading(false);
- }
- setProgress(before => before + 1 / globalSearchSources.length);
- }
+ });
};
const renderItem = ({item}) => (
@@ -133,42 +130,22 @@ const GlobalSearch = ({route, navigation}) => {
)}
item.sourceId.toString()}
renderItem={renderItem}
extraData={pinned}
ListEmptyComponent={
- <>
- {!loading && (
-
- )}
- >
- }
- ListFooterComponent={
- loading && (
-
-
-
- )
+
}
/>
@@ -176,5 +153,3 @@ const GlobalSearch = ({route, navigation}) => {
};
export default GlobalSearch;
-
-// const styles = StyleSheet.create({});
diff --git a/src/screens/browse/globalsearch/GlobalSearchNovelCover.js b/src/screens/browse/globalsearch/GlobalSearchNovelCover.js
index 5920bf41..4b7ef452 100644
--- a/src/screens/browse/globalsearch/GlobalSearchNovelCover.js
+++ b/src/screens/browse/globalsearch/GlobalSearchNovelCover.js
@@ -1,5 +1,6 @@
import React from 'react';
import {StyleSheet, View, Text, Image, Pressable} from 'react-native';
+import {defaultCoverUri} from '../../../sources/helpers/constants';
const GlobalSearchNovelCover = ({
novel,
@@ -10,32 +11,28 @@ const GlobalSearchNovelCover = ({
}) => {
const {novelName, novelCover} = novel;
+ const uri =
+ novelCover && !novelCover.startsWith('/') ? novelCover : defaultCoverUri;
+
return (
-
+
- <>
-
-
- {novelName}
-
- >
+
+
+ {novelName}
+
);
@@ -44,10 +41,16 @@ const GlobalSearchNovelCover = ({
export default GlobalSearchNovelCover;
const styles = StyleSheet.create({
- novelContainer: {
+ container: {
+ flex: 1,
+ borderRadius: 6,
+ overflow: 'hidden',
+ },
+ pressable: {
paddingHorizontal: 5,
paddingVertical: 4,
borderRadius: 4,
+ flex: 1,
},
novelCover: {
height: 150,
diff --git a/src/screens/browse/globalsearch/GlobalSearchNovelList.js b/src/screens/browse/globalsearch/GlobalSearchNovelList.js
index 4b8e6bcf..d6f6e013 100644
--- a/src/screens/browse/globalsearch/GlobalSearchNovelList.js
+++ b/src/screens/browse/globalsearch/GlobalSearchNovelList.js
@@ -29,7 +29,7 @@ const GlobalSearchNovelList = ({data, theme, library, navigation}) => {
contentContainerStyle={styles.listContainer}
horizontal={true}
data={data}
- keyExtractor={item => item.novelUrl}
+ keyExtractor={item => item.sourceId + item.novelUrl}
renderItem={renderItem}
ListEmptyComponent={ListEmptyComponent}
/>
diff --git a/src/screens/browse/globalsearch/GlobalSearchSourceItem.js b/src/screens/browse/globalsearch/GlobalSearchSourceItem.js
index e53c7660..6f021e08 100644
--- a/src/screens/browse/globalsearch/GlobalSearchSourceItem.js
+++ b/src/screens/browse/globalsearch/GlobalSearchSourceItem.js
@@ -1,10 +1,14 @@
import React from 'react';
-import {StyleSheet, View, Text} from 'react-native';
+import {StyleSheet, View, Text, ActivityIndicator} from 'react-native';
import GlobalSearchNovelList from './GlobalSearchNovelList';
const GlobalSearchSourceItem = ({source, library, theme, navigation}) => {
- const {sourceName, lang, novels} = source;
+ const {sourceName, lang, loading, novels, error} = source;
+
+ const colorError = {
+ color: theme.statusBar === 'dark-content' ? '#B3261E' : '#F2B8B5',
+ };
return (
<>
@@ -14,12 +18,21 @@ const GlobalSearchSourceItem = ({source, library, theme, navigation}) => {
{lang}
-
+ {error ? (
+ {error}
+ ) : loading ? (
+
+ ) : (
+
+ )}
>
);
};
@@ -31,4 +44,8 @@ const styles = StyleSheet.create({
padding: 8,
paddingVertical: 16,
},
+ error: {
+ paddingHorizontal: 8,
+ paddingVertical: 16,
+ },
});
diff --git a/src/screens/browse/migration/MigrationNovelList.js b/src/screens/browse/migration/MigrationNovelList.js
index 527ff376..6bd18559 100644
--- a/src/screens/browse/migration/MigrationNovelList.js
+++ b/src/screens/browse/migration/MigrationNovelList.js
@@ -48,7 +48,7 @@ const MigrationNovelList = ({data, theme, library, navigation}) => {
contentContainerStyle={styles.flatListCont}
horizontal={true}
data={data}
- keyExtractor={item => item.novelUrl}
+ keyExtractor={item => item.sourceId + item.novelUrl}
renderItem={renderItem}
ListEmptyComponent={
{
const isMounted = React.useRef(true);
const [progress, setProgress] = useState(0);
- const [loading, setLoading] = useState(false);
const [searchResults, setSearchResults] = useState('');
const {searchAllSources = false} = useSettings();
let {
@@ -44,48 +42,52 @@ const MigrationNovels = ({navigation, route}) => {
const getSearchResults = async () => {
let migrationSources = searchAllSources ? sources : pinnedSources;
- for (let i = 0; i < migrationSources.length; i++) {
- if (isMounted.current === false) {
- break;
+
+ setSearchResults(
+ migrationSources.map(item => ({
+ sourceId: item.sourceId,
+ sourceName: item.sourceName,
+ lang: item.lang,
+ loading: true,
+ novels: [],
+ error: null,
+ })),
+ );
+
+ migrationSources.map(async item => {
+ if (isMounted.current === true) {
+ try {
+ const source = getSource(item.sourceId);
+ const data = await source.searchNovels(novelName);
+
+ setSearchResults(prevState =>
+ prevState.map(sourceItem =>
+ sourceItem.sourceId === item.sourceId
+ ? {...sourceItem, novels: data, loading: false}
+ : {...sourceItem},
+ ),
+ );
+ } catch (e) {
+ setSearchResults(prevState =>
+ prevState.map(sourceItem =>
+ sourceItem.sourceId === item.sourceId
+ ? {
+ ...sourceItem,
+ loading: false,
+ error: e.message,
+ }
+ : sourceItem,
+ ),
+ );
+ }
+
+ setProgress(before => before + 1 / migrationSources.length);
}
-
- try {
- setLoading(true);
-
- const source = getSource(migrationSources[i].sourceId);
- const data = await source.searchNovels(novelName);
-
- setSearchResults(before => [
- ...before,
- {
- sourceId: migrationSources[i].sourceId,
- sourceName: migrationSources[i].sourceName,
- sourceLanguage: migrationSources[i].lang,
- novels: data,
- },
- ]);
- setLoading(false);
- } catch (error) {
- showToast(error.message);
-
- setSearchResults(before => [
- ...before,
- {
- sourceId: migrationSources[i].sourceId,
- sourceName: migrationSources[i].sourceName,
- sourceLanguage: migrationSources[i].lang,
- novels: [],
- },
- ]);
- setLoading(false);
- }
- setProgress(before => before + 1 / migrationSources.length);
- }
+ });
};
useEffect(() => {
getSearchResults();
-
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
@@ -95,62 +97,55 @@ const MigrationNovels = ({navigation, route}) => {
};
}, []);
+ const colorError = {
+ color: theme.statusBar === 'dark-content' ? '#B3261E' : '#F2B8B5',
+ };
+
const renderItem = ({item}) => (
<>
{item.sourceName}
- {item.sourceLanguage}
+ {item.lang}
-
+ {item.error ? (
+ {item.error}
+ ) : item.loading ? (
+
+ ) : (
+
+ )}
>
);
return (
- navigation.goBack()} />
+
{progress > 0 && (
)}
item.sourceId.toString()}
renderItem={renderItem}
extraData={pinned}
ListEmptyComponent={
- <>
- {!loading && (
-
- )}
- >
- }
- ListFooterComponent={
- loading && (
-
-
-
- )
+
}
/>
@@ -159,4 +154,9 @@ const MigrationNovels = ({navigation, route}) => {
export default MigrationNovels;
-// const styles = StyleSheet.create({});
+const styles = StyleSheet.create({
+ error: {
+ paddingHorizontal: 8,
+ paddingVertical: 16,
+ },
+});