diff --git a/package-lock.json b/package-lock.json index 920242dcc..53ec1ed30 100644 --- a/package-lock.json +++ b/package-lock.json @@ -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", diff --git a/package.json b/package.json index 41ecf58f0..878fc6f82 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/src/components/Camera/CameraOptionsModal.js b/src/components/Camera/CameraOptionsModal.js new file mode 100644 index 000000000..e54a1f18b --- /dev/null +++ b/src/components/Camera/CameraOptionsModal.js @@ -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 => ( + + take photo with camera + upload photo from gallery + record a sound + submit without evidence + +); + +export default CameraOptionsModal; diff --git a/src/components/Observations/ObsListRightHeader.js b/src/components/Observations/ObsListRightHeader.js new file mode 100644 index 000000000..8baada576 --- /dev/null +++ b/src/components/Observations/ObsListRightHeader.js @@ -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 => ( + console.log( "navigate to messages" )} style={viewStyles.messages}> + messages + +); + +export default ObsListRightHeader; diff --git a/src/components/SharedComponents/Footer.js b/src/components/SharedComponents/Footer.js index a0cb95ae2..480d4f3db 100644 --- a/src/components/SharedComponents/Footer.js +++ b/src/components/SharedComponents/Footer.js @@ -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 ( - - - menu - - - explore - - - camera - - - obs list - - - notifications - - + <> + } + /> + + + menu + + + explore + + + camera + + + obs list + + + notifications + + + ); }; diff --git a/src/components/SharedComponents/Modal.js b/src/components/SharedComponents/Modal.js new file mode 100644 index 000000000..490f23fd3 --- /dev/null +++ b/src/components/SharedComponents/Modal.js @@ -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 => ( + + {modal} + +); + +export default Modal; diff --git a/src/navigation/drawerNavigation.js b/src/navigation/drawerNavigation.js index 481469ef1..dd7a0b19b 100644 --- a/src/navigation/drawerNavigation.js +++ b/src/navigation/drawerNavigation.js @@ -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 => ( - + ( { + headerRight: ( ) => + } )} + /> diff --git a/src/styles/observations/obsListRightHeader.js b/src/styles/observations/obsListRightHeader.js new file mode 100644 index 000000000..478ae633a --- /dev/null +++ b/src/styles/observations/obsListRightHeader.js @@ -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 +}; diff --git a/src/styles/sharedComponents/modal.js b/src/styles/sharedComponents/modal.js new file mode 100644 index 000000000..83af92734 --- /dev/null +++ b/src/styles/sharedComponents/modal.js @@ -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 +};