Skip to content

Commit

Permalink
fix(messenger): refracto Message component
Browse files Browse the repository at this point in the history
Signed-off-by: clegirar <clemntgirard@gmail.com>
  • Loading branch information
clegirar committed Nov 20, 2020
1 parent 90e432a commit 9a9fbcf
Show file tree
Hide file tree
Showing 10 changed files with 862 additions and 705 deletions.
3 changes: 2 additions & 1 deletion js/packages/components/chat/MultiMember.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ import { messenger as messengerpb } from '@berty-tech/api/index.js'
import * as api from '@berty-tech/api/index.pb'

import { ChatFooter, ChatDate } from './shared-components/Chat'
import { Message, MessageSystemWrapper } from './shared-components/Message'
import { Message } from './message'
import { MessageSystemWrapper } from './message/MessageSystemWrapper'
import BlurView from '../shared-components/BlurView'
import { SwipeNavRecognizer } from '../shared-components/SwipeNavRecognizer'
import AvatarGroup19 from '../main/Avatar_Group_Copy_19.png'
Expand Down
27 changes: 15 additions & 12 deletions js/packages/components/chat/OneToOne.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ import {
import { Icon, Text } from '@ui-kitten/components'
import { CommonActions } from '@react-navigation/native'
import { Translation, useTranslation } from 'react-i18next'
import moment from 'moment'
import { groupBy } from 'lodash'

import { useStyles } from '@berty-tech/styles'
import { Routes, ScreenProps, useNavigation } from '@berty-tech/navigation'
import * as api from '@berty-tech/api/index.pb'
import { messenger as messengerpb } from '@berty-tech/api/index.js'
import * as api from '@berty-tech/api/index.pb'
import { PersistentOptionsKeys } from '@berty-tech/store/context'
import {
useContact,
useConversation,
Expand All @@ -29,22 +30,24 @@ import {
useClient,
useNotificationsInhibitor,
} from '@berty-tech/store/hooks'
import { Routes, ScreenProps, useNavigation } from '@berty-tech/navigation'
import { useStyles } from '@berty-tech/styles'

import { ProceduralCircleAvatar } from '../shared-components/ProceduralCircleAvatar'
import { Message, MessageInvitationButton, MessageSystemWrapper } from './shared-components/Message'
import BlurView from '../shared-components/BlurView'
import { pbDateToNum, timeFormat } from '../helpers'
import { useLayout } from '../hooks'
import { playSound } from '../sounds'

import moment from 'moment'
import { Message } from './message'
import { MessageInvitationButton } from './message/MessageInvitation'
import { MessageSystemWrapper } from './message/MessageSystemWrapper'
import { ProceduralCircleAvatar } from '../shared-components/ProceduralCircleAvatar'

import BlurView from '../shared-components/BlurView'
import { ChatDate, ChatFooter } from './shared-components/Chat'
import { SwipeNavRecognizer } from '../shared-components/SwipeNavRecognizer'

import Logo from '../main/1_berty_picto.svg'
import Avatar from '../modals/Buck_Berty_Icon_Card.svg'
import { groupBy } from 'lodash'
import { pbDateToNum, timeFormat } from '../helpers'
import { useLayout } from '../hooks'
import { playSound } from '../sounds'
import { PersistentOptionsKeys } from '@berty-tech/store/context'

//
// Chat
Expand Down
218 changes: 218 additions & 0 deletions js/packages/components/chat/message/MessageInvitation.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
import React, { useMemo, useState } from 'react'
import { Text as TextNative, TouchableOpacity, View } from 'react-native'
import { Icon, Text } from '@ui-kitten/components'
import { Buffer } from 'buffer'

import { useClient, useConversation, useOneToOneContact } from '@berty-tech/store/hooks'
import { useStyles } from '@berty-tech/styles'

import { ProceduralCircleAvatar } from '../../shared-components/ProceduralCircleAvatar'
import { MessageSystemWrapper } from './MessageSystemWrapper'

const base64ToURLBase64 = (str: string) =>
str.replace(/\+/, '-').replace(/\//, '_').replace(/\=/, '')

export const MessageInvitationButton: React.FC<{
onPress?: any
activeOpacity: any
backgroundColor: any
icon: any
color: any
title: any
styleOpacity?: any
disabled?: boolean
}> = ({
onPress,
activeOpacity,
backgroundColor,
icon,
color,
title,
styleOpacity,
disabled = false,
}) => {
const [{ flex, padding, border, width, row, text, opacity }] = useStyles()
return (
<TouchableOpacity
style={[flex.align.center]}
activeOpacity={activeOpacity}
onPress={onPress}
disabled={disabled}
>
<View
style={[
padding.tiny,
padding.vertical.small,
border.radius.tiny,
width(120),
row.center,
flex.align.center,
padding.right.small,
{ backgroundColor },
]}
>
<Icon name={icon} width={24} height={24} fill={color} style={[opacity(styleOpacity)]} />
<TextNative
style={[
text.align.center,
text.size.scale(14),
text.bold.medium,
opacity(styleOpacity),
{ fontFamily: 'Open Sans', color },
]}
>
{title}
</TextNative>
</View>
</TouchableOpacity>
)
}

const MessageInvitationSent: React.FC<{ message: any }> = ({ message }) => {
const [{ text }] = useStyles()
const conversationContact = useOneToOneContact(message.conversationPublicKey)
return (
<Text style={[text.size.scale(14), text.align.center]}>
You invited {conversationContact?.displayName || 'this contact'} to a group! 💌
</Text>
)
}

const MessageInvitationReceived: React.FC<{ message: any }> = ({ message }) => {
const [{ row, flex, text, margin, color }] = useStyles()
const client: any = useClient()
const [error, setError] = useState(false)
const [{ convPk, displayName }, setPdlInfo] = useState({ convPk: '', displayName: '' })
const [accepting, setAccepting] = useState(false)
const conv = useConversation(convPk)
const { link } = message.payload || {}
const acceptDisabled = useMemo(() => accepting || conv || !convPk || error, [
accepting,
conv,
convPk,
error,
])

// Parse deep link
React.useEffect(() => {
if (!convPk && link && !conv) {
setError(false)
client
.parseDeepLink({
link,
})
.then((reply: any) => {
setPdlInfo({
displayName: reply.bertyGroup.displayName,
convPk: base64ToURLBase64(
new Buffer(reply?.bertyGroup?.group?.publicKey || '').toString('base64'),
),
})
})
.catch((err: any) => {
console.warn(err)
setError(true)
})
}
}, [convPk, conv, link, client])

const handleAccept = React.useCallback(() => {
if (convPk && !conv && !accepting && !error) {
setAccepting(true)
client
.conversationJoin({ link })
.catch((err: any) => {
console.warn(err)
setError(true)
})
.finally(() => {
setAccepting(false)
})
}
}, [client, link, conv, convPk, accepting, error])

return (
<React.Fragment>
<View style={[row.left, flex.align.center, flex.justify.center]}>
<TextNative
style={[
text.color.black,
text.size.scale(15),
text.bold.medium,
{ fontFamily: 'Open Sans' },
]}
>
GROUP INVITATION
</TextNative>
</View>
<View style={[margin.top.small, flex.align.center, flex.justify.center]}>
<ProceduralCircleAvatar seed={convPk || '42'} size={40} style={[margin.bottom.small]} />
<TextNative
style={[
text.color.black,
text.size.scale(13),
text.bold.small,
margin.bottom.small,
{ fontFamily: 'Open Sans' },
]}
>
{displayName}
</TextNative>
</View>
<View style={[row.center, flex.justify.spaceEvenly, flex.align.center, margin.top.medium]}>
<MessageInvitationButton
onPress={undefined} // TODO: Command to refuse invitation
activeOpacity={!conv ? 0.2 : 1}
icon='close-outline'
color={color.grey}
title='REFUSE'
backgroundColor={color.white}
styleOpacity={0.6}
disabled
/>
<MessageInvitationButton
onPress={handleAccept}
activeOpacity={!conv ? 0.2 : 1}
icon='checkmark-outline'
color={error ? color.grey : !conv ? color.blue : color.green}
title={!conv ? 'ACCEPT' : 'ACCEPTED'}
backgroundColor={error ? color.white : !conv ? color.light.blue : color.light.green}
styleOpacity={acceptDisabled ? 0.6 : undefined}
disabled={acceptDisabled ? true : false}
/>
</View>
{error && (
<Text
style={[
margin.top.small,
margin.horizontal.small,
text.size.small,
text.bold.small,
text.color.red,
text.align.center,
]}
>
Error adding you to the group ☹️ Our bad!
</Text>
)}
</React.Fragment>
)
}

export const MessageInvitation: React.FC<{ message: any }> = ({ message }) => {
const [{ row, padding, margin }] = useStyles()

return (
<View style={[row.center, padding.horizontal.medium, margin.bottom.small, { paddingTop: 2 }]}>
{message.isMe ? (
<MessageSystemWrapper logo={false}>
<MessageInvitationSent message={message} />
</MessageSystemWrapper>
) : (
<MessageSystemWrapper>
<MessageInvitationReceived message={message} />
</MessageSystemWrapper>
)}
</View>
)
}
89 changes: 89 additions & 0 deletions js/packages/components/chat/message/MessageMonitorMetadata.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import React from 'react'
import { View } from 'react-native'
import { Icon, Text } from '@ui-kitten/components'

import { useStyles } from '@berty-tech/styles'
import { pbDateToNum, timeFormat } from '../../helpers'
import { types as typespb } from '@berty-tech/api'

const getMonitorEventKeys = () => {
return ['undefined', 'advertiseGroup', 'peerFound', 'peerJoin', 'peerLeave']
}

const eventMonitorTypes = typespb.MonitorGroup.TypeEventMonitor

export const MessageMonitorMetadata: React.FC<{ inte: any }> = ({ inte }) => {
const [{ padding, text }] = useStyles()
const sentDate = pbDateToNum(inte?.sentDate)

/* typespb.MonitorGroup.TypeEventMonitor */
const monitorEvent = inte.payload.event
const monitorEventKeys = getMonitorEventKeys()
const { peerId, driverName, maddrs, isSelf } = monitorEvent[monitorEventKeys[monitorEvent.type]]

let monitorPayload
switch (monitorEvent.type) {
case eventMonitorTypes.TypeEventMonitorAdvertiseGroup:
const msgAdvertise = `local peer advertised ${peerId.substr(
peerId.length - 10,
)} on ${driverName}, with ${maddrs.length} maddrs:`
const addrsAdvertise = maddrs.map((addr: string) => `--${addr}`)
monitorPayload = [msgAdvertise, ...addrsAdvertise].join('\n')
break
case eventMonitorTypes.TypeEventMonitorPeerFound:
const msgPeerFound = `new peer found ${peerId.substr(
peerId.length - 10,
)} on ${driverName}, with ${maddrs.length} maddrs:`
const addrsPeerFound = maddrs.map((addr: string) => `--${addr}`)
monitorPayload = [msgPeerFound, ...addrsPeerFound].join('\n')
break
case eventMonitorTypes.TypeEventMonitorPeerJoin:
if (isSelf) {
monitorPayload = 'you just joined this group'
} else {
let activeAddr = '<unknown>'
if (maddrs.length) {
activeAddr = maddrs[0]
}
monitorPayload = `peer joined ${peerId.substr(peerId.length - 10)} on: ${activeAddr}`
}
break
case eventMonitorTypes.TypeEventMonitorPeerLeave:
if (isSelf) {
monitorPayload = 'you just leaved this group'
} else {
monitorPayload = `peer leaved ${peerId.substr(peerId.length - 10)}`
}
break
default:
console.log('undefined event type', monitorEvent)
monitorPayload = 'undefined'
}
return (
<View style={[padding.vertical.tiny, padding.horizontal.medium]}>
<View style={{ justifyContent: 'center', alignItems: 'center' }}>
<Icon name='monitor-outline' fill='#4E58BF' width={25} height={25} />
<Text
style={[
{ textAlign: 'center', fontFamily: 'Open Sans', color: '#4E58BF' },
text.bold.small,
text.italic,
text.size.scale(14),
]}
>
{monitorPayload}
</Text>
</View>
<Text
style={[
{ fontFamily: 'Open Sans', alignSelf: 'flex-end', color: '#4E58BF' },
text.bold.small,
text.italic,
text.size.small,
]}
>
{timeFormat.fmtTimestamp3(sentDate)}
</Text>
</View>
)
}

0 comments on commit 9a9fbcf

Please sign in to comment.