Compare commits

...

2 commits

3 changed files with 55 additions and 22 deletions

View file

@ -21,19 +21,8 @@ function Remote() {
export default function ComicList() { export default function ComicList() {
return ( return (
<Tab.Navigator <Tab.Navigator
screenOptions={({ navigation, route }) => { screenOptions={({ route }) => {
return { return {
headerRight: () => (
<View style={styles.padding}>
<TouchableOpacity
onPress={() => {
navigation.push("OldHome");
}}
>
<MaterialCommunityIcons name="cog" size={24} style={{ color: "black" }} />
</TouchableOpacity>
</View>
),
tabBarIcon: (({ focused, size, color }) => { tabBarIcon: (({ focused, size, color }) => {
const iconName = route.name === 'Local' const iconName = route.name === 'Local'
? (focused ? 'download' : 'download-outline') ? (focused ? 'download' : 'download-outline')
@ -48,9 +37,3 @@ export default function ComicList() {
</Tab.Navigator> </Tab.Navigator>
); );
} }
const styles = StyleSheet.create({
padding: {
paddingEnd: 16,
},
});

View file

@ -1,5 +1,5 @@
import { FC } from "react" import { FC, useEffect } from "react"
import { ActivityIndicator, FlatList, StyleSheet, Text, View } from "react-native" import { ActivityIndicator, FlatList, StyleSheet, Text, TouchableOpacity, View } from "react-native"
import Touchable from "../../components/Touchable"; import Touchable from "../../components/Touchable";
import ComicCard from '../../components/ComicCard'; import ComicCard from '../../components/ComicCard';
import { ComicMetadata, useLocalComics } from "../../provider" import { ComicMetadata, useLocalComics } from "../../provider"
@ -9,6 +9,8 @@ import { TabParamList } from "../comiclist";
import { NativeStackNavigationProp } from "@react-navigation/native-stack"; import { NativeStackNavigationProp } from "@react-navigation/native-stack";
import { RootStackParamList } from "../../../App"; import { RootStackParamList } from "../../../App";
import { LocalComicId } from "../../provider/local"; import { LocalComicId } from "../../provider/local";
import { useQueryClient } from "react-query";
import { MaterialCommunityIcons, MaterialIcons } from "@expo/vector-icons";
export type ComicListNavigationProp = CompositeNavigationProp< export type ComicListNavigationProp = CompositeNavigationProp<
BottomTabNavigationProp<TabParamList, 'Local'>, BottomTabNavigationProp<TabParamList, 'Local'>,
@ -24,9 +26,36 @@ const Comic: FC<ComicMetadata & { onClick: () => void }> = (props) => {
} }
export default function LocalComicList() { export default function LocalComicList() {
const client = useQueryClient();
const navigator = useNavigation<ComicListNavigationProp>();
const { data, error, isLoading } = useLocalComics(); const { data, error, isLoading } = useLocalComics();
const navigation = useNavigation<ComicListNavigationProp>(); const navigation = useNavigation<ComicListNavigationProp>();
useEffect(() => {
navigator.setOptions({
headerRight: () => <View style={styles.iconRow}>
<View style={styles.padding}>
<TouchableOpacity
onPress={() => {
navigation.push("OldHome");
}}
>
<MaterialCommunityIcons name="cog" size={24} style={{ color: "black" }} />
</TouchableOpacity>
</View>
<View style={styles.padding}>
<TouchableOpacity
onPress={() => {
client.invalidateQueries('localComics');
}}
>
<MaterialCommunityIcons name="refresh" size={24} style={{ color: "black" }} />
</TouchableOpacity>
</View>
</View>
});
}, [client]);
if (isLoading) return <ActivityIndicator />; if (isLoading) return <ActivityIndicator />;
if (error) return <Text>Failed to load comic: {error.toString()}</Text>; if (error) return <Text>Failed to load comic: {error.toString()}</Text>;
if (!data) return <Text>Whoops! We couldn't find that comic :/</Text>; if (!data) return <Text>Whoops! We couldn't find that comic :/</Text>;
@ -38,11 +67,32 @@ export default function LocalComicList() {
}); });
} }
if (data.length === 0) {
return <View style={styles.center}>
<MaterialIcons name='sentiment-dissatisfied' size={32} color='#666' />
<Text style={styles.noComicsText}>You don't have any comics downloaded</Text>
</View>
}
return <FlatList data={data} renderItem={({ item }) => <Comic onClick={() => openComic(item.id)} {...item} />} keyExtractor={item => item.id} /> return <FlatList data={data} renderItem={({ item }) => <Comic onClick={() => openComic(item.id)} {...item} />} keyExtractor={item => item.id} />
} }
const styles = StyleSheet.create({ const styles = StyleSheet.create({
center: {
flex: 1,
justifyContent: "center",
alignItems: "center",
},
noComicsText: {
color: '#666',
},
comic: { comic: {
padding: 8, padding: 8,
}, },
iconRow: {
flexDirection: 'row',
},
padding: {
paddingEnd: 16,
},
}); });

View file

@ -40,7 +40,7 @@ async function localJson<T>(comicId: string, path: string): Promise<T | null> {
if (parsed === null) return null; if (parsed === null) return null;
const [providerKey, id] = parsed; const [providerKey, id] = parsed;
const pth = dataPath(`comics/${providerKey}/${id}/${path}`); const pth = dataPath(`comics/${providerKey}/${id}/${path}`);
if (!pathExists(pth)) return null; if (!await pathExists(pth)) return null;
return JSON.parse(await FileSystem.readAsStringAsync(pth)); return JSON.parse(await FileSystem.readAsStringAsync(pth));
} }
@ -48,7 +48,7 @@ async function localJson<T>(comicId: string, path: string): Promise<T | null> {
const localProvider: LocalProvider = { const localProvider: LocalProvider = {
async listComics() { async listComics() {
const directory = dataPath('comics/'); const directory = dataPath('comics/');
if (!pathExists(directory)) return []; if (!await pathExists(directory)) return [];
const providers = await FileSystem.readDirectoryAsync(directory) as NonLocalProviderKey[]; const providers = await FileSystem.readDirectoryAsync(directory) as NonLocalProviderKey[];
const comics: LocalComicMetadata[] = []; const comics: LocalComicMetadata[] = [];
for (const provider of providers) { for (const provider of providers) {