diff --git a/client/react-native/common/components/App.js b/client/react-native/common/components/App.js
index 254eb1414c..620e359b4f 100644
--- a/client/react-native/common/components/App.js
+++ b/client/react-native/common/components/App.js
@@ -1,9 +1,9 @@
import React, { PureComponent } from 'react'
import Screens from './Screens'
-import { NativeModules } from 'react-native'
+import { NativeModules, Platform } from 'react-native'
import { subscriptions } from '../graphql'
import { SafeAreaView } from 'react-navigation'
-
+import KeyboardSpacer from 'react-native-keyboard-spacer'
const { CoreModule } = NativeModules
export default class App extends PureComponent {
@@ -38,6 +38,7 @@ export default class App extends PureComponent {
return (
+ {Platform.OS === 'ios' && }
)
}
diff --git a/client/react-native/common/components/Library/Button.js b/client/react-native/common/components/Library/Button.js
index 33467b529c..f7ba34bc0f 100644
--- a/client/react-native/common/components/Library/Button.js
+++ b/client/react-native/common/components/Library/Button.js
@@ -1,6 +1,8 @@
import React from 'react'
import { Text } from '../Library'
-const Button = ({ style, ...props }) =>
+const Button = ({ style, ...props }) => (
+
+)
export default Button
diff --git a/client/react-native/common/components/Library/CustomTextInput.js b/client/react-native/common/components/Library/CustomTextInput.js
index eba4513da8..4f8b2f3937 100644
--- a/client/react-native/common/components/Library/CustomTextInput.js
+++ b/client/react-native/common/components/Library/CustomTextInput.js
@@ -6,7 +6,7 @@ import {
Text,
TextInput,
TouchableOpacity,
- View
+ View,
} from 'react-native'
import { Icon } from '.'
import { colors, fonts } from '../../constants'
@@ -28,11 +28,11 @@ type Props = {
borderRight?: number,
borderTop?: number,
borderLeft?: number,
- value?: string
+ value?: string,
}
type State = {|
- passwordVisible: boolean
+ passwordVisible: boolean,
|}
class CustomTextInput extends React.PureComponent {
@@ -41,11 +41,11 @@ class CustomTextInput extends React.PureComponent {
borderBottom: 0,
borderRight: 0,
borderTop: 0,
- borderLeft: 0
+ borderLeft: 0,
}
state = {
- passwordVisible: false
+ passwordVisible: false,
}
input: ?TextInput
@@ -60,7 +60,7 @@ class CustomTextInput extends React.PureComponent {
_togglePasswordVisibility = () => {
this.setState(prevState => ({
- passwordVisible: !prevState.passwordVisible
+ passwordVisible: !prevState.passwordVisible,
}))
}
@@ -81,7 +81,7 @@ class CustomTextInput extends React.PureComponent {
const inputPadding = {
paddingLeft: renderLeft ? 0 : 18,
- paddingRight: renderRight || this.props.secureTextEntry ? 0 : 18
+ paddingRight: renderRight || this.props.secureTextEntry ? 0 : 18,
}
return (
@@ -146,7 +146,7 @@ class CustomTextInput extends React.PureComponent {
const styles = StyleSheet.create({
container: {
alignItems: 'center',
- flexDirection: 'row'
+ flexDirection: 'row',
},
input: {
flex: 1,
@@ -155,25 +155,25 @@ const styles = StyleSheet.create({
color: colors.textGrey,
fontSize: 14,
lineHeight: 24,
- width: 50
+ width: 50,
},
eyeIcon: {
color: colors.subtleGrey,
padding: 15,
- fontSize: 16
+ fontSize: 16,
},
errorContainer: {
backgroundColor: colors.error,
alignItems: 'flex-start',
paddingHorizontal: 6,
- paddingVertical: 4
+ paddingVertical: 4,
},
error: {
color: colors.white,
fontFamily: fonts.medium,
fontSize: 10,
- lineHeight: 12
- }
+ lineHeight: 12,
+ },
})
export default CustomTextInput
diff --git a/client/react-native/common/components/Library/Flex.js b/client/react-native/common/components/Library/Flex.js
index 8fc8089db4..37638dfb05 100644
--- a/client/react-native/common/components/Library/Flex.js
+++ b/client/react-native/common/components/Library/Flex.js
@@ -1,5 +1,5 @@
import React from 'react'
-import { View } from 'react-native'
+import { View, TouchableOpacity } from 'react-native'
const getDirection = (key, directions = { rows: 'column', cols: 'row' }) =>
directions[key] || null
@@ -12,7 +12,7 @@ const getAlign = (
center: 'center',
stretch: 'stretch',
}
-) => align[key] || align['center']
+) => align[key] || align['stretch']
const getJustify = (
key,
@@ -35,23 +35,27 @@ export const Block = ({
children,
style,
...props
-}) => (
-
- {children}
-
-)
+}) => {
+ style = [
+ {
+ flex: size,
+ flexDirection: direction && getDirection(direction),
+ alignItems: align && getAlign(align),
+ alignSelf: self && getAlign(self),
+ justifyContent: justify && getJustify(justify),
+ },
+ style,
+ ]
+ return props.onPress ? (
+
+ {children}
+
+ ) : (
+
+ {children}
+
+ )
+}
export const Grid = props =>
diff --git a/client/react-native/common/components/Library/Header.js b/client/react-native/common/components/Library/Header.js
index 880f01628e..6dc93dd878 100644
--- a/client/react-native/common/components/Library/Header.js
+++ b/client/react-native/common/components/Library/Header.js
@@ -12,17 +12,8 @@ import {
const [defaultTextColor, defaultBackColor] = [colors.black, colors.white]
-const HeaderButton = ({ icon, color, onPress }) => {
- return (
-
- )
+const HeaderButton = ({ icon, color, style, ...otherProps }) => {
+ return
}
export default class Header extends PureComponent {
@@ -65,8 +56,8 @@ export default class Header extends PureComponent {
{backBtn === true && (
@@ -74,18 +65,29 @@ export default class Header extends PureComponent {
icon='arrow-left'
color={colorBtnLeft}
onPress={() => navigation.goBack(null)}
+ justify='start'
+ middle
/>
)}
-
-
+
{title}
-
{rightBtnIcon !== null && (
)}
diff --git a/client/react-native/common/components/Library/Icon.js b/client/react-native/common/components/Library/Icon.js
index dca530da75..efc251a9e5 100644
--- a/client/react-native/common/components/Library/Icon.js
+++ b/client/react-native/common/components/Library/Icon.js
@@ -17,7 +17,6 @@ const Icon = ({ name, color, rotate, style, ...props }) => {
name: iconName,
color: color || colors.textGrey,
style: [
- { color: color || colors.textGrey },
rotate && {
transform: [
{ rotate: typeof rotate === 'boolean' ? '90deg' : `${rotate}deg` },
diff --git a/client/react-native/common/components/Library/ListItem.js b/client/react-native/common/components/Library/ListItem.js
index f63f4fb65f..6f5b5677f2 100644
--- a/client/react-native/common/components/Library/ListItem.js
+++ b/client/react-native/common/components/Library/ListItem.js
@@ -2,7 +2,7 @@ import React, { PureComponent } from 'react'
import { TouchableOpacity, Image } from 'react-native'
import { colors } from '../../constants'
import { Flex, Text } from '.'
-import { marginHorizontal, marginLeft } from '../../styles'
+import { marginLeft, padding } from '../../styles'
export default class ListItem extends PureComponent {
render () {
@@ -13,14 +13,13 @@ export default class ListItem extends PureComponent {
style={[
{
backgroundColor: colors.white,
- paddingVertical: 16,
height: 72,
},
- marginHorizontal,
+ padding,
]}
>
-
-
+
+
-
+
{title}
-
+
{subtitle}
diff --git a/client/react-native/common/components/Library/Menu.js b/client/react-native/common/components/Library/Menu.js
index 8528f0ef9c..2033f103a5 100644
--- a/client/react-native/common/components/Library/Menu.js
+++ b/client/react-native/common/components/Library/Menu.js
@@ -1,37 +1,50 @@
import React, { Component, Fragment } from 'react'
+import { ActivityIndicator, StyleSheet, ScrollView, View } from 'react-native'
+import { Flex, Separator, Text } from '.'
import {
- ActivityIndicator,
- StyleSheet,
- ScrollView,
- View,
- TouchableOpacity,
-} from 'react-native'
-import { Separator, CustomTextInput, Icon, Text } from '.'
-import Flex from './Flex'
-import { largeText, margin, marginTopLeft, marginTop } from '../../styles'
+ marginTopLeft,
+ marginTop,
+ paddingLeft,
+ paddingHorizontal,
+ padding,
+} from '../../styles'
import { colors } from '../../constants'
export default class Menu extends Component {
- static Section = ({ icon, title, children, style, ...props }) => (
-
-
-
- {title && (
-
- {title}
+ static Header = ({ icon, title, description }) => (
+
+ {icon && (
+
+ {icon}
+
+ )}
+ {title && (
+
+
+ {title}
+
+ {description && (
+
+ {description}
)}
-
+
+ )}
+
+ )
+
+ static Section = ({ icon, title, children, style, ...props }) => (
+
+
+ {title && (
+
+ {title}
+
+ )}
{children}
@@ -50,72 +63,66 @@ export default class Menu extends Component {
})
render (
- { icon, title, style, color, children, onPress, onDelete } = this.props
+ { icon, input, title, style, color, children, onPress, onDelete } = this
+ .props
) {
return (
-
-
-
- {children || (
-
- {title}
-
- )}
-
- {onDelete && (
-
-
- {this.state.delete ? (
-
- ) : (
-
- )}
-
-
- )}
- {onPress && (
-
-
-
+
+ {children || (
+
+ {title}
+
)}
-
+ {onDelete &&
+ (this.state.delete ? (
+
+ ) : (
+
+ ))}
+ {onPress && (
+
+ )}
+
)
}
}
- static Input = ({ icon, style, ...props }) => (
-
-
- {icon && }
-
-
-
-
- )
+ static Input = ({ ...props }) =>
render () {
const { style, absolute } = this.props
return (
-
+
{this.props.children}
+
)
}
diff --git a/client/react-native/common/components/Library/Screen.js b/client/react-native/common/components/Library/Screen.js
index 3e10c16c23..a4fa14d5b0 100644
--- a/client/react-native/common/components/Library/Screen.js
+++ b/client/react-native/common/components/Library/Screen.js
@@ -1,6 +1,6 @@
import React, { Component } from 'react'
import { StyleSheet, Dimensions, View } from 'react-native'
-import { screen } from '../../constants'
+import { screen, colors } from '../../constants'
export default class Screen extends Component {
state = {
@@ -42,7 +42,7 @@ export default class Screen extends Component {
style={[
{
flex: 1,
- justifyContent: 'flex-start',
+ backgroundColor: colors.background,
},
dimensions,
style,
diff --git a/client/react-native/common/components/Library/Text.js b/client/react-native/common/components/Library/Text.js
index 24f8ece850..72832da9c4 100644
--- a/client/react-native/common/components/Library/Text.js
+++ b/client/react-native/common/components/Library/Text.js
@@ -1,12 +1,6 @@
-import React from 'react'
-import {
- TouchableOpacity,
- View,
- Text as TextNative,
- TextInput,
- Platform,
-} from 'react-native'
-import { Icon } from '.'
+import React, { Fragment } from 'react'
+import { View, Text as TextNative, TextInput, Platform } from 'react-native'
+import { Icon, Flex } from '.'
import {
tinyText,
smallText,
@@ -22,6 +16,12 @@ import {
bold,
shadow,
margin,
+ marginTop,
+ marginRight,
+ marginLeft,
+ marginBottom,
+ marginHorizontal,
+ marginVertical,
} from '../../styles'
import { colors } from '../../constants'
@@ -52,8 +52,20 @@ const getPadding = (
}
) => {
let padding = props.padding
- if (typeof padding === 'boolean') {
- padding = find({ inside: props, from: paddings, or: 'small' })
+ switch (typeof padding) {
+ case 'boolean':
+ padding = find({ inside: props, from: paddings, or: 'small' })
+ break
+ case 'string':
+ padding = paddings[padding]
+ break
+ case 'object':
+ return Object.keys(padding).reduce((a, key) => {
+ a[`padding${key.charAt(0).toUpperCase()}${key.slice(1)}`] = padding[key]
+ return a
+ }, {})
+ default:
+ return null
}
return {
paddingVertical: padding / 3,
@@ -63,16 +75,16 @@ const getPadding = (
const getIconPadding = (
props,
- paddings = {
- tiny: 4,
- small: 6,
+ margins = {
+ tiny: 5,
+ small: 7,
medium: 8,
large: 10,
big: 12,
}
) =>
(props.children || props.input) && {
- paddingRight: find({ inside: props, from: paddings, or: 'small' }),
+ marginRight: find({ inside: props, from: margins, or: 'small' }),
}
const getBorderRadius = (
@@ -151,14 +163,59 @@ const getJustify = (
props,
justify = {
center: 'center',
- left: 'flex-start',
- right: 'flex-end',
+ left: 'start',
+ right: 'end',
}
-) => find({ inside: props, from: justify, or: 'center' })
+) => find({ inside: props, from: justify, or: undefined })
+
+const getAlign = (
+ props,
+ align = {
+ middle: 'center',
+ top: 'start',
+ right: 'end',
+ }
+) => find({ inside: props, from: align, or: undefined })
+
+const getMargin = (
+ props,
+ margins = {
+ top: marginTop,
+ left: marginLeft,
+ right: marginRight,
+ bottom: marginBottom,
+ horizontal: marginHorizontal,
+ vertical: marginVertical,
+ }
+) => {
+ switch (typeof props.margin) {
+ case 'boolean':
+ return margin
+ case 'string':
+ return margins[props.margin]
+ case 'object':
+ return Object.keys(margins).reduce((a, key) => {
+ a[`margin${key.charAt(0).toUpperCase()}${key.slice(1)}`] =
+ props.margin[key]
+ return a
+ }, {})
+ default:
+ return null
+ }
+}
export const BackgroundText = props => {
- const { background, children, button, height, onPress } = props
- const style = [
+ const {
+ background,
+ children,
+ height,
+ size,
+ justify,
+ align,
+ self,
+ onPress,
+ } = props
+ const styleProp = [
{
backgroundColor:
(background === true && colors.blackGrey) ||
@@ -168,26 +225,25 @@ export const BackgroundText = props => {
},
getBorderRadius(props),
getPadding(props),
+ getMargin(props),
getOpacity(props),
props.shadow && shadow,
- props.margin && typeof props.margin === 'boolean'
- ? margin
- : { margin: props.margin },
- props.flex && typeof props.flex === 'boolean'
- ? { flex: 1 }
- : { flex: props.flex },
]
- return button ? (
-
+ const flexProps = {
+ size,
+ justify: justify || getJustify(props),
+ align: align || getAlign(props),
+ self,
+ }
+ return (
+
{children}
-
- ) : (
- {children}
+
)
}
export const ForegroundText = props => {
- const { icon, input, style, children, height, onSubmit } = props
+ const { icon, input, children, height, ellipsis, onSubmit } = props
const [vertical, horizontal, size, iconSize, weight, color, iconPadding] = [
getVertiAlign(props),
getHorizAlign(props),
@@ -198,15 +254,7 @@ export const ForegroundText = props => {
getIconPadding(props),
]
return (
-
+
{icon && typeof icon === 'string' ? (
{
iconSize,
weight,
color,
- style,
vertical,
horizontal,
iconPadding,
@@ -222,7 +269,7 @@ export const ForegroundText = props => {
]}
/>
) : (
- icon
+ icon && {icon}
)}
{input ? (
{
size,
weight,
color,
- style,
vertical,
horizontal,
{ height, lineHeight: height },
{
- flex: 1,
...(Platform.OS === 'web' ? { outline: 'none' } : {}),
},
+ { flex: 1 },
]}
placeholder={children || input.placeholder}
- placeholderTextColor={color}
+ placeholderTextColor={color.color}
onSubmitEditing={onSubmit}
/>
) : (
{children}
)}
-
+
)
}
diff --git a/client/react-native/common/components/Library/index.js b/client/react-native/common/components/Library/index.js
index c1fafdb1cc..b7a2eb8032 100644
--- a/client/react-native/common/components/Library/index.js
+++ b/client/react-native/common/components/Library/index.js
@@ -8,3 +8,4 @@ export Text from './Text'
export Flex from './Flex'
export Separator from './Separator'
export Button from './Button'
+export CustomTextInput from './CustomTextInput.js'
diff --git a/client/react-native/common/components/Screens/Chats/Add.js b/client/react-native/common/components/Screens/Chats/Add.js
index b33c6846fa..796b846930 100644
--- a/client/react-native/common/components/Screens/Chats/Add.js
+++ b/client/react-native/common/components/Screens/Chats/Add.js
@@ -1,82 +1,13 @@
// TODO: create generic contact list with pagination
import React, { PureComponent } from 'react'
-import {
- FlatList,
- TouchableOpacity,
- TextInput,
- Image,
- View,
-} from 'react-native'
-import { Screen, Flex, Text, Separator } from '../../Library'
+import { FlatList, TouchableOpacity, Image, View } from 'react-native'
+import { Screen, Flex, Text, Separator, Header } from '../../Library'
import { colors } from '../../../constants'
-import {
- paddingLeft,
- paddingRight,
- marginHorizontal,
- padding,
- borderBottom,
- paddingBottom,
- border,
-} from '../../../styles'
+import { marginHorizontal, border } from '../../../styles'
import { QueryReducer } from '../../../relay'
import { queries, subscriptions, mutations } from '../../../graphql'
-const Header = ({ navigation, onPressRight }) => (
-
-
-
- navigation.goBack(null)}
- />
-
- Add members
-
-
-
-
-
-
-
-
-)
-
class Item extends PureComponent {
state = { selected: false }
@@ -102,7 +33,7 @@ class Item extends PureComponent {
]}
>
-
+
-
+
@@ -158,7 +82,13 @@ export default class List extends PureComponent {
header: (
),
tabBarVisible: true,
@@ -173,9 +103,16 @@ export default class List extends PureComponent {
}
componentDidMount () {
- this.props.navigation.setParams({
- onPressRight: this.onSubmit,
- })
+ const onSubmit = this.props.navigation.getParam('onSubmit')
+ if (!onSubmit) {
+ this.props.navigation.setParams({
+ onSubmit: this.onSubmit(this.onDefaultSubmit),
+ })
+ } else {
+ this.props.navigation.setParams({
+ onSubmit: this.onSubmit(onSubmit),
+ })
+ }
this.subscribers = [
subscriptions.contactRequest.subscribe({
@@ -195,13 +132,16 @@ export default class List extends PureComponent {
contactsID: [],
}
- onSubmit = async () => {
+ onDefaultSubmit = async ({ contactsID }) => {
+ const retry = this.props.navigation.getParam('retry')
+ await mutations.conversationCreate.commit({ contactsID })
+ retry && retry()
+ this.props.navigation.goBack(null)
+ }
+
+ onSubmit = onSubmit => async () => {
try {
- const { contactsID } = this.state
- await mutations.conversationCreate.commit({ contactsID })
- const retry = this.props.navigation.getParam('retry')
- retry && retry()
- this.props.navigation.getParam('goBack')()
+ await onSubmit(this.state)
} catch (err) {
console.error(err)
}
diff --git a/client/react-native/common/components/Screens/Chats/Detail.js b/client/react-native/common/components/Screens/Chats/Detail.js
index 12883cb289..d02491a77a 100644
--- a/client/react-native/common/components/Screens/Chats/Detail.js
+++ b/client/react-native/common/components/Screens/Chats/Detail.js
@@ -1,10 +1,11 @@
import React, { PureComponent } from 'react'
-import { FlatList, Text as TextNative } from 'react-native'
+import { FlatList } from 'react-native'
import { colors } from '../../../constants'
import { queries, mutations, subscriptions } from '../../../graphql'
import { QueryReducer } from '../../../relay'
import { Text, Flex, Screen, Header } from '../../Library'
-import { paddingHorizontal, shadow, textRight, textLeft } from '../../../styles'
+import { paddingHorizontal, shadow } from '../../../styles'
+import { conversation as utils } from '../../../utils'
const Message = props => {
const conversation = props.navigation.getParam('conversation')
@@ -13,45 +14,27 @@ const Message = props => {
conversation.members.find(m => m.contactId === contactId).contact.status ===
'Myself'
return (
-
-
- {JSON.parse(props.data.attributes).message.text}
-
-
+ {JSON.parse(props.data.attributes).message.text}
+
)
}
-const getTitle = ({ title, members } = this.props) =>
- title ||
- members.map((m, index) => {
- const displayName =
- m.contact.status === 'Myself'
- ? m.contact.status
- : m.contact.overrideDisplayName || m.contact.displayName
- const before =
- index === 0 ? '' : index === members.length - 1 ? ' and ' : ', '
- return `${before}${displayName}`
- })
-
class List extends PureComponent {
onEndReached = () => {}
@@ -123,7 +106,7 @@ class Input extends PureComponent {
middle
padding
margin
- flex
+ height={36}
rounded='circle'
icon='edit-2'
input={{
@@ -133,7 +116,6 @@ class Input extends PureComponent {
autoFocus: true,
value: this.state.input,
}}
- height={36}
background={colors.grey8}
color={colors.grey5}
onSubmit={this.onSubmit}
@@ -147,8 +129,14 @@ export default class Detail extends PureComponent {
header: (
+ navigation.push('chats/settings', {
+ conversation: navigation.getParam('conversation'),
+ })
+ }
/>
),
})
diff --git a/client/react-native/common/components/Screens/Chats/List.js b/client/react-native/common/components/Screens/Chats/List.js
index a9e6d90f74..2107aa0cf5 100644
--- a/client/react-native/common/components/Screens/Chats/List.js
+++ b/client/react-native/common/components/Screens/Chats/List.js
@@ -5,27 +5,16 @@ import { colors } from '../../../constants'
import { QueryReducer } from '../../../relay'
import { subscriptions } from '../../../graphql'
import { createFragmentContainer, graphql } from 'react-relay'
-
-const getTitle = ({ title, members } = this.props) =>
- title ||
- members.map((m, index) => {
- const displayName =
- m.contact.status === 'Myself'
- ? m.contact.status
- : m.contact.overrideDisplayName || m.contact.displayName
- const before =
- index === 0 ? '' : index === members.length - 1 ? ' and ' : ', '
- return `${before}${displayName}`
- })
+import { conversation as utils } from '../../../utils'
class ListItemWrapper extends PureComponent {
render () {
const { data, navigation } = this.props
return (
navigation.push('Detail', { conversation: data })}
+ onPress={() => navigation.push('chats/detail', { conversation: data })}
/>
)
}
@@ -112,7 +101,7 @@ export default class ListScreen extends PureComponent {
searchBar
searchHandler={navigation.getParam('searchHandler')} // Placeholder
onPressRightBtn={() =>
- navigation.push('Add', {
+ navigation.push('chats/add', {
goBack: () => {
navigation.goBack(null)
const retry = navigation.getParam('retry')
diff --git a/client/react-native/common/components/Screens/Chats/Settings.js b/client/react-native/common/components/Screens/Chats/Settings.js
new file mode 100644
index 0000000000..871fbeb3a8
--- /dev/null
+++ b/client/react-native/common/components/Screens/Chats/Settings.js
@@ -0,0 +1,165 @@
+import React, { PureComponent } from 'react'
+import { Image } from 'react-native'
+import { Screen, Menu, Header } from '../../Library'
+import { colors } from '../../../constants'
+import { conversation as utils } from '../../../utils'
+import { mutations } from '../../../graphql'
+
+export default class Settings extends PureComponent {
+ static navigationOptions = ({ navigation }) => {
+ const [conversation, { edit }, onEdit, onSave] = [
+ navigation.getParam('conversation') || { members: [] },
+ navigation.getParam('state') || {},
+ navigation.getParam('onEdit'),
+ navigation.getParam('onSave'),
+ ]
+ const rightIcon = edit ? 'save' : 'edit-2'
+ const onPressRight = edit ? onSave : onEdit
+ return {
+ tabBarVisible: false,
+ header: (
+ 2 && rightIcon}
+ backBtn
+ onPressRightBtn={conversation.members.length > 2 && onPressRight}
+ />
+ ),
+ }
+ }
+
+ state = {
+ edit: false,
+ }
+
+ componentDidMount () {
+ this.props.navigation.setParams({
+ onEdit: this.onEdit,
+ onSave: this.onSave,
+ })
+ }
+
+ onEdit = () => {
+ this.setState({ edit: true }, () =>
+ this.props.navigation.setParams({ state: this.state })
+ )
+ }
+
+ onSave = () => {
+ this.setState({ edit: false }, () =>
+ this.props.navigation.setParams({ state: this.state })
+ )
+ }
+
+ addMembers = async ({ contactsID }) => {
+ try {
+ const { id } = this.props.navigation.getParam('conversation')
+ await mutations.conversationInvite.commit({
+ conversationID: id,
+ contactsID,
+ })
+ } catch (err) {
+ console.error(err)
+ }
+ this.props.navigation.goBack(null)
+ }
+
+ render () {
+ const { edit } = this.state
+ const conversation = this.props.navigation.getParam('conversation')
+ const title = utils.getTitle(conversation)
+ return (
+
+
+
+ )
+ }
+}
diff --git a/client/react-native/common/components/Screens/Chats/index.js b/client/react-native/common/components/Screens/Chats/index.js
index be0c752171..ef12007157 100644
--- a/client/react-native/common/components/Screens/Chats/index.js
+++ b/client/react-native/common/components/Screens/Chats/index.js
@@ -2,14 +2,16 @@ import { createSubStackNavigator } from '../../../helpers/react-navigation'
import List from './List'
import Detail from './Detail'
import Add from './Add'
+import Settings from './Settings'
export default createSubStackNavigator(
{
- List,
- Detail,
- Add,
+ 'chats/list': List,
+ 'chats/add': Add,
+ 'chats/detail': Detail,
+ 'chats/settings': Settings,
},
{
- initialRouteName: 'List',
+ initialRouteName: 'chats/list',
}
)
diff --git a/client/react-native/common/components/Screens/Contacts/Add/ByPublicKey.js b/client/react-native/common/components/Screens/Contacts/Add/ByPublicKey.js
index 04cfbd3e77..bf85c8df51 100644
--- a/client/react-native/common/components/Screens/Contacts/Add/ByPublicKey.js
+++ b/client/react-native/common/components/Screens/Contacts/Add/ByPublicKey.js
@@ -91,29 +91,32 @@ class ByPublicKey extends PureComponent {
selectTextOnFocus
/>
{routeName === 'Enter a public key' && (
-
+
+
+
)}
)
diff --git a/client/react-native/common/components/Screens/Contacts/Add/Choice.js b/client/react-native/common/components/Screens/Contacts/Add/Choice.js
index 3642a4642e..a4ad96d089 100644
--- a/client/react-native/common/components/Screens/Contacts/Add/Choice.js
+++ b/client/react-native/common/components/Screens/Contacts/Add/Choice.js
@@ -16,31 +16,31 @@ export default class Choice extends PureComponent {
@@ -65,10 +65,10 @@ const Item = ({ icon, name, link, navigation }) => (
]}
>
-
+
{name}
-
+
)
diff --git a/client/react-native/common/components/Screens/Contacts/Add/Request.js b/client/react-native/common/components/Screens/Contacts/Add/Request.js
index 4bceed9781..bdd394f020 100644
--- a/client/react-native/common/components/Screens/Contacts/Add/Request.js
+++ b/client/react-native/common/components/Screens/Contacts/Add/Request.js
@@ -42,7 +42,7 @@ class Request extends PureComponent {
state={state}
retry={retry}
subtitle={subtitle}
- action='RequestValidation'
+ action='contacts/add/request-validation'
navigation={navigation}
/>
)
diff --git a/client/react-native/common/components/Screens/Contacts/Add/index.js b/client/react-native/common/components/Screens/Contacts/Add/index.js
index 49ca9f6500..ba8bcb830a 100644
--- a/client/react-native/common/components/Screens/Contacts/Add/index.js
+++ b/client/react-native/common/components/Screens/Contacts/Add/index.js
@@ -11,16 +11,16 @@ import { Header } from '../../../Library'
export default createSubStackNavigator(
{
- Request,
- ByQRCode,
- ByPublicKey,
- ByBump,
- Invite,
- RequestValidation,
- Choice,
+ 'contacts/add/request': Request,
+ 'contacts/add/by-qr-code': ByQRCode,
+ 'contacts/add/by-public-key': ByPublicKey,
+ 'contacts/add/by-bump': ByBump,
+ 'contacts/add/invite': Invite,
+ 'contacts/add/request-validation': RequestValidation,
+ 'contacts/add/choice': Choice,
},
{
- initialRouteName: 'Choice',
+ initialRouteName: 'contacts/add/choice',
navigationOptions: ({ navigation }) => ({
header: (
navigation.push('Add')}
+ onPressRightBtn={() => navigation.push('contacts/add')}
searchBar
searchHandler={navigation.getParam('searchHandler')}
/>
@@ -86,7 +86,7 @@ class ContactListWrapper extends PureComponent {
state={state}
retry={retry}
subtitle='Last seen 3 hours ago ...' // Placeholder
- action='Detail'
+ action='contacts/detail'
navigation={navigation}
/>
)
diff --git a/client/react-native/common/components/Screens/Contacts/index.js b/client/react-native/common/components/Screens/Contacts/index.js
index 2b526953f4..b8f6f7f556 100644
--- a/client/react-native/common/components/Screens/Contacts/index.js
+++ b/client/react-native/common/components/Screens/Contacts/index.js
@@ -6,13 +6,13 @@ import List from './List'
export default createSubStackNavigator(
{
- List,
- Add,
- Detail,
- Edit,
+ 'contacts/list': List,
+ 'contacts/add': Add,
+ 'contacts/detail': Detail,
+ 'contacts/edit': Edit,
},
{
- initialRouteName: 'List',
+ initialRouteName: 'contacts/list',
hedaer: null,
}
)
diff --git a/client/react-native/common/components/Screens/Settings/List.js b/client/react-native/common/components/Screens/Settings/List.js
index 7cd1ce1374..64e9090bb4 100644
--- a/client/react-native/common/components/Screens/Settings/List.js
+++ b/client/react-native/common/components/Screens/Settings/List.js
@@ -46,7 +46,7 @@ export default class List extends PureComponent {
navigation.push('Devtools')}
+ onPress={() => navigation.push('settings/devtools')}
/>
({
header: (
diff --git a/client/react-native/common/components/Screens/index.js b/client/react-native/common/components/Screens/index.js
index ee78c18782..87a3b1e36d 100644
--- a/client/react-native/common/components/Screens/index.js
+++ b/client/react-native/common/components/Screens/index.js
@@ -7,12 +7,12 @@ import { borderTop, shadow } from '../../styles'
export default createTabNavigator(
{
- Contacts,
- Chats,
- Settings,
+ contacts: Contacts,
+ chats: Chats,
+ settings: Settings,
},
{
- initialRouteName: 'Chats',
+ initialRouteName: 'chats',
swipeEnabled: true,
animationEnabled: true,
tabBarPosition: 'bottom',
diff --git a/client/react-native/common/constants/colors.js b/client/react-native/common/constants/colors.js
index ade5949d36..bfb5753ca1 100644
--- a/client/react-native/common/constants/colors.js
+++ b/client/react-native/common/constants/colors.js
@@ -31,4 +31,6 @@ export default {
success: '#15D09D',
warning: '#FFD665',
error: '#F00062',
+
+ background: '#FAFAFE',
}
diff --git a/client/react-native/common/graphql/mutations/ConversationInvite.js b/client/react-native/common/graphql/mutations/ConversationInvite.js
new file mode 100644
index 0000000000..5043109d77
--- /dev/null
+++ b/client/react-native/common/graphql/mutations/ConversationInvite.js
@@ -0,0 +1,54 @@
+import { graphql } from 'react-relay'
+import { commit } from '../../relay'
+
+const ConversationInviteMutation = graphql`
+ mutation ConversationInviteMutation($input: ConversationInviteInput!) {
+ ConversationInvite(input: $input) {
+ clientMutationId
+ bertyEntityConversation {
+ id
+ createdAt
+ updatedAt
+ deletedAt
+ title
+ topic
+ members {
+ id
+ createdAt
+ updatedAt
+ deletedAt
+ status
+ contact {
+ id
+ createdAt
+ updatedAt
+ deletedAt
+ sigchain
+ status
+ devices {
+ id
+ createdAt
+ updatedAt
+ deletedAt
+ name
+ status
+ apiVersion
+ contactId
+ }
+ displayName
+ displayStatus
+ overrideDisplayName
+ overrideDisplayStatus
+ }
+ conversationId
+ contactId
+ }
+ }
+ }
+ }
+`
+
+export default {
+ commit: input =>
+ commit(ConversationInviteMutation, 'ConversationInvite', input),
+}
diff --git a/client/react-native/common/graphql/mutations/index.js b/client/react-native/common/graphql/mutations/index.js
index 33dab9134e..0d72598f6b 100644
--- a/client/react-native/common/graphql/mutations/index.js
+++ b/client/react-native/common/graphql/mutations/index.js
@@ -2,3 +2,4 @@ export contactRequest from './ContactRequest'
export contactAcceptRequest from './ContactAcceptRequest'
export conversationCreate from './ConversationCreate'
export conversationAddMessage from './ConversationAddMessage'
+export conversationInvite from './ConversationInvite'
diff --git a/client/react-native/common/relay/commit.js b/client/react-native/common/relay/commit.js
index 3ba6ac2938..6c3dfdd8ac 100644
--- a/client/react-native/common/relay/commit.js
+++ b/client/react-native/common/relay/commit.js
@@ -1,8 +1,8 @@
import { commitMutation } from 'react-relay'
import environment from './environment'
-export default (mutation, clientMutationId, input = {}) =>
- new Promise((resolve, reject) =>
+export default (mutation, clientMutationId, input = {}, configs) => {
+ return new Promise((resolve, reject) =>
commitMutation(environment, {
mutation,
variables: { input: { clientMutationId, ...input } },
@@ -14,5 +14,7 @@ export default (mutation, clientMutationId, input = {}) =>
resolve(res)
},
onError: reject,
+ ...configs,
})
)
+}
diff --git a/client/react-native/common/relay/environment.js b/client/react-native/common/relay/environment.js
index 5d510163c9..5aeeed6305 100644
--- a/client/react-native/common/relay/environment.js
+++ b/client/react-native/common/relay/environment.js
@@ -106,7 +106,6 @@ const setupSubscription = async (config, variables, cacheConfig, observer) => {
)
const onNext = result => {
- console.log(result)
observer.onNext(result)
}
diff --git a/client/react-native/common/styles.js b/client/react-native/common/styles.js
index 4a5e7729fd..8c37f0f39b 100644
--- a/client/react-native/common/styles.js
+++ b/client/react-native/common/styles.js
@@ -51,31 +51,26 @@ const styles = StyleSheet.create({
lineHeight: 14,
fontSize: 10,
textAlign: 'center',
- color: colors.textGrey,
},
smallText: {
lineHeight: 20,
fontSize: 14,
textAlign: 'center',
- color: colors.textGrey,
},
mediumText: {
lineHeight: 20,
fontSize: 16,
textAlign: 'center',
- color: colors.textGrey,
},
bigText: {
lineHeight: 30,
fontSize: 25,
textAlign: 'center',
- color: colors.textGrey,
},
largeText: {
lineHeight: 23,
fontSize: 18,
textAlign: 'center',
- color: colors.textGrey,
},
textGrey: {
color: colors.textGrey,
diff --git a/client/react-native/common/utils/conversation.js b/client/react-native/common/utils/conversation.js
new file mode 100644
index 0000000000..77d0fa271b
--- /dev/null
+++ b/client/react-native/common/utils/conversation.js
@@ -0,0 +1,13 @@
+export const getTitle = ({ title, members } = this.props) =>
+ title ||
+ members
+ .map((m, index) => {
+ const displayName =
+ m.contact.status === 'Myself'
+ ? m.contact.status
+ : m.contact.overrideDisplayName || m.contact.displayName
+ const before =
+ index === 0 ? '' : index === members.length - 1 ? ' and ' : ', '
+ return `${before}${displayName}`
+ })
+ .join('')
diff --git a/client/react-native/common/utils/index.js b/client/react-native/common/utils/index.js
new file mode 100644
index 0000000000..cc7659d972
--- /dev/null
+++ b/client/react-native/common/utils/index.js
@@ -0,0 +1 @@
+export * as conversation from './conversation'
diff --git a/client/react-native/package.json b/client/react-native/package.json
index 006606220f..ff6f628155 100644
--- a/client/react-native/package.json
+++ b/client/react-native/package.json
@@ -13,6 +13,7 @@
"react-art": "^16.4.2",
"react-dom": "^16.4.2",
"react-native": "^0.55.4",
+ "react-native-keyboard-spacer": "^0.4.1",
"react-native-network-info": "^3.2.2",
"react-native-vector-icons": "^5.0.0",
"react-native-web": "^0.8.9",
diff --git a/client/react-native/web/public/index.html b/client/react-native/web/public/index.html
index 2dbdc50225..f51f0b7407 100644
--- a/client/react-native/web/public/index.html
+++ b/client/react-native/web/public/index.html
@@ -12,7 +12,14 @@
diff --git a/client/react-native/yarn.lock b/client/react-native/yarn.lock
index 46ece64e7a..d8f3ee36b0 100644
--- a/client/react-native/yarn.lock
+++ b/client/react-native/yarn.lock
@@ -5210,6 +5210,10 @@ react-native-drawer-layout@1.3.2:
dependencies:
react-native-dismiss-keyboard "1.0.0"
+react-native-keyboard-spacer@^0.4.1:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/react-native-keyboard-spacer/-/react-native-keyboard-spacer-0.4.1.tgz#46f18a320432098a25ea9fa89f5143dd254d332d"
+
react-native-network-info@^3.2.2:
version "3.2.2"
resolved "https://registry.yarnpkg.com/react-native-network-info/-/react-native-network-info-3.2.2.tgz#93625587ab5ae31b7c853f37ec2b75a0af6c936d"