Skip to content

Commit

Permalink
feat: reply and reaction feature
Browse files Browse the repository at this point in the history
Signed-off-by: Sakul <sakulbudhathoki977@gmail.com>
  • Loading branch information
sakul-budhathoki committed Apr 2, 2021
1 parent 2cec504 commit d41db33
Show file tree
Hide file tree
Showing 16 changed files with 849 additions and 225 deletions.
8 changes: 7 additions & 1 deletion go/pkg/bertymessenger/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -1416,10 +1416,16 @@ func (svc *service) ConversationLoad(ctx context.Context, request *messengertype
if medias == nil {
medias = []*messengertypes.Media{}
}
ais := make([]*messengertypes.Interaction, len(interactions))
for i, inte := range interactions {
if ais[i], err = svc.db.getAugmentedInteraction(inte.CID); err != nil {
return nil, errcode.ErrDBRead.Wrap(err)
}
}

if err := svc.dispatcher.StreamEvent(messengertypes.StreamEvent_TypeConversationPartialLoad, &messengertypes.StreamEvent_ConversationPartialLoad{
ConversationPK: interactions[0].ConversationPublicKey,
Interactions: interactions,
Interactions: ais,
Medias: medias,
}, false); err != nil {
svc.logger.Error("unable to bulk send conversation events", zap.Error(err))
Expand Down
14 changes: 14 additions & 0 deletions go/pkg/bertymessenger/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -1425,3 +1425,17 @@ func (d *dbWrapper) setupVirtualTablesAndTriggers() error {

return nil
}

func (d *dbWrapper) getAugmentedInteraction(cid string) (*messengertypes.Interaction, error) {
inte, err := d.getInteractionByCID(cid)
if err != nil {
return nil, errcode.ErrDBRead.Wrap(err)
}

inte.Reactions, err = buildReactionsView(d, cid)
if err != nil {
return nil, errcode.ErrDBRead.Wrap(err)
}

return inte, nil
}
9 changes: 2 additions & 7 deletions go/pkg/bertymessenger/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -542,19 +542,14 @@ func (svc *service) sendAccountUserInfo(groupPK string) error {

func (svc *service) streamInteraction(tx *dbWrapper, cid string, isNew bool) error {
if svc != nil && svc.dispatcher != nil {
eventInte, err := tx.getInteractionByCID(cid)
if err != nil {
return errcode.ErrDBRead.Wrap(err)
}

eventInte.Reactions, err = buildReactionsView(tx, cid)
interaction, err := tx.getAugmentedInteraction(cid)
if err != nil {
return errcode.ErrDBRead.Wrap(err)
}

if err := svc.dispatcher.StreamEvent(
mt.StreamEvent_TypeInteractionUpdated,
&mt.StreamEvent_InteractionUpdated{Interaction: eventInte},
&mt.StreamEvent_InteractionUpdated{Interaction: interaction},
isNew,
); err != nil {
return errcode.ErrMessengerStreamEvent.Wrap(err)
Expand Down
1 change: 1 addition & 0 deletions js/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ declare module 'react-native-in-app-notification'
declare module 'react-native-audiowaveform'
declare module 'linkify-it'
declare module 'react-native-flags'
declare module 'react-native-emoji-board'

declare module 'google-palette' {
const content: (type: string, count: number) => string[]
Expand Down
3 changes: 3 additions & 0 deletions js/package.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions js/packages/components/chat/MessageList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,12 @@ export const MessageList: React.FC<{
members={members || {}}
previousMessage={index < messages.length - 1 ? messages[index + 1] : undefined}
nextMessage={index > 0 ? messages[index - 1] : undefined}
replyOf={messages.find((message) => message.cid === item.targetCid)}
scrollToCid={(cid) => {
flatListRef?.current?.scrollToIndex({
index: messages.findIndex((message) => message.cid === cid),
})
}}
/>
</>
)
Expand Down
99 changes: 69 additions & 30 deletions js/packages/components/chat/MultiMember.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { TouchableOpacity, View, Platform } from 'react-native'
import { Text, Icon } from '@ui-kitten/components'
import { CommonActions } from '@react-navigation/native'
import { useTranslation } from 'react-i18next'
import EmojiBoard from 'react-native-emoji-board'

import { KeyboardAvoidingView } from '@berty-tech/components/shared-components/KeyboardAvoidingView'
import { useStyles } from '@berty-tech/styles'
Expand All @@ -12,6 +13,7 @@ import {
useLastConvInteraction,
useReadEffect,
useNotificationsInhibitor,
useMsgrContext,
} from '@berty-tech/store/hooks'
import beapi from '@berty-tech/api'

Expand All @@ -22,6 +24,7 @@ import { useLayout } from '../hooks'
import { MultiMemberAvatar } from '../avatars'
import { MessageList } from '@berty-tech/components/chat/MessageList'
import { useSafeAreaInsets } from 'react-native-safe-area-context'
import { ReplyReactionProvider } from './ReplyReactionContext'

//
// MultiMember
Expand Down Expand Up @@ -111,13 +114,13 @@ export const MultiMember: React.FC<ScreenProps.Chat.Group> = ({ route: { params
}
return false
})

const [inputIsFocused, setInputFocus] = useState(false)
const [{ background, flex }] = useStyles()
const { dispatch } = useNavigation()
useReadEffect(params.convId, 1000)
const conv = useConversation(params?.convId)
const { t } = useTranslation()
const ctx = useMsgrContext()
const insets = useSafeAreaInsets()

const lastInte = useLastConvInteraction(params?.convId || '')
const lastUpdate = conv?.lastUpdate || lastInte?.sentDate || conv?.createdDate || null
Expand All @@ -127,33 +130,69 @@ export const MultiMember: React.FC<ScreenProps.Chat.Group> = ({ route: { params
const [isSwipe, setSwipe] = useState(true)

return (
<View style={[flex.tiny, background.white]}>
<SwipeNavRecognizer
onSwipeLeft={() =>
isSwipe &&
dispatch(
CommonActions.navigate({
name: Routes.Chat.MultiMemberSettings,
params: { convId: params?.convId },
}),
)
}
>
<KeyboardAvoidingView
style={[flex.tiny]}
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
>
<MessageList id={params?.convId} {...{ setStickyDate, setShowStickyDate }} />
<ChatFooter
convPk={params?.convId}
isFocused={inputIsFocused}
setFocus={setInputFocus}
placeholder={t('chat.multi-member.input-placeholder')}
setSwipe={setSwipe}
/>
<HeaderMultiMember id={params?.convId} {...({ stickyDate, showStickyDate } as any)} />
</KeyboardAvoidingView>
</SwipeNavRecognizer>
</View>
<ReplyReactionProvider>
{({ activeEmojiKeyboardCid, setActiveEmojiKeyboardCid, setActivePopoverCid }) => (
<View style={[flex.tiny, background.white]}>
<SwipeNavRecognizer
onSwipeLeft={() =>
isSwipe &&
dispatch(
CommonActions.navigate({
name: Routes.Chat.MultiMemberSettings,
params: { convId: params?.convId },
}),
)
}
>
<KeyboardAvoidingView
style={[flex.tiny]}
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
>
<MessageList id={params?.convId} {...{ setStickyDate, setShowStickyDate }} />
<ChatFooter
convPk={params?.convId}
placeholder={t('chat.multi-member.input-placeholder')}
setSwipe={setSwipe}
/>
<HeaderMultiMember id={params?.convId} {...({ stickyDate, showStickyDate } as any)} />
</KeyboardAvoidingView>
</SwipeNavRecognizer>
{!!activeEmojiKeyboardCid && (
<EmojiBoard
showBoard={true}
onClick={(emoji) => {
ctx.client
?.interact({
conversationPublicKey: conv?.publicKey,
type: beapi.messenger.AppMessage.Type.TypeUserReaction,
payload: beapi.messenger.AppMessage.UserReaction.encode({
emoji: `:${emoji.name}:`,
state: true,
}).finish(),
targetCid: activeEmojiKeyboardCid,
})
.then(() => {
ctx.playSound('messageSent')
setActivePopoverCid(null)
setActiveEmojiKeyboardCid(null)
})
.catch((e) => {
console.warn('e sending message:', e)
})
}}
onRemove={() => {
setActivePopoverCid(activeEmojiKeyboardCid)
setActiveEmojiKeyboardCid(null)
}}
containerStyle={{
position: 'absolute',
bottom: 0,
paddingBottom: insets.bottom,
}}
/>
)}
</View>
)}
</ReplyReactionProvider>
)
}
110 changes: 76 additions & 34 deletions js/packages/components/chat/OneToOne.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ import { Icon, Text } from '@ui-kitten/components'
import { CommonActions } from '@react-navigation/native'
import { useTranslation } from 'react-i18next'
import { useSafeAreaInsets } from 'react-native-safe-area-context'
import EmojiBoard from 'react-native-emoji-board'

import { KeyboardAvoidingView } from '@berty-tech/components/shared-components/KeyboardAvoidingView'
import { useStyles } from '@berty-tech/styles'
import { Routes, ScreenProps, useNavigation } from '@berty-tech/navigation'
import beapi from '@berty-tech/api'
import {
useContact,
useMsgrContext,
useConversation,
useReadEffect,
useNotificationsInhibitor,
Expand All @@ -22,6 +24,7 @@ import { useLayout } from '../hooks'
import { ChatDate, ChatFooter } from './common'
import { SwipeNavRecognizer } from '../shared-components/SwipeNavRecognizer'
import { MessageList } from '@berty-tech/components/chat/MessageList'
import { ReplyReactionProvider } from './ReplyReactionContext'

//
// Chat
Expand Down Expand Up @@ -131,13 +134,14 @@ export const OneToOne: React.FC<ScreenProps.Chat.OneToOne> = ({ route: { params
return false
})

const [inputIsFocused, setInputFocus] = useState(false)
const insets = useSafeAreaInsets()
const [{ flex, background }] = useStyles()
useReadEffect(params?.convId, 1000)
const { dispatch } = useNavigation()
const { t } = useTranslation()
const conv = useConversation(params?.convId)
const contact = useContact(conv?.contactPublicKey)
const ctx = useMsgrContext()

const isIncoming = contact?.state === beapi.messenger.Contact.State.IncomingRequest
const isFooterDisable = isIncoming
Expand All @@ -150,38 +154,76 @@ export const OneToOne: React.FC<ScreenProps.Chat.OneToOne> = ({ route: { params
const [isSwipe, setSwipe] = useState(true)

return (
<View style={[StyleSheet.absoluteFill, background.white, { flex: 1 }]}>
<SwipeNavRecognizer
onSwipeLeft={() =>
isSwipe &&
dispatch(
CommonActions.navigate({
name: Routes.Chat.OneToOneSettings,
params: { convId: params?.convId },
}),
)
}
>
<KeyboardAvoidingView
style={[flex.tiny, { justifyContent: 'flex-start' }]}
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
>
<MessageList
id={params?.convId}
scrollToMessage={params?.scrollToMessage || '0'}
{...{ setStickyDate, setShowStickyDate }}
/>
<ChatFooter
convPk={params?.convId}
isFocused={inputIsFocused}
setFocus={setInputFocus}
disabled={isFooterDisable}
placeholder={placeholder}
setSwipe={setSwipe}
/>
<ChatHeader convPk={params?.convId || ''} {...{ stickyDate, showStickyDate }} />
</KeyboardAvoidingView>
</SwipeNavRecognizer>
</View>
<ReplyReactionProvider>
{({ activeEmojiKeyboardCid, setActiveEmojiKeyboardCid, setActivePopoverCid }) => (
<View style={[StyleSheet.absoluteFill, background.white, { flex: 1 }]}>
<SwipeNavRecognizer
onSwipeLeft={() =>
isSwipe &&
dispatch(
CommonActions.navigate({
name: Routes.Chat.OneToOneSettings,
params: { convId: params?.convId },
}),
)
}
>
<KeyboardAvoidingView
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
style={[flex.tiny, { justifyContent: 'flex-start' }]}
>
<MessageList
id={params?.convId}
scrollToMessage={params?.scrollToMessage || '0'}
{...{ setStickyDate, setShowStickyDate }}
/>

<ChatFooter
convPk={params?.convId}
disabled={isFooterDisable}
placeholder={placeholder}
setSwipe={setSwipe}
/>

<ChatHeader convPk={params?.convId || ''} {...{ stickyDate, showStickyDate }} />
</KeyboardAvoidingView>
</SwipeNavRecognizer>
{!!activeEmojiKeyboardCid && (
<EmojiBoard
showBoard={true}
onClick={(emoji) => {
ctx.client
?.interact({
conversationPublicKey: conv?.publicKey,
type: beapi.messenger.AppMessage.Type.TypeUserReaction,
payload: beapi.messenger.AppMessage.UserReaction.encode({
emoji: `:${emoji.name}:`,
state: true,
}).finish(),
targetCid: activeEmojiKeyboardCid,
})
.then(() => {
ctx.playSound('messageSent')
setActivePopoverCid(null)
setActiveEmojiKeyboardCid(null)
})
.catch((e) => {
console.warn('e sending message:', e)
})
}}
onRemove={() => {
setActivePopoverCid(activeEmojiKeyboardCid)
setActiveEmojiKeyboardCid(null)
}}
containerStyle={{
position: 'absolute',
bottom: 0,
paddingBottom: insets.bottom,
}}
/>
)}
</View>
)}
</ReplyReactionProvider>
)
}

0 comments on commit d41db33

Please sign in to comment.