Filter sources by languages

This commit is contained in:
Rajarshee Chatterjee
2021-06-13 10:47:41 +05:30
parent 721d3842fb
commit 7773d50607
8 changed files with 275 additions and 50 deletions
+5
View File
@@ -21,6 +21,7 @@ import { githubUpdateChecker } from "../Hooks/githubUpdateChecker";
import NewUpdateDialog from "../Components/NewUpdateDialog";
import { NavigationContainer } from "@react-navigation/native";
import BrowseNovelUpdates from "../Screens/Browse/discover/BrowseNovelUpdates";
import BrowseSettings from "../Screens/Browse/BrowseSettings";
const Stack = createStackNavigator();
@@ -49,6 +50,10 @@ const MainNavigator = () => {
<Stack.Screen name="MoreStack" component={MoreStack} />
<Stack.Screen name="Extension" component={Extension} />
<Stack.Screen name="BrowseMal" component={MalTopNovels} />
<Stack.Screen
name="BrowseSettings"
component={BrowseSettings}
/>
<Stack.Screen
name="BrowseNovelUpdates"
component={BrowseNovelUpdates}
+32 -14
View File
@@ -26,15 +26,23 @@ const Browse = ({ navigation }) => {
const [searchText, setSearchText] = useState("");
// const [globalSearch, setGlobalSearch] = useState(false);
// const [searchResult, setSearchResults] = useState();
const { sources, search, loading, pinned } = useSelector(
(state) => state.sourceReducer
);
let {
sources,
search,
loading,
pinned,
filters,
showNovelUpdates,
showMyAnimeList,
} = useSelector((state) => state.sourceReducer);
const theme = useTheme();
const dispatch = useDispatch();
const isPinned = (sourceId) =>
pinned.indexOf(sourceId) === -1 ? false : true;
sources = sources.filter((source) => filters.indexOf(source.lang) === -1);
useEffect(() => {
dispatch(getSourcesAction());
}, [getSourcesAction]);
@@ -88,6 +96,10 @@ const Browse = ({ navigation }) => {
icon: "swap-vertical-variant",
onPress: () => navigation.navigate("Migration"),
},
{
icon: "cog-outline",
onPress: () => navigation.navigate("BrowseSettings"),
},
]}
/>
@@ -99,17 +111,23 @@ const Browse = ({ navigation }) => {
extraData={pinned}
ListHeaderComponent={
<View>
<Text
style={{
color: theme.textColorSecondary,
paddingHorizontal: 16,
paddingVertical: 8,
}}
>
Discover
</Text>
<NovelUpdatesCard theme={theme} />
<MalCard theme={theme} />
{(showNovelUpdates || showMyAnimeList) && (
<>
<Text
style={{
color: theme.textColorSecondary,
paddingHorizontal: 16,
paddingVertical: 8,
}}
>
Discover
</Text>
{showNovelUpdates && (
<NovelUpdatesCard theme={theme} />
)}
{showMyAnimeList && <MalCard theme={theme} />}
</>
)}
{pinned.length > 0 && (
<FlatList
contentContainerStyle={{ paddingBottom: 16 }}
+105
View File
@@ -0,0 +1,105 @@
import React, { useState } from "react";
import { FlatList, Pressable, Text, View } from "react-native";
import { Switch } from "react-native-paper";
import { useDispatch, useSelector } from "react-redux";
import { Appbar } from "../../Components/Appbar";
import { ScreenContainer } from "../../Components/Common";
import { ListSubHeader } from "../../Components/List";
import { useTheme } from "../../Hooks/reduxHooks";
import {
enableDiscover,
filterLanguage,
} from "../../redux/source/source.actions";
const BrowseSettings = ({ navigation }) => {
const theme = useTheme();
const dispatch = useDispatch();
const { filters, showNovelUpdates, showMyAnimeList } = useSelector(
(state) => state.sourceReducer
);
const languages = ["English", "Spanish"];
const renderItem = ({ item }) => {
return (
<Pressable
android_ripple={{ color: theme.rippleColor }}
style={{
padding: 16,
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
}}
onPress={() => dispatch(filterLanguage(item))}
>
<Text style={{ color: theme.textColorPrimary }}>{item}</Text>
<Switch
color={theme.colorAccent}
value={filters.indexOf(item) === -1 ? true : false}
onValueChange={() => dispatch(filterLanguage(item))}
/>
</Pressable>
);
};
return (
<ScreenContainer theme={theme}>
<Appbar onBackAction={navigation.goBack} title="Sources" />
<View>
<ListSubHeader theme={theme}>Discover</ListSubHeader>
<Pressable
android_ripple={{ color: theme.rippleColor }}
style={{
padding: 16,
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
}}
onPress={() => dispatch(enableDiscover("showNovelUpdates"))}
>
<Text style={{ color: theme.textColorPrimary }}>
Novel Updates
</Text>
<Switch
color={theme.colorAccent}
value={showNovelUpdates}
onValueChange={() =>
dispatch(enableDiscover("showNovelUpdates"))
}
/>
</Pressable>
<Pressable
android_ripple={{ color: theme.rippleColor }}
style={{
padding: 16,
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
}}
onPress={() => dispatch(enableDiscover("showMyAnimeList"))}
>
<Text style={{ color: theme.textColorPrimary }}>
MyAnimeList
</Text>
<Switch
color={theme.colorAccent}
value={showMyAnimeList}
onValueChange={() =>
dispatch(enableDiscover("showMyAnimeList"))
}
/>
</Pressable>
<ListSubHeader theme={theme}>Languages</ListSubHeader>
<FlatList
data={languages}
keyExtractor={(item) => item}
renderItem={renderItem}
/>
</View>
</ScreenContainer>
);
};
export default BrowseSettings;
@@ -0,0 +1,5 @@
import React from "react";
const NovelUpdatesBottomSheet = () => {};
export default NovelUpdatesBottomSheet;
@@ -1,7 +1,8 @@
import React from "react";
import { Dimensions, View, Text, StyleSheet } from "react-native";
import Slider from "@react-native-community/slider";
import { Dimensions, View, Text } from "react-native";
import { getDeviceOrientation } from "../../../Services/utils/helpers";
const VerticalScrollbar = ({
theme,
@@ -12,28 +13,22 @@ const VerticalScrollbar = ({
scrollViewRef,
setScrollPercentage,
}) => {
const onSlidingComplete = (value) => {
setLoading(true);
setScrollPercentage(value);
scrollViewRef.current.scrollTo({
x: 0,
y: Math.round((value * contentSize) / 100),
animated: false,
});
setLoading(false);
};
if (hide) {
return null;
} else {
} else if (getDeviceOrientation() === "potrait") {
return (
<View
style={[
{
position: "absolute",
zIndex: 2,
// top: 0,
right: -(Dimensions.get("window").width / 2) + 40,
bottom: 300,
backgroundColor: "rgba(0,0,0,0.6)",
flexDirection: "row",
justifyContent: "flex-end",
alignItems: "center",
borderRadius: 50,
marginHorizontal: 8,
transform: [{ rotate: "90deg" }],
},
]}
>
<View style={styles.verticalSliderContainer}>
<Text
style={{
color: theme.textColorPrimary,
@@ -46,27 +41,16 @@ const VerticalScrollbar = ({
<Slider
style={{
flex: 1,
// width: Dimensions.get("window").width - 100,
height: 40,
// paddingHorizontal: 8,
}}
minimumValue={0}
maximumValue={100}
step={1}
value={scrollPercentage}
onSlidingComplete={(value) => {
setLoading(true);
setScrollPercentage(value);
scrollViewRef.current.scrollTo({
x: 0,
y: Math.round((value * contentSize) / 100),
animated: false,
});
setLoading(false);
}}
onSlidingComplete={onSlidingComplete}
thumbTintColor={theme.colorAccent}
minimumTrackTintColor={theme.colorAccent}
maximumTrackTintColor="#000000"
maximumTrackTintColor={theme.textColorPrimary}
/>
<Text
style={{
@@ -79,7 +63,69 @@ const VerticalScrollbar = ({
</Text>
</View>
);
} else {
return (
<View style={styles.horizontalSliderContainer}>
<Text
style={{
color: theme.textColorPrimary,
marginLeft: 16,
}}
>
{scrollPercentage}
</Text>
<Slider
style={{
flex: 1,
height: 40,
}}
minimumValue={0}
maximumValue={100}
step={1}
value={scrollPercentage}
onSlidingComplete={onSlidingComplete}
thumbTintColor={theme.colorAccent}
minimumTrackTintColor={theme.colorAccent}
maximumTrackTintColor={theme.textColorPrimary}
/>
<Text
style={{
color: theme.textColorPrimary,
marginRight: 16,
}}
>
100
</Text>
</View>
);
}
};
export default VerticalScrollbar;
const styles = StyleSheet.create({
verticalSliderContainer: {
position: "absolute",
zIndex: 2,
right: -(Dimensions.get("window").width / 2) + 40,
bottom: 300,
backgroundColor: "rgba(0,0,0,0.7)",
flexDirection: "row",
justifyContent: "flex-end",
alignItems: "center",
borderRadius: 50,
marginHorizontal: 8,
transform: [{ rotate: "90deg" }],
},
horizontalSliderContainer: {
position: "absolute",
zIndex: 2,
bottom: 100,
backgroundColor: "rgba(0,0,0,0.7)",
flexDirection: "row",
justifyContent: "flex-end",
alignItems: "center",
borderRadius: 50,
marginHorizontal: 8,
},
});
+21 -2
View File
@@ -1,5 +1,10 @@
import { GET_SOURCES, PIN_SOURCES, SEARCH_SOURCES } from "./source.types";
import { fetchSources } from "../../Services/Source/source";
import {
ENABLE_DISCOVER,
FILTER_LANGUAGE,
GET_SOURCES,
PIN_SOURCES,
SEARCH_SOURCES,
} from "./source.types";
import { showToast } from "../../Hooks/showToast";
import { sources } from "../../sources/sources";
@@ -26,3 +31,17 @@ export const pinSourceAction = (sourceId) => async (dispatch) => {
payload: sourceId,
});
};
export const filterLanguage = (language) => async (dispatch) => {
dispatch({
type: FILTER_LANGUAGE,
payload: language,
});
};
export const enableDiscover = (key) => async (dispatch) => {
dispatch({
type: ENABLE_DISCOVER,
payload: key,
});
};
+26 -1
View File
@@ -1,10 +1,19 @@
import { GET_SOURCES, SEARCH_SOURCES, PIN_SOURCES } from "./source.types";
import {
GET_SOURCES,
SEARCH_SOURCES,
PIN_SOURCES,
FILTER_LANGUAGE,
ENABLE_DISCOVER,
} from "./source.types";
const initialState = {
sources: [],
pinnedSources: [],
search: [],
pinned: [],
filters: [],
showNovelUpdates: true,
showMyAnimeList: true,
loading: true,
};
@@ -30,6 +39,22 @@ const sourceReducer = (state = initialState, action) => {
source.sourceName.toLowerCase().includes(payload)
),
};
case FILTER_LANGUAGE:
return {
...state,
filters:
state.filters.indexOf(payload) === -1
? [...state.filters, payload]
: state.filters.filter(
(language) => language !== payload
),
};
case ENABLE_DISCOVER:
return {
...state,
[payload]: !state[payload],
};
default:
return state;
}
+2
View File
@@ -1,3 +1,5 @@
export const GET_SOURCES = "GET_SOURCES";
export const SEARCH_SOURCES = "SEARCH_SOURCES";
export const PIN_SOURCES = "PIN_SOURCES";
export const FILTER_LANGUAGE = "FILTER_LANGUAGE";
export const ENABLE_DISCOVER = "ENABLE_DISCOVER";