Better bottom navigation (#1335)
* Better bottom navigation * Add double press actions to the rest of the tabs * Fix history screen double press * Fix lint error * Fix more lint errors 😢 * 😢 * memo
This commit is contained in:
@@ -7,10 +7,10 @@ import { coverPlaceholderColor } from '../theme/colors';
|
||||
import color from 'color';
|
||||
import { ThemeColors } from '@theme/types';
|
||||
import { NovelItem } from '@plugins/types';
|
||||
import { LibraryNovelInfo } from '@database/types';
|
||||
import { NovelInfo } from '@database/types';
|
||||
|
||||
interface ListViewProps {
|
||||
item: NovelItem | LibraryNovelInfo;
|
||||
item: NovelItem | NovelInfo;
|
||||
downloadBadge?: React.ReactNode;
|
||||
unreadBadge?: React.ReactNode;
|
||||
inLibraryBadge?: React.ReactNode;
|
||||
|
||||
@@ -53,7 +53,7 @@ interface INovelCover<TNovel> {
|
||||
libraryStatus: boolean;
|
||||
theme: ThemeColors;
|
||||
isSelected: boolean;
|
||||
addSkeletonLoading: boolean;
|
||||
addSkeletonLoading?: boolean;
|
||||
onLongPress: (item: TNovel) => void;
|
||||
selectedNovelIds: number[];
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { lazy } from 'react';
|
||||
import React, { lazy, useMemo } from 'react';
|
||||
import { createMaterialBottomTabNavigator } from 'react-native-paper/react-navigation';
|
||||
|
||||
import Library from '../screens/library/LibraryScreen';
|
||||
@@ -8,7 +8,7 @@ const Browse = lazy(() => import('../screens/browse/BrowseScreen'));
|
||||
const More = lazy(() => import('../screens/more/MoreScreen'));
|
||||
|
||||
import { getString } from '@strings/translations';
|
||||
import { useAppSettings, useTheme } from '@hooks/persisted';
|
||||
import { useAppSettings, usePlugins, useTheme } from '@hooks/persisted';
|
||||
import { BottomNavigatorParamList } from './types';
|
||||
|
||||
const Tab = createMaterialBottomTabNavigator<BottomNavigatorParamList>();
|
||||
@@ -22,6 +22,12 @@ const BottomNavigator = () => {
|
||||
showLabelsInNav = false,
|
||||
} = useAppSettings();
|
||||
|
||||
const { filteredInstalledPlugins } = usePlugins();
|
||||
const pluginsWithUpdate = useMemo(
|
||||
() => filteredInstalledPlugins.filter(p => p.hasUpdate).length,
|
||||
[filteredInstalledPlugins],
|
||||
);
|
||||
|
||||
return (
|
||||
<Tab.Navigator
|
||||
barStyle={{ backgroundColor: theme.surface2 }}
|
||||
@@ -63,6 +69,9 @@ const BottomNavigator = () => {
|
||||
options={{
|
||||
title: getString('browse'),
|
||||
tabBarIcon: 'compass-outline',
|
||||
tabBarBadge: pluginsWithUpdate
|
||||
? pluginsWithUpdate.toString()
|
||||
: undefined,
|
||||
}}
|
||||
/>
|
||||
<Tab.Screen
|
||||
|
||||
@@ -116,6 +116,7 @@ const MainNavigator = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
// @ts-ignore
|
||||
<NavigationContainer theme={{ colors: theme, dark: theme.isDark }}>
|
||||
{isNewVersion && <NewUpdateDialog newVersion={latestRelease} />}
|
||||
<Stack.Navigator screenOptions={{ headerShown: false }}>
|
||||
|
||||
@@ -53,6 +53,11 @@ export type HistoryScreenProps = CompositeScreenProps<
|
||||
StackScreenProps<RootStackParamList>
|
||||
>;
|
||||
|
||||
export type UpdateScreenProps = CompositeScreenProps<
|
||||
MaterialBottomTabScreenProps<BottomNavigatorParamList, 'Updates'>,
|
||||
StackScreenProps<RootStackParamList>
|
||||
>;
|
||||
|
||||
export type BrowseScreenProps = CompositeScreenProps<
|
||||
MaterialBottomTabScreenProps<BottomNavigatorParamList, 'Browse'>,
|
||||
StackScreenProps<RootStackParamList>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Text } from 'react-native';
|
||||
import React, { useMemo } from 'react';
|
||||
import React, { useEffect, useMemo } from 'react';
|
||||
import { TabView, TabBar } from 'react-native-tab-view';
|
||||
|
||||
import { useSearch } from '@hooks';
|
||||
@@ -38,6 +38,18 @@ const BrowseScreen = ({ navigation }: BrowseScreenProps) => {
|
||||
[],
|
||||
);
|
||||
|
||||
useEffect(
|
||||
() =>
|
||||
navigation.addListener('tabPress', e => {
|
||||
if (navigation.isFocused()) {
|
||||
e.preventDefault();
|
||||
|
||||
navigation.navigate('GlobalSearchScreen', {});
|
||||
}
|
||||
}),
|
||||
[navigation],
|
||||
);
|
||||
|
||||
const [index, setIndex] = React.useState(0);
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState } from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { StyleSheet, SectionList, Text } from 'react-native';
|
||||
import dayjs from 'dayjs';
|
||||
import { Portal } from 'react-native-paper';
|
||||
@@ -70,6 +70,23 @@ const HistoryScreen = () => {
|
||||
setFalse: closeClearHistoryDialog,
|
||||
} = useBoolean();
|
||||
|
||||
useEffect(
|
||||
() =>
|
||||
navigation.addListener('tabPress', e => {
|
||||
let lastNovel = history[0];
|
||||
if (navigation.isFocused() && lastNovel) {
|
||||
e.preventDefault();
|
||||
|
||||
navigation.navigate('Novel', {
|
||||
name: lastNovel.novelName,
|
||||
path: lastNovel.novelPath,
|
||||
pluginId: lastNovel.pluginId,
|
||||
});
|
||||
}
|
||||
}),
|
||||
[navigation, history],
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<SearchbarV2
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useRef, useState } from 'react';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { StyleSheet, Text, useWindowDimensions, View } from 'react-native';
|
||||
import { BottomSheetModal } from '@gorhom/bottom-sheet';
|
||||
import {
|
||||
@@ -85,6 +85,18 @@ const LibraryScreen = ({ navigation }: LibraryScreenProps) => {
|
||||
|
||||
const bottomSheetRef = useRef<BottomSheetModal | null>(null);
|
||||
|
||||
useEffect(
|
||||
() =>
|
||||
navigation.addListener('tabPress', e => {
|
||||
if (navigation.isFocused()) {
|
||||
e.preventDefault();
|
||||
|
||||
bottomSheetRef.current?.present?.();
|
||||
}
|
||||
}),
|
||||
[navigation],
|
||||
);
|
||||
|
||||
const renderTabBar = (
|
||||
props: SceneRendererProps & { navigationState: State },
|
||||
) =>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from 'react';
|
||||
import React, { useEffect } from 'react';
|
||||
import { StyleSheet, View, Pressable, Text, ScrollView } from 'react-native';
|
||||
import { getString } from '@strings/translations';
|
||||
|
||||
@@ -28,6 +28,23 @@ const MoreScreen = ({ navigation }: MoreStackScreenProps) => {
|
||||
const enableIncognitoMode = () =>
|
||||
setLibrarySettings({ incognitoMode: !incognitoMode });
|
||||
|
||||
useEffect(
|
||||
() =>
|
||||
navigation.addListener('tabPress', e => {
|
||||
if (navigation.isFocused()) {
|
||||
e.preventDefault();
|
||||
|
||||
navigation.navigate('MoreStack', {
|
||||
screen: 'SettingsStack',
|
||||
params: {
|
||||
screen: 'Settings',
|
||||
},
|
||||
});
|
||||
}
|
||||
}),
|
||||
[navigation],
|
||||
);
|
||||
|
||||
return (
|
||||
<ScrollView>
|
||||
<MoreHeader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useCallback } from 'react';
|
||||
import React, { useCallback, useEffect } from 'react';
|
||||
import dayjs from 'dayjs';
|
||||
import { RefreshControl, SectionList, StyleSheet, Text } from 'react-native';
|
||||
|
||||
@@ -19,8 +19,9 @@ import { useFocusEffect } from '@react-navigation/native';
|
||||
import { deleteChapter } from '@database/queries/ChapterQueries';
|
||||
import { showToast } from '@utils/showToast';
|
||||
import ServiceManager from '@services/ServiceManager';
|
||||
import { UpdateScreenProps } from '@navigators/types';
|
||||
|
||||
const UpdatesScreen = () => {
|
||||
const UpdatesScreen = ({ navigation }: UpdateScreenProps) => {
|
||||
const theme = useTheme();
|
||||
const {
|
||||
isLoading,
|
||||
@@ -76,6 +77,20 @@ const UpdatesScreen = () => {
|
||||
}, [downloadQueue]),
|
||||
);
|
||||
|
||||
useEffect(
|
||||
() =>
|
||||
navigation.addListener('tabPress', e => {
|
||||
if (navigation.isFocused()) {
|
||||
e.preventDefault();
|
||||
|
||||
navigation.navigate('MoreStack', {
|
||||
screen: 'Downloads',
|
||||
});
|
||||
}
|
||||
}),
|
||||
[navigation],
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<SearchbarV2
|
||||
|
||||
Reference in New Issue
Block a user