Add better sizing for pictures
This commit is contained in:
@@ -76,6 +76,7 @@
|
|||||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
|
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
|
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/shaders" isTestSource="true" />
|
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/shaders" isTestSource="true" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/.DS_Store" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/blame" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/blame" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import {
|
|||||||
BoundInput,
|
BoundInput,
|
||||||
BoundButton,
|
BoundButton,
|
||||||
BoundOptionStrip,
|
BoundOptionStrip,
|
||||||
|
BoundHeader,
|
||||||
} from "../ui"
|
} from "../ui"
|
||||||
import { MessageModal } from "../Modal"
|
import { MessageModal } from "../Modal"
|
||||||
import autobind from "autobind-decorator"
|
import autobind from "autobind-decorator"
|
||||||
|
|||||||
@@ -20,54 +20,40 @@ console.ignoredYellowBox = [
|
|||||||
"<ViroSurface>",
|
"<ViroSurface>",
|
||||||
]
|
]
|
||||||
|
|
||||||
export const ensurePermission = (
|
export const ensurePermissions = (
|
||||||
permission,
|
permissions,
|
||||||
neverAskKeyName,
|
|
||||||
rationale,
|
rationale,
|
||||||
onSuccess,
|
onSuccess,
|
||||||
onError
|
onError
|
||||||
) => {
|
) => {
|
||||||
if (Platform.OS === "ios") {
|
if (Platform.OS === "ios") {
|
||||||
if (onSuccess) {
|
if (onSuccess) {
|
||||||
onSuccess()
|
onSuccess(
|
||||||
|
permissions.reduce(
|
||||||
|
(dict, permission) =>
|
||||||
|
(dict[permission] = PermissionsAndroid.RESULTS.GRANTED),
|
||||||
|
{}
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
PermissionsAndroid.check(permission)
|
PermissionsAndroid.requestMultiple(permissions, rationale)
|
||||||
.then((flag) => {
|
.then((results) => {
|
||||||
if (flag) {
|
if (
|
||||||
|
!Object.values(results).every(
|
||||||
|
(grant) => grant === PermissionsAndroid.RESULTS.GRANTED
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return Promise.reject()
|
||||||
|
}
|
||||||
|
|
||||||
if (onSuccess) {
|
if (onSuccess) {
|
||||||
onSuccess()
|
onSuccess(results)
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return AsyncStorage.getItem(neverAskKeyName)
|
|
||||||
})
|
|
||||||
.then((value) => {
|
|
||||||
if (value === "YES") {
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
return PermissionsAndroid.request(permission, rationale)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then((result) => {
|
.catch((error) => {
|
||||||
if (result === PermissionsAndroid.RESULTS.GRANTED) {
|
|
||||||
if (onSuccess) {
|
|
||||||
onSuccess()
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result === PermissionsAndroid.RESULTS.NEVER_ASK_AGAIN) {
|
|
||||||
AsyncStorage.setItem(neverAskKeyName, "YES")
|
|
||||||
}
|
|
||||||
|
|
||||||
if (onError) {
|
|
||||||
onError()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
if (onError) {
|
if (onError) {
|
||||||
onError()
|
onError()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,5 +3,5 @@ import { Route, Redirect } from "react-router-native"
|
|||||||
|
|
||||||
export const DefaultRoute = () => {
|
export const DefaultRoute = () => {
|
||||||
// NOTE: When working on the app, change this to the page you are working on
|
// NOTE: When working on the app, change this to the page you are working on
|
||||||
return <Route render={() => <Redirect to={"/home"} />} />
|
return <Route render={() => <Redirect to={"/workitem"} />} />
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,17 +9,19 @@ import {
|
|||||||
TouchableOpacity,
|
TouchableOpacity,
|
||||||
TouchableHighlight,
|
TouchableHighlight,
|
||||||
PermissionsAndroid,
|
PermissionsAndroid,
|
||||||
AsyncStorage,
|
Platform,
|
||||||
} from "react-native"
|
} from "react-native"
|
||||||
import MapView, { Marker } from "react-native-maps"
|
import MapView, { Marker } from "react-native-maps"
|
||||||
import { Icon, Header } from "../ui"
|
import { Icon, Header } from "../ui"
|
||||||
|
import { MessageModal } from "../Modal"
|
||||||
import { api } from "../API"
|
import { api } from "../API"
|
||||||
import autobind from "autobind-decorator"
|
import autobind from "autobind-decorator"
|
||||||
import { ifIphoneX } from "react-native-iphone-x-helper"
|
import { ifIphoneX } from "react-native-iphone-x-helper"
|
||||||
import { workItemTypeText, pad, regionContainingPoints } from "../util"
|
import { workItemTypeText, pad, regionContainingPoints } from "../util"
|
||||||
import { ensurePermission } from "../App"
|
import { ensurePermissions } from "../App"
|
||||||
import { versionInfo } from "../version"
|
import { versionInfo } from "../version"
|
||||||
import { minGPSAccuracy } from "../config"
|
import { minGPSAccuracy } from "../config"
|
||||||
|
import KeyboardSpacer from "react-native-keyboard-spacer"
|
||||||
import pinImage from "./images/pin.png"
|
import pinImage from "./images/pin.png"
|
||||||
|
|
||||||
const neverAskForLocationPermissionKeyName = "NeverAskForLocationPermission"
|
const neverAskForLocationPermissionKeyName = "NeverAskForLocationPermission"
|
||||||
@@ -38,38 +40,50 @@ export class Home extends React.Component {
|
|||||||
longitudeDelta: 0.0922,
|
longitudeDelta: 0.0922,
|
||||||
},
|
},
|
||||||
positionInfo: null,
|
positionInfo: null,
|
||||||
allowCameraAccess: false,
|
disableARViewer: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
ensurePermission(
|
ensurePermissions(
|
||||||
|
[
|
||||||
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
|
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
|
||||||
neverAskForLocationPermissionKeyName,
|
PermissionsAndroid.PERMISSIONS.CAMERA,
|
||||||
|
],
|
||||||
{
|
{
|
||||||
title: versionInfo.title,
|
title: versionInfo.title,
|
||||||
message:
|
message:
|
||||||
"This app needs access to your location so that " +
|
"This app needs these permissions so that you can " +
|
||||||
"you can find and access the geo located items.",
|
"find, access and photograph geo located items.",
|
||||||
},
|
},
|
||||||
() => {
|
(results) => {
|
||||||
|
if (
|
||||||
|
results[PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION] ===
|
||||||
|
PermissionsAndroid.RESULTS.GRANTED
|
||||||
|
) {
|
||||||
this.watchId = navigator.geolocation.watchPosition(
|
this.watchId = navigator.geolocation.watchPosition(
|
||||||
this.handlePositionChange,
|
this.handlePositionChange,
|
||||||
null,
|
null,
|
||||||
{ distanceFilter: 10 }
|
{ distanceFilter: 10 }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
ensurePermission(
|
if (
|
||||||
PermissionsAndroid.PERMISSIONS.CAMERA,
|
results[PermissionsAndroid.PERMISSIONS.CAMERA] ===
|
||||||
neverAskForCameraKeyName,
|
PermissionsAndroid.RESULTS.GRANTED
|
||||||
{
|
) {
|
||||||
title: versionInfo.title,
|
this.setState({ disableARViewer: false })
|
||||||
message:
|
}
|
||||||
"This app needs access to your camera so that " +
|
|
||||||
"you can view AR items.",
|
|
||||||
},
|
},
|
||||||
() => {
|
() => {
|
||||||
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
|
@autobind
|
||||||
handlePositionChange(positionInfo) {
|
handlePositionChange(positionInfo) {
|
||||||
this.setState({ positionInfo })
|
this.setState({ positionInfo })
|
||||||
@@ -150,7 +169,14 @@ export class Home extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { sections, showWorkItems, region, positionInfo } = this.state
|
const {
|
||||||
|
sections,
|
||||||
|
showWorkItems,
|
||||||
|
region,
|
||||||
|
positionInfo,
|
||||||
|
messageModal,
|
||||||
|
disableARViewer,
|
||||||
|
} = this.state
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
@@ -164,7 +190,8 @@ export class Home extends React.Component {
|
|||||||
leftButton={{ icon: "logout", onPress: this.handleLogoutPress }}
|
leftButton={{ icon: "logout", onPress: this.handleLogoutPress }}
|
||||||
rightButton={{ icon: "glasses", onPress: this.handleGlassesPress }}
|
rightButton={{ icon: "glasses", onPress: this.handleGlassesPress }}
|
||||||
disabled={
|
disabled={
|
||||||
!(positionInfo && positionInfo.coords.accuracy <= minGPSAccuracy)
|
!(positionInfo && positionInfo.coords.accuracy <= minGPSAccuracy) ||
|
||||||
|
disableARViewer
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<MapView
|
<MapView
|
||||||
@@ -347,6 +374,14 @@ export class Home extends React.Component {
|
|||||||
/>
|
/>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
|
<MessageModal
|
||||||
|
open={!!messageModal}
|
||||||
|
icon={messageModal ? messageModal.icon : ""}
|
||||||
|
message={messageModal ? messageModal.message : ""}
|
||||||
|
detail={messageModal ? messageModal.detail : ""}
|
||||||
|
onDismiss={messageModal && this.handleMessageDismiss}
|
||||||
|
/>
|
||||||
|
{Platform.OS === "ios" && <KeyboardSpacer />}
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import {
|
|||||||
Header,
|
Header,
|
||||||
PhotoButton,
|
PhotoButton,
|
||||||
BoundOptionStrip,
|
BoundOptionStrip,
|
||||||
|
PhotoPanel,
|
||||||
} from "../ui"
|
} from "../ui"
|
||||||
import { MessageModal } from "../Modal"
|
import { MessageModal } from "../Modal"
|
||||||
import autobind from "autobind-decorator"
|
import autobind from "autobind-decorator"
|
||||||
@@ -46,10 +47,6 @@ const styles = StyleSheet.create({
|
|||||||
shadowOpacity: 0.5,
|
shadowOpacity: 0.5,
|
||||||
padding: 10,
|
padding: 10,
|
||||||
},
|
},
|
||||||
label: {
|
|
||||||
fontSize: 14,
|
|
||||||
marginBottom: 4,
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
|
|
||||||
export class WorkItem extends React.Component {
|
export class WorkItem extends React.Component {
|
||||||
@@ -257,13 +254,7 @@ export class WorkItem extends React.Component {
|
|||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
<View style={styles.panel}>
|
<View style={styles.panel}>
|
||||||
<Text style={styles.label}>Pictures:</Text>
|
<PhotoPanel />
|
||||||
<View
|
|
||||||
style={{ flexDirection: "row", justifyContent: "space-between" }}>
|
|
||||||
<PhotoButton />
|
|
||||||
<PhotoButton />
|
|
||||||
<PhotoButton />
|
|
||||||
</View>
|
|
||||||
</View>
|
</View>
|
||||||
{isIphoneX ? <View style={{ height: 30, width: "100%" }} /> : null}
|
{isIphoneX ? <View style={{ height: 30, width: "100%" }} /> : null}
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
export const localIPAddr = "192.168.1.175"
|
export const localIPAddr = "192.168.1.175"
|
||||||
//export const defaultUser = "john@lyon-smith.org"
|
export const defaultUser = "john@lyon-smith.org"
|
||||||
export const defaultUser = ""
|
// export const defaultUser = ""
|
||||||
// export const minGPSAccuracy = 20
|
// export const minGPSAccuracy = 20
|
||||||
export const minGPSAccuracy = 100
|
export const minGPSAccuracy = 100
|
||||||
|
|||||||
@@ -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 (
|
|
||||||
<TouchableOpacity>
|
|
||||||
<View style={{
|
|
||||||
flexDirection: 'row',
|
|
||||||
width: 100,
|
|
||||||
height: 60,
|
|
||||||
borderWidth: 2,
|
|
||||||
borderColor: 'gray',
|
|
||||||
borderRadius: 4,
|
|
||||||
justifyContent: 'center',
|
|
||||||
}}>
|
|
||||||
<Icon name='add' size={24} style={{ alignSelf: 'center' }} />
|
|
||||||
</View>
|
|
||||||
</TouchableOpacity>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
74
mobile/src/ui/PhotoPanel.js
Normal file
74
mobile/src/ui/PhotoPanel.js
Normal file
@@ -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 (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flexDirection: "column",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
}}>
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
fontSize: 14,
|
||||||
|
marginBottom: 4,
|
||||||
|
}}>
|
||||||
|
Pictures:
|
||||||
|
</Text>
|
||||||
|
{Array.from(new Array(numRows), (x, i) => (
|
||||||
|
<View
|
||||||
|
key={"r" + i.toString()}
|
||||||
|
style={{
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
width: "100%",
|
||||||
|
height: photoHeight + rowPadding,
|
||||||
|
paddingTop: rowPadding / 2,
|
||||||
|
paddingBottom: rowPadding / 2,
|
||||||
|
}}>
|
||||||
|
{Array.from(new Array(numCols), (y, j) => (
|
||||||
|
<TouchableOpacity
|
||||||
|
key={"r" + i.toString() + "c" + j.toString()}
|
||||||
|
style={{
|
||||||
|
width: photoWidth,
|
||||||
|
height: photoHeight,
|
||||||
|
borderWidth: 2,
|
||||||
|
borderColor: "gray",
|
||||||
|
borderRadius: 4,
|
||||||
|
justifyContent: "center",
|
||||||
|
}}>
|
||||||
|
<Icon name="add" size={24} style={{ alignSelf: "center" }} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
export { Icon } from './Icon'
|
export { Icon } from "./Icon"
|
||||||
export { Header } from './Header'
|
export { Header } from "./Header"
|
||||||
export { PhotoButton } from './PhotoButton'
|
export { PhotoPanel } from "./PhotoPanel"
|
||||||
export { OptionStrip } from './OptionStrip'
|
export { OptionStrip } from "./OptionStrip"
|
||||||
export { BoundSwitch } from './BoundSwitch'
|
export { BoundSwitch } from "./BoundSwitch"
|
||||||
export { BoundInput } from './BoundInput'
|
export { BoundInput } from "./BoundInput"
|
||||||
export { BoundButton } from './BoundButton'
|
export { BoundButton } from "./BoundButton"
|
||||||
export { BoundOptionStrip } from './BoundOptionStrip'
|
export { BoundOptionStrip } from "./BoundOptionStrip"
|
||||||
export { BoundHeader } from './BoundHeader'
|
export { BoundHeader } from "./BoundHeader"
|
||||||
|
|||||||
Reference in New Issue
Block a user