Make PhotoPanel bound
This commit is contained in:
@@ -36,10 +36,7 @@ export class BoundInput extends React.Component {
|
||||
handleChangeText(newText) {
|
||||
const { binder, name } = this.props
|
||||
|
||||
// TODO: Sometimes this is undefined and causes a crash?!
|
||||
if (binder) {
|
||||
const state = binder.getFieldState(name)
|
||||
|
||||
this.setState(binder.updateFieldValue(name, newText))
|
||||
}
|
||||
}
|
||||
|
||||
169
mobile/src/ui/BoundPhotoPanel.js
Normal file
169
mobile/src/ui/BoundPhotoPanel.js
Normal file
@@ -0,0 +1,169 @@
|
||||
import React, { Component } from "react"
|
||||
import PropTypes from "prop-types"
|
||||
import {
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
Image,
|
||||
TouchableOpacity,
|
||||
Dimensions,
|
||||
ActivityIndicator,
|
||||
} from "react-native"
|
||||
import { Icon } from "."
|
||||
import ImagePicker from "react-native-image-picker"
|
||||
import autobind from "autobind-decorator"
|
||||
import { api } from "../API"
|
||||
|
||||
const getScreenPortraitDimensions = () => {
|
||||
const { width, height } = Dimensions.get("window")
|
||||
|
||||
return {
|
||||
screenWidth: Math.min(width, height),
|
||||
screenHeight: Math.max(width, height),
|
||||
}
|
||||
}
|
||||
|
||||
export class BoundPhotoPanel extends Component {
|
||||
static propTypes = {
|
||||
onUploadStarted: PropTypes.func,
|
||||
onUploadEnded: PropTypes.func,
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
const { name, binder } = this.props
|
||||
|
||||
this.state = binder.getFieldState(name)
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.binder !== this.props.binder) {
|
||||
this.setState(nextProps.binder.getFieldState(nextProps.name))
|
||||
}
|
||||
}
|
||||
|
||||
@autobind
|
||||
handlePhotoPress(index) {
|
||||
const { onUploadStarted, onUploadEnded } = this.props
|
||||
|
||||
ImagePicker.showImagePicker(
|
||||
{
|
||||
title: "Select Photo",
|
||||
storageOptions: {
|
||||
skipBackup: true,
|
||||
path: "photos",
|
||||
},
|
||||
},
|
||||
(response) => {
|
||||
if (!response.didCancel && !response.error) {
|
||||
if (onUploadStarted) {
|
||||
onUploadStarted()
|
||||
}
|
||||
api
|
||||
.upload(response.data)
|
||||
.then((uploadData) => {
|
||||
if (onUploadEnded) {
|
||||
onUploadEnded(true, uploadData)
|
||||
}
|
||||
|
||||
const { binder, name } = this.props
|
||||
|
||||
if (binder) {
|
||||
const value = binder.getFieldValue(name)
|
||||
let newValue = value.slice(0)
|
||||
|
||||
newValue[index] = uploadData.assetId
|
||||
|
||||
this.setState(binder.updateFieldValue(name, newValue))
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
if (onUploadEnded) {
|
||||
onUploadEnded(false)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
render() {
|
||||
const { screenWidth, screenHeight } = getScreenPortraitDimensions()
|
||||
const photoWidth = screenHeight / 4
|
||||
const photoHeight = screenWidth / 4
|
||||
const rowPadding = 10
|
||||
const { value: assetIds } = this.state
|
||||
|
||||
const renderPhoto = (index) => {
|
||||
const assetId = assetIds[index]
|
||||
|
||||
if (assetId) {
|
||||
console.log(api.makeImageUrl(assetId))
|
||||
}
|
||||
|
||||
return (
|
||||
<TouchableOpacity
|
||||
key={assetId || "blank" + index.toString()}
|
||||
style={{
|
||||
width: photoWidth,
|
||||
height: photoHeight,
|
||||
borderWidth: 2,
|
||||
borderColor: "gray",
|
||||
borderRadius: 4,
|
||||
justifyContent: "center",
|
||||
}}
|
||||
onPress={() => this.handlePhotoPress(index)}>
|
||||
{!assetId && (
|
||||
<Icon name="add" size={24} style={{ alignSelf: "center" }} />
|
||||
)}
|
||||
{assetId && (
|
||||
<Image
|
||||
source={{ uri: api.makeImageUrl(assetId) }}
|
||||
style={{ width: "100%", height: "100%" }}
|
||||
resizeMode="contain"
|
||||
/>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
)
|
||||
}
|
||||
|
||||
const extraRowStyle = {
|
||||
height: photoHeight + rowPadding,
|
||||
paddingTop: rowPadding / 2,
|
||||
paddingBottom: rowPadding / 2,
|
||||
}
|
||||
|
||||
return (
|
||||
<View
|
||||
style={{
|
||||
flexDirection: "column",
|
||||
justifyContent: "space-between",
|
||||
}}>
|
||||
<Text
|
||||
style={{
|
||||
fontSize: 14,
|
||||
marginBottom: 4,
|
||||
}}>
|
||||
Pictures:
|
||||
</Text>
|
||||
<View style={[styles.photoRow, extraRowStyle]}>
|
||||
{renderPhoto(0)}
|
||||
{renderPhoto(1)}
|
||||
</View>
|
||||
<View style={[styles.photoRow, extraRowStyle]}>
|
||||
{renderPhoto(2)}
|
||||
{renderPhoto(3)}
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
photoRow: {
|
||||
flexDirection: "row",
|
||||
justifyContent: "space-between",
|
||||
width: "100%",
|
||||
},
|
||||
})
|
||||
@@ -1,104 +0,0 @@
|
||||
import React, { Component } from "react"
|
||||
import {
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
Image,
|
||||
TouchableOpacity,
|
||||
Dimensions,
|
||||
} from "react-native"
|
||||
import { Icon } from "."
|
||||
import ImagePicker from "react-native-image-picker"
|
||||
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 {
|
||||
@autobind
|
||||
handlePhotoPress() {
|
||||
ImagePicker.showImagePicker(
|
||||
{
|
||||
title: "Select Photo",
|
||||
storageOptions: {
|
||||
skipBackup: true,
|
||||
path: "photos",
|
||||
},
|
||||
},
|
||||
(response) => {
|
||||
console.log("Response = ", response)
|
||||
|
||||
if (response.didCancel) {
|
||||
console.log("User cancelled image picker")
|
||||
} else if (response.error) {
|
||||
console.log("ImagePicker Error: ", response.error)
|
||||
} else if (response.customButton) {
|
||||
console.log("User tapped custom button: ", response.customButton)
|
||||
} else {
|
||||
// You can also display the image using data:
|
||||
// let source = { uri: 'data:image/jpeg;base64,' + response.data };
|
||||
console.log(response)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
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",
|
||||
}}
|
||||
onPress={this.handlePhotoPress}>
|
||||
<Icon name="add" size={24} style={{ alignSelf: "center" }} />
|
||||
</TouchableOpacity>
|
||||
))}
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
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"
|
||||
export { BoundPhotoPanel } from "./BoundPhotoPanel"
|
||||
|
||||
Reference in New Issue
Block a user