Browse Source

Merge branch 'file-message' into 'master'

File message

See merge request jetup/rws/rws-appication!248
merge-requests/249/head
Coder 3 years ago
parent
commit
f0813d1fd7
  1. 8
      package-lock.json
  2. 1
      package.json
  3. 6
      src/api/chats/requests.interface.ts
  4. 43
      src/api/chats/requests.ts
  5. 36
      src/modules/chats/atoms/attachments-menu.atom.tsx
  6. 3
      src/modules/chats/atoms/index.ts
  7. 20
      src/modules/chats/atoms/send-button.tsx
  8. 21
      src/modules/chats/components/chat-actions.component.tsx
  9. 54
      src/modules/chats/components/chat-attachments-menu-item.component.tsx
  10. 33
      src/modules/chats/components/chat-footer.tsx
  11. 19
      src/modules/chats/components/chats-list.component.tsx
  12. 4
      src/modules/chats/components/index.ts
  13. 17
      src/modules/chats/configs/attachments-menu.config.ts
  14. 3
      src/modules/chats/configs/index.ts
  15. 3
      src/modules/chats/hooks/index.ts
  16. 5
      src/modules/chats/hooks/use-chat-messages.hook.ts
  17. 97
      src/modules/chats/hooks/use-send-files.hook.ts
  18. 117
      src/modules/chats/screens/chat.tsx
  19. 3
      src/modules/chats/transforms/chat-messages.transforms.ts
  20. 67
      src/services/domain/chat-messages.service.ts
  21. 30
      src/services/system/media.service.ts
  22. 2
      src/shared/enums/chat.enums.ts
  23. 3
      src/shared/interfaces/index.ts
  24. 5
      src/shared/interfaces/media.interfaces.ts
  25. 7
      src/shared/themes/dark/chat.ts
  26. 8
      src/shared/themes/interfaces/chat.interface.ts
  27. 8
      src/shared/themes/light/chat.ts

8
package-lock.json generated

@ -24466,6 +24466,14 @@ @@ -24466,6 +24466,14 @@
"integrity": "sha512-l8/3MHq6O9PRWSrKwy63WvDCnt8IXOce86AEkJFVVtKR9cAGLLaFyXUGyqIc5T/kpCyOqofOattVDjZGUn/zAQ==",
"requires": {}
},
"react-native-document-picker": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/react-native-document-picker/-/react-native-document-picker-8.0.0.tgz",
"integrity": "sha512-4O1FNOJHzfZ7BBFOJhNoeCKHSjthFtZyMEWJsAxX1ORdShGSa6miLvTHtQjpCDMNWSoPU1C7fXLNNPrv8GAarQ==",
"requires": {
"invariant": "^2.2.4"
}
},
"react-native-draggable-switch": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/react-native-draggable-switch/-/react-native-draggable-switch-1.1.1.tgz",

1
package.json

@ -36,6 +36,7 @@ @@ -36,6 +36,7 @@
"react-native-calendars": "^1.1274.0",
"react-native-date-picker": "^3.4.3",
"react-native-device-info": "^8.3.3",
"react-native-document-picker": "^8.0.0",
"react-native-draggable-switch": "^1.1.1",
"react-native-drawer": "^2.5.1",
"react-native-expire-storage": "0.0.3",

6
src/api/chats/requests.interface.ts

@ -1,3 +1,4 @@ @@ -1,3 +1,4 @@
import { IFile } from "@/shared";
import { AxiosRequestConfig } from "axios";
import { IRequestConfig } from "../http.service";
@ -28,4 +29,9 @@ export interface ISetChatMuted { @@ -28,4 +29,9 @@ export interface ISetChatMuted {
export interface ISendTextMessage {
chatId: number
message: string
}
export interface ISendFileMessage {
chatId: number
files: IFile[]
}

43
src/api/chats/requests.ts

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
import { IRequestConfig } from '@/api/http.service'
import { Platform } from 'react-native'
import http from '../http.service'
import { ApiResponse } from '../http.types'
import * as req from './requests.interface'
@ -47,3 +48,45 @@ export const sendTextMessageReq = ( @@ -47,3 +48,45 @@ export const sendTextMessageReq = (
): ApiResponse<void> => {
return http.post<void>('chats-messages/text-message', data)
}
export const sendFileMessageReq = (
data: req.ISendFileMessage,
): ApiResponse<void> => {
const formData = createFormData(data)
return http.post<void>('chats-messages/file-message', formData)
}
export const sendImageMessageReq = (
data: req.ISendFileMessage,
): ApiResponse<void> => {
const formData = createFormData(data)
return http.post<void>('chats-messages/image-message', formData)
}
export const sendVideoMessageReq = (
data: req.ISendFileMessage,
): ApiResponse<void> => {
const formData = createFormData(data)
return http.post<void>('chats-messages/video-message', formData)
}
export const sendAudioMessageReq = (
data: req.ISendFileMessage,
): ApiResponse<void> => {
const formData = createFormData(data)
return http.post<void>('chats-messages/audio-message', formData)
}
const createFormData = (data: req.ISendFileMessage) => {
const formData = new FormData()
formData.append('chatId', data.chatId.toString())
data.files.map(it => {
const dataToSave = {
uri: Platform.OS=='ios' ? it.uri.replace("file://", "/") : it.uri,
name: it.name,
type: it.type }
formData.append('files', dataToSave as any )
})
return formData
}

36
src/modules/chats/atoms/attachments-menu.atom.tsx

@ -0,0 +1,36 @@ @@ -0,0 +1,36 @@
import { $size, useTheme } from '@/shared'
import { PartialTheme } from '@/shared/themes/interfaces'
import React from 'react'
import { View, StyleSheet } from 'react-native'
import { AttachmentsMenuItem } from '../components'
import { attachmentsMenuConfig } from '../configs'
interface IProps {
isMenuOpen: boolean
onPressItem: (key: string) => void
}
export const AttachmentsMenu = ({ isMenuOpen, onPressItem }: IProps) => {
const { styles } = useTheme(createStyles)
if (!isMenuOpen) return null
return (
<View style={styles.menu}>
{attachmentsMenuConfig.map(it => (
<AttachmentsMenuItem {...it} onPress={onPressItem} />
))}
</View>
)
}
const createStyles = (theme: PartialTheme) =>
StyleSheet.create({
menu: {
flexDirection: 'row',
justifyContent: 'flex-start',
marginLeft: $size(20),
marginTop: $size(10),
marginBottom: $size(20),
},
})

3
src/modules/chats/atoms/index.ts

@ -9,4 +9,5 @@ export * from './send-button' @@ -9,4 +9,5 @@ export * from './send-button'
export * from './chat-header-label.atom'
export * from './chat-header-go-back-btn.atom'
export * from './chat-header-right-btn.atom'
export * from './add-group-photo-btn'
export * from './add-group-photo-btn'
export * from './attachments-menu.atom'

20
src/modules/chats/atoms/send-button.tsx

@ -1,12 +1,24 @@ @@ -1,12 +1,24 @@
import { $size, useTheme } from '@/shared'
import { $size, IconComponent, useTheme } from '@/shared'
import { PartialTheme } from '@/shared/themes/interfaces'
import React from 'react'
import { View, StyleSheet } from 'react-native'
import Svg, { SvgProps, Path } from 'react-native-svg'
import Svg, { Path } from 'react-native-svg'
export const SendButton = (props: SvgProps) => {
export const SendButton = (props: any) => {
const { styles, theme } = useTheme(createStyles)
if (!props.text)
return (
<View style={props.buttonContainerStyle}>
<IconComponent
style={props?.iconStyle}
color={props?.iconColor}
name="microphone-1"
size={$size(25, 27)}
/>
</View>
)
return (
<View style={styles.container}>
<Svg
@ -17,7 +29,7 @@ export const SendButton = (props: SvgProps) => { @@ -17,7 +29,7 @@ export const SendButton = (props: SvgProps) => {
<Path
d="M20.581 11.346 4.745 2.478a.75.75 0 0 0-1.072.906l2.987 8.364a.75.75 0 0 1 0 .504l-2.987 8.364a.75.75 0 0 0 1.072.907l15.836-8.868a.75.75 0 0 0 0-1.31v0ZM6.75 12h6"
stroke={theme?.chats?.message?.$btnSend}
strokeWidth={1.5}
strokeWidth={2}
strokeLinecap="round"
strokeLinejoin="round"
transform={`translate(${$size(1, 2)}, ${$size(

21
src/modules/chats/components/chat-actions.component.tsx

@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
import { $size, IconComponent } from '@/shared'
import React from 'react'
import { View } from 'react-native'
import { Actions } from 'react-native-gifted-chat'
export const renderActions = (props: any) => (
<Actions
{...props}
icon={() => (
<View style={props.buttonContainerStyle}>
<IconComponent
style={props?.iconStyle}
color={props?.iconColor}
name={props.isMenuOpen ? 'x-1' : 'paperclip-1'}
size={props.isMenuOpen ? $size(16, 18) : $size(23, 25)}
/>
</View>
)}
cancelButtonIndex={1}
/>
)

54
src/modules/chats/components/chat-attachments-menu-item.component.tsx

@ -0,0 +1,54 @@ @@ -0,0 +1,54 @@
import { $size, IconComponent, useTheme } from '@/shared'
import { PartialTheme } from '@/shared/themes/interfaces'
import React from 'react'
import { StyleSheet, View, Text, TouchableOpacity } from 'react-native'
interface IProps {
iconName: string
title: string
name: string
onPress: (name: string) => void
}
export const AttachmentsMenuItem = ({
iconName,
title,
name,
onPress,
}: IProps) => {
const { styles, theme } = useTheme(createStyles)
return (
<TouchableOpacity
style={styles.componentContainer}
onPress={() => onPress(name)}>
<View style={styles.iconContainer}>
<IconComponent
color={theme?.chats?.attachmentsMenu?.$icon}
name={iconName}
size={$size(28, 26)}
/>
</View>
<Text style={styles.title}>{title}</Text>
</TouchableOpacity>
)
}
const createStyles = (theme: PartialTheme) =>
StyleSheet.create({
componentContainer: {
flexDirection: 'column',
alignItems: 'center',
marginRight: $size(30),
},
iconContainer: {
backgroundColor: theme?.chats?.attachmentsMenu?.$iconBg,
padding: $size(16, 14),
borderRadius: 15,
},
title: {
marginTop: $size(7, 5),
color: theme?.chats?.attachmentsMenu?.$title,
fontSize: $size(12),
},
})

33
src/modules/chats/components/chat-footer.tsx

@ -4,12 +4,21 @@ import React from 'react' @@ -4,12 +4,21 @@ import React from 'react'
import { ScrollView, StyleSheet, View } from 'react-native'
import { Composer, InputToolbar, Send } from 'react-native-gifted-chat'
import { SendButton } from '../atoms/send-button'
import { renderActions } from './chat-actions.component'
export const NewChatMessageInput = (props: any) => {
const { styles } = useTheme(createStyles)
const { styles, theme } = useTheme(createStyles)
return (
<InputToolbar
{...props}
renderActions={props =>
renderActions({
...props,
buttonContainerStyle: styles.buttonContainer,
iconColor: theme?.chats?.message?.$btnAttach,
iconStyle: styles.icon,
})
}
containerStyle={styles.toolBar}
renderComposer={props => (
<ScrollView style={styles.inputContainer}>
@ -23,9 +32,14 @@ export const NewChatMessageInput = (props: any) => { @@ -23,9 +32,14 @@ export const NewChatMessageInput = (props: any) => {
)}
renderSend={props => {
return (
<View style={styles.buttonContainer}>
<View>
<Send {...props}>
<SendButton />
<SendButton
{...props}
buttonContainerStyle={styles.buttonContainer}
iconColor={theme?.chats?.message?.$btnSend}
iconStyle={styles.icon}
/>
</Send>
</View>
)
@ -47,7 +61,7 @@ const createStyles = (theme: PartialTheme) => @@ -47,7 +61,7 @@ const createStyles = (theme: PartialTheme) =>
borderRadius: 15,
backgroundColor: theme?.chats?.$elementsBg,
marginRight: $size(5),
marginLeft: $size(15),
marginLeft: $size(20),
paddingHorizontal: $size(8),
flexGrow: 5,
},
@ -63,6 +77,13 @@ const createStyles = (theme: PartialTheme) => @@ -63,6 +77,13 @@ const createStyles = (theme: PartialTheme) =>
lineHeight: $size(20),
color: theme?.$secondaryText,
},
buttonContainer: {},
buttonContainer: {
width: $size(33, 33),
height: $size(33, 33),
backgroundColor: theme?.chats?.message?.$bgPrimary,
borderRadius: 100,
justifyContent: 'center',
alignItems: 'center',
},
icon: {},
})

19
src/modules/chats/components/chats-list.component.tsx

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
import { createCardStyles } from '@/modules/tasks/helpers'
import { $size, ChatType, createFullName, IChat } from '@/shared'
import { $size, ChatType, createFullName, IChat, MessageType } from '@/shared'
import { useTheme } from '@/shared/hooks/use-theme.hook'
import { PartialTheme } from '@/shared/themes/interfaces'
import React, { FC } from 'react'
@ -37,11 +37,26 @@ export const ChatsList: FC<IProps> = ({ @@ -37,11 +37,26 @@ export const ChatsList: FC<IProps> = ({
item?.chatMembers[0]?.user?.lastName,
)
const getLastMessageText = () => {
switch (item.lastMessage?.type) {
case MessageType.Text:
return item.lastMessage?.content?.message
case MessageType.File:
return 'Файлове повідомлення'
case MessageType.Image:
return 'Зображення'
case MessageType.Audio:
return 'Аудіо повідомлення'
default:
return null
}
}
return (
<SwipableChatRowCardSmart
id={item.id}
label={name}
lastMessage={item.lastMessage?.content?.message}
lastMessage={getLastMessageText()}
previewUrl={previewUrl}
isOnline={false}
isPinned={false}

4
src/modules/chats/components/index.ts

@ -8,4 +8,6 @@ export * from './chat-detail-footer.component' @@ -8,4 +8,6 @@ export * from './chat-detail-footer.component'
export * from './chat-detail-footer-actions.component'
export * from './new-chat-member-list.component'
export * from './chat-member-item-row.component'
export * from './create-chat-header.component'
export * from './create-chat-header.component'
export * from './chat-actions.component'
export * from './chat-attachments-menu-item.component'

17
src/modules/chats/configs/attachments-menu.config.ts

@ -0,0 +1,17 @@ @@ -0,0 +1,17 @@
export const attachmentsMenuConfig = [
{
iconName: 'camera-1',
title: 'Камера',
name: 'camera'
},
{
iconName: 'image-1',
title: 'Галерея',
name: 'gallery'
},
{
iconName: 'filetext-1',
title: 'Файл',
name: 'file'
},
]

3
src/modules/chats/configs/index.ts

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
export * from './chat-card-buttons.config'
export * from './data-message'
export * from './member-card-btns.config'
export * from './chat-details-footer-btns.config'
export * from './chat-details-footer-btns.config'
export * from './attachments-menu.config'

3
src/modules/chats/hooks/index.ts

@ -3,4 +3,5 @@ export * from './use-chat-details.hook' @@ -3,4 +3,5 @@ export * from './use-chat-details.hook'
export * from './use-edit-group-chat.hook'
export * from './use-chat-members.hook'
export * from './use-chat-messages.hook'
export * from './use-create-chat.hook'
export * from './use-create-chat.hook'
export * from './use-send-files.hook'

5
src/modules/chats/hooks/use-chat-messages.hook.ts

@ -5,7 +5,8 @@ import { useState, useEffect } from 'react' @@ -5,7 +5,8 @@ import { useState, useEffect } from 'react'
export const useChatMessages = (chatId: number) => {
const [isShowLoadEarlier, setShowLoadEarlier] = useState<boolean>(false)
const [message, setMessage] = useState<string>('')
const [message, setMessage] = useState<string>('')
const nav = useNav()
const {
@ -49,7 +50,7 @@ export const useChatMessages = (chatId: number) => { @@ -49,7 +50,7 @@ export const useChatMessages = (chatId: number) => {
const messagesContainsItem = (itemId: number) => _.find(messages, message => message.id === itemId)
const onNewMessage = (data: { message: IChatMessage }) => {
if (data?.message?.chatId === chatId && !messagesContainsItem(data?.message?.id)) {
if (Number(data?.message?.chatId) === chatId && !messagesContainsItem(data?.message?.id)) {
_setItems([data?.message, ...messages])
}
}

97
src/modules/chats/hooks/use-send-files.hook.ts

@ -0,0 +1,97 @@ @@ -0,0 +1,97 @@
import { chatMessagesService } from '@/services/domain'
import { mediaService } from '@/services/system/media.service'
import _ from 'lodash'
import { Alert, Platform } from 'react-native'
import { Image } from 'react-native-image-crop-picker'
import {DocumentPickerResponse} from 'react-native-document-picker'
const MAX_FILE_SIZE = 52428800
export const useSendFiles = () => {
const getName = image => {
if (Platform.OS === 'ios') return image.filename
try {
return String(image.path).split('/').reverse()[0]
} catch (e) {
return 'avatar.jpg'
}
}
const checkFileSizeAllowed = (files: (Image | DocumentPickerResponse)[]) => {
if (_.every(files, file => file.size <= MAX_FILE_SIZE)) return true
Alert.alert('Не вдалось віправити файл. Розмір файла не повинен перевищувати 50 мб')
return false
}
const handlePressGallery = async () => {
const selected = await mediaService.openMultiplePicker()
const allowed = checkFileSizeAllowed(selected)
if (!allowed) return null
const prepared = selected.map(it => ({
name: getName(it),
type: it.mime,
uri:
Platform.OS === 'android'
? it.path
: it.path.replace('file://', ''),
}))
return prepared
}
const handlePressFile = async () => {
const selected = await mediaService.openFilesPicker()
const allowed = checkFileSizeAllowed(selected)
if (!allowed) return null
const prepared = selected.map(it => ({
name: it.name,
type: it.type,
uri: it.uri,
}))
return prepared
}
const handlePressCamera = async () => {
const selected: any = await mediaService.openCamera()
const allowed = checkFileSizeAllowed(selected)
if (!allowed) return null
const prepared = {
name: getName(selected),
type: selected.mime,
uri:
Platform.OS === 'android'
? selected.path
: selected.path.replace('file://', ''),
}
return [prepared]
}
const handlePressMenuItem = async (name: string, chatId: number) => {
const menuHandler = {
gallery: handlePressGallery,
camera: handlePressCamera,
file: handlePressFile,
}
const apiRequest = {
gallery: chatMessagesService.sendImageMessage,
camera: chatMessagesService.sendImageMessage,
file: chatMessagesService.sendFileMessage,
}
const files = await menuHandler[name]()
if (_.isEmpty(files)) return
await apiRequest[name]({
chatId,
files,
})
}
return {
handlePressMenuItem,
}
}

117
src/modules/chats/screens/chat.tsx

@ -7,25 +7,27 @@ import { @@ -7,25 +7,27 @@ import {
KeyboardSpacer,
useTheme,
} from '@/shared'
import React, { FC } from 'react'
import { GiftedChat } from 'react-native-gifted-chat'
import React, { FC, useState } from 'react'
import { GiftedChat, MessageImage } from 'react-native-gifted-chat'
import { NewChatMessageInput } from '@/modules/chats/components'
import { ChatMessage } from '@/modules/chats/components/'
import { BubbleMessage } from '@/modules/chats/atoms'
import { useChatDetails, useChatMessages } from '../hooks'
import { AttachmentsMenu, BubbleMessage } from '@/modules/chats/atoms'
import { useChatDetails, useChatMessages, useSendFiles } from '../hooks'
import { useSelector } from 'react-redux'
import { selectSelectedChatId } from '@/store/chats'
import { ChatLayout } from '../layouts'
import { transformMessages } from '../transforms'
import { selectId } from '@/store/account'
import { View, Text, StyleSheet } from 'react-native'
import { View, Text, StyleSheet, Keyboard } from 'react-native'
import { PartialTheme } from '@/shared/themes/interfaces'
import { chatMessagesService } from '@/services/domain'
interface IProps extends IRouteParams {}
export const ChatConversation: FC<IProps> = ({ navigation }) => {
const accountId = useSelector(selectId)
const selectedChatId = useSelector(selectSelectedChatId)
const [isMenuOpen, setMenuOpen] = useState(false)
const { styles } = useTheme(createStyles)
@ -39,10 +41,11 @@ export const ChatConversation: FC<IProps> = ({ navigation }) => { @@ -39,10 +41,11 @@ export const ChatConversation: FC<IProps> = ({ navigation }) => {
loadMore,
setNewMessage,
newMessage,
setMessages,
sendMessage,
} = useChatMessages(selectedChatId)
const { handlePressMenuItem } = useSendFiles()
const renderAvatar = props => {
return (
<Avatar
@ -53,46 +56,80 @@ export const ChatConversation: FC<IProps> = ({ navigation }) => { @@ -53,46 +56,80 @@ export const ChatConversation: FC<IProps> = ({ navigation }) => {
)
}
const onPressMenuItem = async (name: string) => {
setMenuOpen(false)
await handlePressMenuItem(name, selectedChatId)
}
return (
<ChatLayout
navigation={navigation}
isLoading={isLoading}
chatInfo={headerChatInfo}>
<GiftedChat
text={newMessage}
timeFormat="HH:mm"
dateFormat="DD.MM.YY"
loadEarlier={isShowLoadEarlier}
isLoadingEarlier={isLoadingNext}
onLoadEarlier={loadMore}
onInputTextChanged={text => setNewMessage(text)}
messages={transformMessages(
messages,
chatDetails?.chatMembers,
accountId,
)}
onSend={sendMessage}
alwaysShowSend={true}
renderBubble={props => <BubbleMessage {...props} />}
renderAvatarOnTop={true}
bottomOffset={0}
renderAvatar={renderAvatar}
renderInputToolbar={props => <NewChatMessageInput {...props} />}
renderChatEmpty={() => (
<View style={styles.emptyContainer}>
<Text style={styles.emptyText}>Повідомлень нема</Text>
</View>
)}
renderMessageText={props => <ChatMessage {...props} />}
user={{
_id: accountId,
}}
/>
<>
<GiftedChat
text={newMessage}
timeFormat="HH:mm"
dateFormat="DD.MM.YY"
loadEarlier={isShowLoadEarlier}
isLoadingEarlier={isLoadingNext}
onLoadEarlier={loadMore}
onInputTextChanged={text => setNewMessage(text)}
messages={transformMessages(
messages,
chatDetails?.chatMembers,
accountId,
)}
onSend={sendMessage}
alwaysShowSend={true}
renderBubble={props => <BubbleMessage {...props} />}
renderAvatarOnTop={true}
bottomOffset={0}
renderAvatar={renderAvatar}
renderInputToolbar={props => (
<NewChatMessageInput
{...props}
isMenuOpen={isMenuOpen}
onPressMenuItem={onPressMenuItem}
/>
)}
onPressActionButton={() => {
if (!isMenuOpen) Keyboard.dismiss()
setMenuOpen(!isMenuOpen)
}}
renderChatEmpty={() => (
<View style={styles.emptyContainer}>
<Text style={styles.emptyText}>
Повідомлень нема
</Text>
</View>
)}
renderMessageText={props => <ChatMessage {...props} />}
// renderMessageImage={props => (
// <MessageImage
// {...props}
// containerStyle={{
// marginBottom: 5,
// }}
// imageStyle={{
// height: 240,
// width: 200,
// // resizeMode: 'contain',
// }}
// />
// )}
user={{
_id: accountId,
}}
/>
<KeyboardSpacer
style={styles.keyboard}
heightSpace={isAndroid(30, $size(30, 20))}
/>
<KeyboardSpacer heightSpace={isAndroid(30, $size(30, 20))} />
<AttachmentsMenu
isMenuOpen={isMenuOpen}
onPressItem={onPressMenuItem}
/>
</>
</ChatLayout>
)
}

3
src/modules/chats/transforms/chat-messages.transforms.ts

@ -37,7 +37,8 @@ export const transformMessage = ( @@ -37,7 +37,8 @@ export const transformMessage = (
return {
_id: item.id,
text: item.content?.message,
image: item.type === MessageType.File && item.content?.fileUrl,
image: item.type === MessageType.Image && item.content?.fileUrl,
video: item.type === MessageType.Video && item.content?.fileUrl,
audio: item.type === MessageType.Audio && item.content?.fileUrl,
createdAt: new Date(item.createdAt),
user: {

67
src/services/domain/chat-messages.service.ts

@ -1,27 +1,56 @@ @@ -1,27 +1,56 @@
import { getChatMessagesListReq, sendTextMessageReq } from "@/api"
import { IFetchChatMessages, ISendTextMessage } from "@/api/chats/requests.interface"
import { IFetchChatMessagesList } from "@/api/chats/responses.interfaces"
import { ApiResponse } from "@/api/http.types"
import {
getChatMessagesListReq,
sendFileMessageReq,
sendImageMessageReq,
sendTextMessageReq,
} from '@/api'
import {
IFetchChatMessages,
ISendFileMessage,
ISendTextMessage,
} from '@/api/chats/requests.interface'
import { IFetchChatMessagesList } from '@/api/chats/responses.interfaces'
import { ApiResponse } from '@/api/http.types'
const fetchMessages = async (params: IFetchChatMessages): ApiResponse<IFetchChatMessagesList> => {
try {
const resp = await getChatMessagesListReq(params)
const fetchMessages = async (
params: IFetchChatMessages,
): ApiResponse<IFetchChatMessagesList> => {
try {
const resp = await getChatMessagesListReq(params)
return resp
} catch (err) {
console.log(err)
}
return resp
} catch (err) {
console.log(err)
}
}
const sendTextMessage = async(data: ISendTextMessage) => {
try {
await sendTextMessageReq(data)
} catch (err) {
console.log('SEND TEXT MESSAGE ERROR', err)
const sendTextMessage = async (data: ISendTextMessage) => {
try {
await sendTextMessageReq(data)
} catch (err) {
console.log('SEND TEXT MESSAGE ERROR', err)
}
}
const sendFileMessage = async (data: ISendFileMessage) => {
try {
await sendFileMessageReq(data)
} catch (err) {
console.log('SEND FILE MESSAGE ERROR', err)
}
}
const sendImageMessage = async (data: ISendFileMessage) => {
try {
await sendImageMessageReq(data)
} catch (err) {
console.log('SEND IMAGE MESSAGE ERROR', err)
}
}
export const chatMessagesService = {
fetchMessages,
sendTextMessage
}
fetchMessages,
sendTextMessage,
sendFileMessage,
sendImageMessage
}

30
src/services/system/media.service.ts

@ -3,6 +3,7 @@ import ImagePicker from 'react-native-image-crop-picker' @@ -3,6 +3,7 @@ import ImagePicker from 'react-native-image-crop-picker'
import { launchImageLibrary } from 'react-native-image-picker'
import { PERMISSIONS } from 'react-native-permissions'
import { mediaPermissionsService } from './media-permissions.service'
import DocumentPicker from 'react-native-document-picker'
interface IPickerProps {
width: number,
@ -66,6 +67,33 @@ const openCropPicker = async ({ cropperCircleOverlay = false, ...props }: IPicke @@ -66,6 +67,33 @@ const openCropPicker = async ({ cropperCircleOverlay = false, ...props }: IPicke
return img
}
const openMultiplePicker = async () => {
const hasPermissions = await mediaPermissionsService.checkCameraPermissions(
permissions.gallery,
)
if (!hasPermissions) return null
const imgs = await ImagePicker.openPicker({
multiple: true,
includeBase64: true,
mediaType: 'photo',
size: 50000000
})
return imgs
}
const openFilesPicker = async () => {
const hasPermissions = await mediaPermissionsService.checkCameraPermissions(
permissions.gallery,
)
if (!hasPermissions) return null
const files = await DocumentPicker.pickMultiple()
return files
}
const openGalleryPicker = async () => {
const hasPermissions = await mediaPermissionsService.checkCameraPermissions(
permissions.gallery,
@ -86,4 +114,6 @@ export const mediaService = { @@ -86,4 +114,6 @@ export const mediaService = {
openCamera,
openCropPicker,
openGalleryPicker,
openMultiplePicker,
openFilesPicker
}

2
src/shared/enums/chat.enums.ts

@ -12,6 +12,8 @@ export enum MessageType { @@ -12,6 +12,8 @@ export enum MessageType {
Text = 't',
File = 'f',
Audio = 'a',
Video = 'v',
Image = 'i',
Forwarded = 'fwd',
MissedCall = 'mc',
SuccessCall = 'sc',

3
src/shared/interfaces/index.ts

@ -10,4 +10,5 @@ export * from './comments.interfaces' @@ -10,4 +10,5 @@ export * from './comments.interfaces'
export * from './factories.interfaces'
export * from './options.interfaces'
export * from './notification.interfaces'
export * from './chats.interfaces'
export * from './chats.interfaces'
export * from './media.interfaces'

5
src/shared/interfaces/media.interfaces.ts

@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
export interface IFile {
uri: string
type: string
name: string
}

7
src/shared/themes/dark/chat.ts

@ -12,6 +12,11 @@ export const chatColors: ChatColors = { @@ -12,6 +12,11 @@ export const chatColors: ChatColors = {
$bg: '#38B362',
$border: colors.$primary,
},
attachmentsMenu: {
$icon: '#FFFFFF',
$iconBg: '#1F1F1F',
$title: '#7F7F7F'
},
rowCard: {
newMessageIndicator: {
$bg: '#DE253B',
@ -40,7 +45,7 @@ export const chatColors: ChatColors = { @@ -40,7 +45,7 @@ export const chatColors: ChatColors = {
$timeMessage: '#FFFFFF',
$ticks: '#DE253B',
$btnSend: '#FFFFFF',
$btnAttach: '#FFFFFF'
}
},

8
src/shared/themes/interfaces/chat.interface.ts

@ -8,6 +8,11 @@ export interface ChatColors { @@ -8,6 +8,11 @@ export interface ChatColors {
$bg: string
$border: string
}
attachmentsMenu: {
$icon: string,
$iconBg: string,
$title: string
}
rowCard: {
newMessageIndicator: {
$bg: string
@ -35,8 +40,7 @@ export interface ChatColors { @@ -35,8 +40,7 @@ export interface ChatColors {
$timeMessage: string
$ticks: string
$btnSend: string
$btnAttach: string
}
},

8
src/shared/themes/light/chat.ts

@ -10,6 +10,11 @@ export const chatColors: ChatColors = { @@ -10,6 +10,11 @@ export const chatColors: ChatColors = {
$bg: '#38B362',
$border: '#ffffff',
},
attachmentsMenu: {
$icon: '#7F7F7F',
$iconBg: '#FFFFFF',
$title: '#7F7F7F'
},
rowCard: {
newMessageIndicator: {
$bg: '#9E2843',
@ -37,7 +42,8 @@ export const chatColors: ChatColors = { @@ -37,7 +42,8 @@ export const chatColors: ChatColors = {
$content: '#3B3B3B',
$timeMessage: '#7F7F7F',
$ticks: '#7F7F7F',
$btnSend: '#9F2843'
$btnSend: '#9F2843',
$btnAttach: '#9F2843'
}
},

Loading…
Cancel
Save