mirror of
https://github.com/inaturalist/iNaturalistReactNative.git
synced 2025-12-23 22:18:36 -05:00
Add react native modal for camera navigation; add messages nav to obs list header
This commit is contained in:
39
package-lock.json
generated
39
package-lock.json
generated
@@ -16,6 +16,7 @@
|
||||
"react-native": "0.65.1",
|
||||
"react-native-gesture-handler": "^1.10.3",
|
||||
"react-native-maps": "^0.29.3",
|
||||
"react-native-modal": "^13.0.0",
|
||||
"react-native-reanimated": "^2.2.2",
|
||||
"react-native-safe-area-context": "^3.3.2",
|
||||
"react-native-screens": "^3.8.0",
|
||||
@@ -12643,6 +12644,14 @@
|
||||
"react-native": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/react-native-animatable": {
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/react-native-animatable/-/react-native-animatable-1.3.3.tgz",
|
||||
"integrity": "sha512-2ckIxZQAsvWn25Ho+DK3d1mXIgj7tITkrS4pYDvx96WyOttSvzzFeQnM2od0+FUMzILbdHDsDEqZvnz1DYNQ1w==",
|
||||
"dependencies": {
|
||||
"prop-types": "^15.7.2"
|
||||
}
|
||||
},
|
||||
"node_modules/react-native-clean-project": {
|
||||
"version": "3.6.7",
|
||||
"resolved": "https://registry.npmjs.org/react-native-clean-project/-/react-native-clean-project-3.6.7.tgz",
|
||||
@@ -12691,6 +12700,19 @@
|
||||
"react-native-web": "^0.13"
|
||||
}
|
||||
},
|
||||
"node_modules/react-native-modal": {
|
||||
"version": "13.0.0",
|
||||
"resolved": "https://registry.npmjs.org/react-native-modal/-/react-native-modal-13.0.0.tgz",
|
||||
"integrity": "sha512-k6r9T31mc7HIDFj1V53ceAAN1dwc8052c4JLtDVEmEQ19Bbq9yiLXoDsQuNb+hB8A+2tVOXmo5Gq4IQfb11upw==",
|
||||
"dependencies": {
|
||||
"prop-types": "^15.6.2",
|
||||
"react-native-animatable": "1.3.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "*",
|
||||
"react-native": ">=0.65.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-native-reanimated": {
|
||||
"version": "2.2.3",
|
||||
"resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-2.2.3.tgz",
|
||||
@@ -25287,6 +25309,14 @@
|
||||
"react-test-renderer": "^17.0.1"
|
||||
}
|
||||
},
|
||||
"react-native-animatable": {
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/react-native-animatable/-/react-native-animatable-1.3.3.tgz",
|
||||
"integrity": "sha512-2ckIxZQAsvWn25Ho+DK3d1mXIgj7tITkrS4pYDvx96WyOttSvzzFeQnM2od0+FUMzILbdHDsDEqZvnz1DYNQ1w==",
|
||||
"requires": {
|
||||
"prop-types": "^15.7.2"
|
||||
}
|
||||
},
|
||||
"react-native-clean-project": {
|
||||
"version": "3.6.7",
|
||||
"resolved": "https://registry.npmjs.org/react-native-clean-project/-/react-native-clean-project-3.6.7.tgz",
|
||||
@@ -25324,6 +25354,15 @@
|
||||
"@types/geojson": "^7946.0.7"
|
||||
}
|
||||
},
|
||||
"react-native-modal": {
|
||||
"version": "13.0.0",
|
||||
"resolved": "https://registry.npmjs.org/react-native-modal/-/react-native-modal-13.0.0.tgz",
|
||||
"integrity": "sha512-k6r9T31mc7HIDFj1V53ceAAN1dwc8052c4JLtDVEmEQ19Bbq9yiLXoDsQuNb+hB8A+2tVOXmo5Gq4IQfb11upw==",
|
||||
"requires": {
|
||||
"prop-types": "^15.6.2",
|
||||
"react-native-animatable": "1.3.3"
|
||||
}
|
||||
},
|
||||
"react-native-reanimated": {
|
||||
"version": "2.2.3",
|
||||
"resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-2.2.3.tgz",
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
"react-native": "0.65.1",
|
||||
"react-native-gesture-handler": "^1.10.3",
|
||||
"react-native-maps": "^0.29.3",
|
||||
"react-native-modal": "^13.0.0",
|
||||
"react-native-reanimated": "^2.2.2",
|
||||
"react-native-safe-area-context": "^3.3.2",
|
||||
"react-native-screens": "^3.8.0",
|
||||
|
||||
17
src/components/Camera/CameraOptionsModal.js
Normal file
17
src/components/Camera/CameraOptionsModal.js
Normal file
@@ -0,0 +1,17 @@
|
||||
// @flow
|
||||
|
||||
import * as React from "react";
|
||||
import { Text, View } from "react-native";
|
||||
|
||||
import { textStyles } from "../../styles/sharedComponents/modal";
|
||||
|
||||
const CameraOptionsModal = ( ): React.Node => (
|
||||
<View>
|
||||
<Text style={textStyles.whiteText}>take photo with camera</Text>
|
||||
<Text style={textStyles.whiteText}>upload photo from gallery</Text>
|
||||
<Text style={textStyles.whiteText}>record a sound</Text>
|
||||
<Text style={textStyles.whiteText}>submit without evidence</Text>
|
||||
</View>
|
||||
);
|
||||
|
||||
export default CameraOptionsModal;
|
||||
14
src/components/Observations/ObsListRightHeader.js
Normal file
14
src/components/Observations/ObsListRightHeader.js
Normal file
@@ -0,0 +1,14 @@
|
||||
// @flow
|
||||
|
||||
import * as React from "react";
|
||||
import { Text, Pressable } from "react-native";
|
||||
|
||||
import { viewStyles } from "../../styles/observations/obsListRightHeader";
|
||||
|
||||
const ObsListRightHeader = ( ): React.Node => (
|
||||
<Pressable onPress={( ) => console.log( "navigate to messages" )} style={viewStyles.messages}>
|
||||
<Text>messages</Text>
|
||||
</Pressable>
|
||||
);
|
||||
|
||||
export default ObsListRightHeader;
|
||||
@@ -5,30 +5,45 @@ import { Pressable, Text, View } from "react-native";
|
||||
import { useNavigation } from "@react-navigation/native";
|
||||
|
||||
import { viewStyles } from "../../styles/sharedComponents/footer";
|
||||
import CameraOptionsModal from "../Camera/CameraOptionsModal";
|
||||
import Modal from "./Modal";
|
||||
|
||||
const Footer = ( ): React.Node => {
|
||||
const [showModal, setModal] = React.useState( false );
|
||||
|
||||
const openModal = React.useCallback( ( ) => setModal( true ), [] );
|
||||
const closeModal = React.useCallback( ( ) => setModal( false ), [] );
|
||||
|
||||
const navigation = useNavigation( );
|
||||
const toggleSideMenu = ( ) => navigation.openDrawer( );
|
||||
const navToObsList = ( ) => navigation.navigate( "my observations" );
|
||||
const navToCameraOptions = ( ) => openModal( );
|
||||
|
||||
return (
|
||||
<View style={[viewStyles.row, viewStyles.shadow]}>
|
||||
<Pressable onPress={toggleSideMenu} accessibilityRole="link">
|
||||
<Text>menu</Text>
|
||||
</Pressable>
|
||||
<Pressable accessibilityRole="link">
|
||||
<Text>explore</Text>
|
||||
</Pressable>
|
||||
<Pressable accessibilityRole="link">
|
||||
<Text>camera</Text>
|
||||
</Pressable>
|
||||
<Pressable onPress={navToObsList} accessibilityRole="link">
|
||||
<Text>obs list</Text>
|
||||
</Pressable>
|
||||
<Pressable accessibilityRole="link">
|
||||
<Text>notifications</Text>
|
||||
</Pressable>
|
||||
</View>
|
||||
<>
|
||||
<Modal
|
||||
showModal={showModal}
|
||||
closeModal={closeModal}
|
||||
modal={<CameraOptionsModal />}
|
||||
/>
|
||||
<View style={[viewStyles.row, viewStyles.shadow]}>
|
||||
<Pressable onPress={toggleSideMenu} accessibilityRole="link">
|
||||
<Text>menu</Text>
|
||||
</Pressable>
|
||||
<Pressable accessibilityRole="link">
|
||||
<Text>explore</Text>
|
||||
</Pressable>
|
||||
<Pressable onPress={navToCameraOptions} accessibilityRole="link">
|
||||
<Text>camera</Text>
|
||||
</Pressable>
|
||||
<Pressable onPress={navToObsList} accessibilityRole="link">
|
||||
<Text>obs list</Text>
|
||||
</Pressable>
|
||||
<Pressable accessibilityRole="link">
|
||||
<Text>notifications</Text>
|
||||
</Pressable>
|
||||
</View>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
29
src/components/SharedComponents/Modal.js
Normal file
29
src/components/SharedComponents/Modal.js
Normal file
@@ -0,0 +1,29 @@
|
||||
// @flow
|
||||
import * as React from "react";
|
||||
import RNModal from "react-native-modal";
|
||||
|
||||
// repurposed from Seek: https://github.com/inaturalist/SeekReactNative/blob/main/components/UIComponents/Modals/Modal.js
|
||||
|
||||
type Props = {
|
||||
showModal: boolean,
|
||||
closeModal: Function,
|
||||
modal: any
|
||||
}
|
||||
|
||||
// accessibility might not work on Android because of backdrop
|
||||
// https://github.com/react-native-modal/react-native-modal/issues/525
|
||||
|
||||
const Modal = ( { showModal, closeModal, modal }: Props ): React.Node => (
|
||||
<RNModal
|
||||
isVisible={showModal}
|
||||
onBackdropPress={closeModal}
|
||||
onSwipeComplete={closeModal}
|
||||
swipeDirection="down"
|
||||
useNativeDriverForBackdrop
|
||||
useNativeDriver
|
||||
>
|
||||
{modal}
|
||||
</RNModal>
|
||||
);
|
||||
|
||||
export default Modal;
|
||||
@@ -5,6 +5,7 @@ import { createDrawerNavigator } from "@react-navigation/drawer";
|
||||
|
||||
import ObsList from "../components/Observations/ObsList";
|
||||
import PlaceholderComponent from "../components/PlaceholderComponent";
|
||||
import ObsListRightHeader from "../components/Observations/ObsListRightHeader";
|
||||
|
||||
// this removes the default hamburger menu from header
|
||||
const screenOptions = { headerLeft: ( ) => <></> };
|
||||
@@ -13,7 +14,13 @@ const Drawer = createDrawerNavigator();
|
||||
|
||||
const DrawerNavigator = ( ): React.Node => (
|
||||
<Drawer.Navigator screenOptions={screenOptions}>
|
||||
<Drawer.Screen name="my observations" component={ObsList} />
|
||||
<Drawer.Screen
|
||||
name="my observations"
|
||||
component={ObsList}
|
||||
options={( { navigation } ) => ( {
|
||||
headerRight: ( ) => <ObsListRightHeader />
|
||||
} )}
|
||||
/>
|
||||
<Drawer.Screen name="missions/seen nearby" component={PlaceholderComponent} />
|
||||
<Drawer.Screen name="search" component={PlaceholderComponent} />
|
||||
<Drawer.Screen name="identify" component={PlaceholderComponent} />
|
||||
|
||||
15
src/styles/observations/obsListRightHeader.js
Normal file
15
src/styles/observations/obsListRightHeader.js
Normal file
@@ -0,0 +1,15 @@
|
||||
// @flow strict-local
|
||||
|
||||
import { StyleSheet } from "react-native";
|
||||
|
||||
import type { ViewStyleProp } from "react-native/Libraries/StyleSheet/StyleSheet";
|
||||
|
||||
const viewStyles: { [string]: ViewStyleProp } = StyleSheet.create( {
|
||||
messages: {
|
||||
marginRight: 20
|
||||
}
|
||||
} );
|
||||
|
||||
export {
|
||||
viewStyles
|
||||
};
|
||||
17
src/styles/sharedComponents/modal.js
Normal file
17
src/styles/sharedComponents/modal.js
Normal file
@@ -0,0 +1,17 @@
|
||||
// @flow strict-local
|
||||
|
||||
import { StyleSheet } from "react-native";
|
||||
|
||||
import type { TextStyleProp } from "react-native/Libraries/StyleSheet/StyleSheet";
|
||||
import { colors } from "../global";
|
||||
|
||||
const textStyles: { [string]: TextStyleProp } = StyleSheet.create( {
|
||||
whiteText: {
|
||||
color: colors.white,
|
||||
marginVertical: 10
|
||||
}
|
||||
} );
|
||||
|
||||
export {
|
||||
textStyles
|
||||
};
|
||||
Reference in New Issue
Block a user