diff --git a/mobile/android/app/app.iml b/mobile/android/app/app.iml
index 85b3055..d5b763e 100644
--- a/mobile/android/app/app.iml
+++ b/mobile/android/app/app.iml
@@ -76,6 +76,7 @@
+
diff --git a/mobile/src/Activity/Activity.js b/mobile/src/Activity/Activity.js
index ffbfd4f..515808d 100644
--- a/mobile/src/Activity/Activity.js
+++ b/mobile/src/Activity/Activity.js
@@ -19,6 +19,7 @@ import {
BoundInput,
BoundButton,
BoundOptionStrip,
+ BoundHeader,
} from "../ui"
import { MessageModal } from "../Modal"
import autobind from "autobind-decorator"
diff --git a/mobile/src/App.js b/mobile/src/App.js
index 00cfbe3..25f634d 100644
--- a/mobile/src/App.js
+++ b/mobile/src/App.js
@@ -20,54 +20,40 @@ console.ignoredYellowBox = [
"",
]
-export const ensurePermission = (
- permission,
- neverAskKeyName,
+export const ensurePermissions = (
+ permissions,
rationale,
onSuccess,
onError
) => {
if (Platform.OS === "ios") {
if (onSuccess) {
- onSuccess()
+ onSuccess(
+ permissions.reduce(
+ (dict, permission) =>
+ (dict[permission] = PermissionsAndroid.RESULTS.GRANTED),
+ {}
+ )
+ )
}
return
}
- PermissionsAndroid.check(permission)
- .then((flag) => {
- if (flag) {
- if (onSuccess) {
- onSuccess()
- }
- return
- }
- return AsyncStorage.getItem(neverAskKeyName)
- })
- .then((value) => {
- if (value === "YES") {
- return
- } else {
- return PermissionsAndroid.request(permission, rationale)
- }
- })
- .then((result) => {
- if (result === PermissionsAndroid.RESULTS.GRANTED) {
- if (onSuccess) {
- onSuccess()
- }
- return
+ PermissionsAndroid.requestMultiple(permissions, rationale)
+ .then((results) => {
+ if (
+ !Object.values(results).every(
+ (grant) => grant === PermissionsAndroid.RESULTS.GRANTED
+ )
+ ) {
+ return Promise.reject()
}
- if (result === PermissionsAndroid.RESULTS.NEVER_ASK_AGAIN) {
- AsyncStorage.setItem(neverAskKeyName, "YES")
- }
-
- if (onError) {
- onError()
+ if (onSuccess) {
+ onSuccess(results)
}
})
- .catch((err) => {
+ .catch((error) => {
if (onError) {
onError()
}
diff --git a/mobile/src/Auth/DefaultRoute.js b/mobile/src/Auth/DefaultRoute.js
index 43027b5..9e21135 100644
--- a/mobile/src/Auth/DefaultRoute.js
+++ b/mobile/src/Auth/DefaultRoute.js
@@ -3,5 +3,5 @@ import { Route, Redirect } from "react-router-native"
export const DefaultRoute = () => {
// NOTE: When working on the app, change this to the page you are working on
- return } />
+ return } />
}
diff --git a/mobile/src/Home/Home.js b/mobile/src/Home/Home.js
index 33ef908..1b44c6a 100644
--- a/mobile/src/Home/Home.js
+++ b/mobile/src/Home/Home.js
@@ -9,17 +9,19 @@ import {
TouchableOpacity,
TouchableHighlight,
PermissionsAndroid,
- AsyncStorage,
+ Platform,
} from "react-native"
import MapView, { Marker } from "react-native-maps"
import { Icon, Header } from "../ui"
+import { MessageModal } from "../Modal"
import { api } from "../API"
import autobind from "autobind-decorator"
import { ifIphoneX } from "react-native-iphone-x-helper"
import { workItemTypeText, pad, regionContainingPoints } from "../util"
-import { ensurePermission } from "../App"
+import { ensurePermissions } from "../App"
import { versionInfo } from "../version"
import { minGPSAccuracy } from "../config"
+import KeyboardSpacer from "react-native-keyboard-spacer"
import pinImage from "./images/pin.png"
const neverAskForLocationPermissionKeyName = "NeverAskForLocationPermission"
@@ -38,38 +40,50 @@ export class Home extends React.Component {
longitudeDelta: 0.0922,
},
positionInfo: null,
- allowCameraAccess: false,
+ disableARViewer: true,
}
- ensurePermission(
- PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
- neverAskForLocationPermissionKeyName,
+ ensurePermissions(
+ [
+ PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
+ PermissionsAndroid.PERMISSIONS.CAMERA,
+ ],
{
title: versionInfo.title,
message:
- "This app needs access to your location so that " +
- "you can find and access the geo located items.",
+ "This app needs these permissions so that you can " +
+ "find, access and photograph geo located items.",
},
- () => {
- this.watchId = navigator.geolocation.watchPosition(
- this.handlePositionChange,
- null,
- { distanceFilter: 10 }
- )
- }
- )
+ (results) => {
+ if (
+ results[PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION] ===
+ PermissionsAndroid.RESULTS.GRANTED
+ ) {
+ this.watchId = navigator.geolocation.watchPosition(
+ this.handlePositionChange,
+ null,
+ { distanceFilter: 10 }
+ )
+ }
- ensurePermission(
- PermissionsAndroid.PERMISSIONS.CAMERA,
- neverAskForCameraKeyName,
- {
- title: versionInfo.title,
- message:
- "This app needs access to your camera so that " +
- "you can view AR items.",
+ if (
+ results[PermissionsAndroid.PERMISSIONS.CAMERA] ===
+ PermissionsAndroid.RESULTS.GRANTED
+ ) {
+ this.setState({ disableARViewer: false })
+ }
},
() => {
- this.setState({ allowCameraAccess: true })
+ this.setState({
+ messageModal: {
+ icon: "hand",
+ message:
+ "You have denied the app access to phone features it needs to function. " +
+ "Some parts of the app are disabled. To enable these features in future " +
+ "please go to Settings.",
+ detail: "",
+ },
+ })
}
)
@@ -96,6 +110,11 @@ export class Home extends React.Component {
}
}
+ @autobind
+ handleMessageDismiss() {
+ this.setState({ messageModal: null })
+ }
+
@autobind
handlePositionChange(positionInfo) {
this.setState({ positionInfo })
@@ -150,7 +169,14 @@ export class Home extends React.Component {
}
render() {
- const { sections, showWorkItems, region, positionInfo } = this.state
+ const {
+ sections,
+ showWorkItems,
+ region,
+ positionInfo,
+ messageModal,
+ disableARViewer,
+ } = this.state
return (
+
+ {Platform.OS === "ios" && }
)
}
diff --git a/mobile/src/WorkItem/WorkItem.js b/mobile/src/WorkItem/WorkItem.js
index c43f84f..bd1d1db 100644
--- a/mobile/src/WorkItem/WorkItem.js
+++ b/mobile/src/WorkItem/WorkItem.js
@@ -20,6 +20,7 @@ import {
Header,
PhotoButton,
BoundOptionStrip,
+ PhotoPanel,
} from "../ui"
import { MessageModal } from "../Modal"
import autobind from "autobind-decorator"
@@ -46,10 +47,6 @@ const styles = StyleSheet.create({
shadowOpacity: 0.5,
padding: 10,
},
- label: {
- fontSize: 14,
- marginBottom: 4,
- },
})
export class WorkItem extends React.Component {
@@ -257,13 +254,7 @@ export class WorkItem extends React.Component {
/>
- Pictures:
-
-
-
-
-
+
{isIphoneX ? : null}
diff --git a/mobile/src/config.js b/mobile/src/config.js
index 6c62150..e86a071 100644
--- a/mobile/src/config.js
+++ b/mobile/src/config.js
@@ -1,5 +1,5 @@
export const localIPAddr = "192.168.1.175"
-//export const defaultUser = "john@lyon-smith.org"
-export const defaultUser = ""
+export const defaultUser = "john@lyon-smith.org"
+// export const defaultUser = ""
// export const minGPSAccuracy = 20
export const minGPSAccuracy = 100
diff --git a/mobile/src/ui/PhotoButton.js b/mobile/src/ui/PhotoButton.js
index 46f87e4..e69de29 100644
--- a/mobile/src/ui/PhotoButton.js
+++ b/mobile/src/ui/PhotoButton.js
@@ -1,31 +0,0 @@
-import React from 'react'
-import {
- StyleSheet,
- View,
- Image,
- TouchableOpacity
-} from 'react-native'
-import { Icon } from '.'
-import autobind from 'autobind-decorator'
-
-// const styles = StyleSheet.create()
-
-export class PhotoButton extends React.Component {
- render() {
- return (
-
-
-
-
-
- )
- }
-}
diff --git a/mobile/src/ui/PhotoPanel.js b/mobile/src/ui/PhotoPanel.js
new file mode 100644
index 0000000..e06d41f
--- /dev/null
+++ b/mobile/src/ui/PhotoPanel.js
@@ -0,0 +1,74 @@
+import React, { Component } from "react"
+import {
+ StyleSheet,
+ Text,
+ View,
+ Image,
+ TouchableOpacity,
+ Dimensions,
+} from "react-native"
+import { Icon } from "."
+import autobind from "autobind-decorator"
+
+const getScreenPortraitDimensions = () => {
+ const { width, height } = Dimensions.get("window")
+
+ return {
+ screenWidth: Math.min(width, height),
+ screenHeight: Math.max(width, height),
+ }
+}
+
+export class PhotoPanel extends Component {
+ render() {
+ const { screenWidth, screenHeight } = getScreenPortraitDimensions()
+ const photoWidth = screenHeight / 4
+ const photoHeight = screenWidth / 4
+ const numRows = 2
+ const numCols = 2
+ const rowPadding = 10
+
+ return (
+
+
+ Pictures:
+
+ {Array.from(new Array(numRows), (x, i) => (
+
+ {Array.from(new Array(numCols), (y, j) => (
+
+
+
+ ))}
+
+ ))}
+
+ )
+ }
+}
diff --git a/mobile/src/ui/index.js b/mobile/src/ui/index.js
index c65ea16..b2865c5 100644
--- a/mobile/src/ui/index.js
+++ b/mobile/src/ui/index.js
@@ -1,9 +1,9 @@
-export { Icon } from './Icon'
-export { Header } from './Header'
-export { PhotoButton } from './PhotoButton'
-export { OptionStrip } from './OptionStrip'
-export { BoundSwitch } from './BoundSwitch'
-export { BoundInput } from './BoundInput'
-export { BoundButton } from './BoundButton'
-export { BoundOptionStrip } from './BoundOptionStrip'
-export { BoundHeader } from './BoundHeader'
+export { Icon } from "./Icon"
+export { Header } from "./Header"
+export { PhotoPanel } from "./PhotoPanel"
+export { OptionStrip } from "./OptionStrip"
+export { BoundSwitch } from "./BoundSwitch"
+export { BoundInput } from "./BoundInput"
+export { BoundButton } from "./BoundButton"
+export { BoundOptionStrip } from "./BoundOptionStrip"
+export { BoundHeader } from "./BoundHeader"