Skip to content
This repository has been archived by the owner on Dec 8, 2022. It is now read-only.

Chat page and buttons to get into Chat page in Interested and Detail. #98

Merged
merged 4 commits into from
May 3, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"react-native": "~0.63.4",
"react-native-gesture-handler": "^1.8.0",
"react-native-get-random-values": "^1.6.0",
"react-native-gifted-chat": "^0.16.3",
"react-native-image-picker": "^3.3.2",
"react-native-paper": "^4.7.2",
"react-native-reanimated": "^1.13.2",
Expand Down
6 changes: 6 additions & 0 deletions src/constants/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ const Theme = {
adoptionButton: '#FDCF58',
floatingButton: '#FAFAFA',
notificationCounter: '#D55',
chatTextInput: '#FFFFFF',
chatBackground: '#F1F2F2',
chatSendIcon: '#FFFFFF',
chatSendBall: '#88C9BF',
chatText: '#434343',
chatBubleUser: '#CFE9E5',
},
named: {
blue: '#007BFF',
Expand Down
13 changes: 12 additions & 1 deletion src/layouts/HeaderLayout/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { useState } from 'react';

import { useNavigation } from '@react-navigation/native';
import Ionicons from 'react-native-vector-icons/Ionicons';
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';

import { ScrollView } from 'react-native-gesture-handler';
import SideMenu from 'react-native-side-menu-updated';
Expand All @@ -12,7 +13,7 @@ import { Theme } from '../../constants';

import { styledComponents, IHeaderProps, ITitleProps } from './styles';

type HeaderActions = 'back' | 'drawer' | 'share' | 'search';
type HeaderActions = 'back' | 'drawer' | 'share' | 'search' | 'options';

interface IButtonAction {
hidden?: boolean,
Expand Down Expand Up @@ -100,6 +101,16 @@ export default function HeaderLayout({
/>
</ActionButton>
);
case 'options':
return (
<ActionButton onPress={() => null}>
<MaterialCommunityIcons
name="dots-vertical"
size={24}
color={buttonType?.iconColor}
/>
</ActionButton>
);
}
};

Expand Down
17 changes: 14 additions & 3 deletions src/pages/Animal/Details/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ export default function AnimalDetails() : JSX.Element {

// Styled components.
const {
AdoptionButtonWrapper,
AnimalImage,
ButtonText,
ButtonTextStrong,
Expand Down Expand Up @@ -286,7 +285,7 @@ export default function AnimalDetails() : JSX.Element {
setLabelStyles(styles.secondaryLabel);

setPageButtons(
<AdoptionButtonWrapper>
<OptionButtonsWrapper>
<AsyncButton
styles={styles.adoptionButton}
asyncAction={false}
Expand All @@ -311,7 +310,19 @@ export default function AnimalDetails() : JSX.Element {
>
<ButtonTextStrong>{ resultInterestedIn ? 'Desistir da adoção' : 'Pretendo adotar' }</ButtonTextStrong>
</AsyncButton>
</AdoptionButtonWrapper>,
<AsyncButton
styles={styles.adoptionButton}
asyncAction={false}
callback={() => navigation.navigate('Chat', {
/* eslint-disable camelcase */
title: owner.data()?.full_name,
targetUserUID: animalData.owner.id,
animalUID: animal.id,
})}
>
<ButtonTextStrong>Chat</ButtonTextStrong>
</AsyncButton>
</OptionButtonsWrapper>,
);

setFloatingButton(
Expand Down
5 changes: 3 additions & 2 deletions src/pages/Animal/Details/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,11 +141,12 @@ export const styledComponents = {
// Styles.
export const styles = {
adoptionButton: {
alignItems: 'center',
backgroundColor: Theme.elements.adoptionButton,
borderRadius: '2px',
height: '40px',
width: '232px',
marginLeft: '8px',
marginRight: '8px',
width: '148px',
},

floatingButtonIcon: {
Expand Down
10 changes: 7 additions & 3 deletions src/pages/Animal/Interested/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,12 @@ const Interested = (): JSX.Element => {
callback={(u: InterestedUser): void => {
Alert.alert(u.userName, 'Selecione a ação', [
{
text: 'Cancelar',
onPress: () => null,
text: 'Chat',
onPress: () => navigation.navigate('Chat', {
title: user.userName,
targetUserUID: u.id,
animalUID: animal?.id,
}),
},
{
text: 'Remover',
Expand All @@ -176,7 +180,7 @@ const Interested = (): JSX.Element => {
}
},
},
]);
], { cancelable: true });
}}
/>
)}
Expand Down
238 changes: 238 additions & 0 deletions src/pages/Chat/Chat/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
import React, {
useCallback, useEffect, useState,
} from 'react';
import { setStatusBarBackgroundColor } from 'expo-status-bar';
import { RouteProp, useFocusEffect, useRoute } from '@react-navigation/native';
import {
GiftedChat, InputToolbar, InputToolbarProps, Send, SendProps, MessageProps, IMessage,
} from 'react-native-gifted-chat';
import MaterialIcons from 'react-native-vector-icons/MaterialIcons';

import HeaderLayout from '../../../layouts/HeaderLayout';
import { Theme } from '../../../constants';
import * as RouteTypes from '../../../types/routes';
import { styledComponents, styles } from './styles';

const mock = [
{
_id: 1,
text: 'Olá! Gostaria de adotar o seu gato!',
createdAt: new Date(1),
user: {
_id: 2,
name: 'React Native',
},
},
{
_id: 2,
text: 'Olá! Gostaria de adotar o seu gato!',
createdAt: new Date(2),
user: {
_id: 2,
name: 'React Native',
},
},
{
_id: 3,
text: 'Olá! Gostaria de adotar o seu gato!',
createdAt: new Date(3),
user: {
_id: 2,
name: 'React Native',
},
},
{
_id: 5,
text: 'Olá! Gostaria de adotar o seu gato!',
createdAt: new Date(5),
user: {
_id: 2,
name: 'React Native',
},
},
{
_id: 6,
text: 'Olá! Gostaria de adotar o seu gato!',
createdAt: new Date(6),
user: {
_id: 2,
name: 'React Native',
},
},
{
_id: 7,
text: 'Olá! Gostaria de adotar o seu gato!',
createdAt: new Date(7),
user: {
_id: 2,
name: 'React Native',
},
},
{
_id: 8,
text: 'Olá! Gostaria de adotar o seu gato!',
createdAt: new Date(8),
user: {
_id: 2,
name: 'React Native',
},
},
{
_id: 4,
text: 'Olá! Gostaria de adotar o seu gato!',
createdAt: new Date(4),
user: {
_id: 2,
name: 'React Native',
},
},
{
_id: 9,
text: 'Olá! Gostaria de adotar o seu gato!',
createdAt: new Date(9),
user: {
_id: 2,
name: 'React Native',
},
},
{
_id: 10,
text: 'Olá! Gostaria de adotar o seu gato!',
createdAt: new Date(10),
user: {
_id: 2,
name: 'React Native',
},
},
{
_id: 11,
text: 'Olá! Gostaria de adotar o seu gato!',
createdAt: new Date(11),
user: {
_id: 2,
name: 'React Native',
},
},
{
_id: 12,
text: 'Que maravilha, Marília! Você mora aqui em Brasília?',
createdAt: new Date(12),
user: {
_id: 1,
name: 'React Native',
},
},
];

export default (): JSX.Element => {
const chatTitle = useRoute<RouteProp<RouteTypes.RouteParams, 'Chat'>>().params?.title;
const animalUID = useRoute<RouteProp<RouteTypes.RouteParams, 'Chat'>>().params?.animalUID;
const targetUserUID = useRoute<RouteProp<RouteTypes.RouteParams, 'Chat'>>().params?.targetUserUID;

useFocusEffect(
useCallback(() => {
setStatusBarBackgroundColor(Theme.elements.statusBarPrimaryDark, true);
}, []),
);

const [messages, setMessages] = useState<IMessage[]>([]);

useEffect(() => {
// eslint-disable-next-line
console.log('================ CHAT PAGE ================');
// eslint-disable-next-line
console.log('chatAPI.getChat(currentUser, targetUser, animal): ', targetUserUID, animalUID);
// eslint-disable-next-line
console.log('...then');
// eslint-disable-next-line
console.log('chatAPI.loadMessages(chat, pageSize) if chat');
setMessages(mock.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime()));
}, [targetUserUID, animalUID]);

const onSend = useCallback((newMessages = []) => {
// eslint-disable-next-line
console.log('chatAPI.pushPessages(chat, newMessages): ', newMessages);
setMessages((previousMessages) => GiftedChat.append(previousMessages, newMessages));
}, []);

const onLoadEarlier = (): void => {
// eslint-disable-next-line
console.log('chatAPI.loadMessages(chat, pageSize, lastMessage): ', messages[0]);
};

const {
Container,
SendWrapper,
MessageBubble,
SelfMessageBubble,
MessageText,
} = styledComponents;

const renderInputToolbar = (props: InputToolbarProps): JSX.Element => (
<InputToolbar {...props} containerStyle={styles.inputContainer} />
);

const renderSend = (props: SendProps<IMessage>): JSX.Element => (
<Send {...props} containerStyle={styles.sendButtonContainer}>
<SendWrapper>
<MaterialIcons
style={styles.sendButtonIcon}
name="send"
size={24}
/>
</SendWrapper>
</Send>
);

const renderMessage = (props: MessageProps<IMessage>): JSX.Element => {
const isSameUser = props.currentMessage?.user._id === 1;
const MessageView = isSameUser ? SelfMessageBubble : MessageBubble;

return (
<MessageView>
<MessageText>{props.currentMessage?.text}</MessageText>
</MessageView>
);
};

return (
<HeaderLayout
disableScrollView
headerShown
title={chatTitle}
headerStyles={{
backgroundColor: Theme.elements.headerPrimary,
maxHeight: '56px',
height: '56px',
}}
leftAction={{
hidden: false,
actionType: 'back',
}}
rightAction={{
hidden: false,
actionType: 'options',
}}
>
<Container>
<GiftedChat
messages={messages}
loadEarlier
infiniteScroll
onLoadEarlier={onLoadEarlier}
onSend={(newMessages) => onSend(newMessages)}
user={{ _id: 1 }}
messagesContainerStyle={styles.messagesContainer}
renderAvatar={() => null}
placeholder=""
alignTop
alwaysShowSend
textInputProps={{ style: styles.textInput }}
renderInputToolbar={renderInputToolbar}
renderSend={renderSend}
renderMessage={renderMessage}
/>
</Container>
</HeaderLayout>
);
};
Loading