@messenger-box/platform-mobile 0.0.1-alpha.190 → 0.0.1-alpha.197
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +508 -203
- package/lib/index.js.map +1 -1
- package/lib/navigation/InboxNavigation.d.ts +3 -1
- package/lib/screens/inbox/DialogMessages.d.ts +3 -1
- package/lib/screens/inbox/Inbox.d.ts +2 -0
- package/lib/screens/inbox/components/CommonMessage.d.ts +9 -0
- package/lib/screens/inbox/components/DialogsListItem.d.ts +5 -4
- package/lib/screens/inbox/components/FilesList.d.ts +13 -0
- package/lib/screens/inbox/components/MessageInput.d.ts +6 -1
- package/lib/screens/inbox/components/MessageItem.d.ts +5 -8
- package/lib/screens/inbox/components/PlainMessage.d.ts +6 -0
- package/lib/screens/inbox/config/config.d.ts +4 -0
- package/lib/screens/inbox/config/index.d.ts +1 -0
- package/lib/screens/inbox/containers/Dialogs.d.ts +5 -1
- package/lib/screens/index.d.ts +1 -0
- package/package.json +4 -4
- package/src/index.ts +1 -0
- package/src/navigation/InboxNavigation.tsx +9 -20
- package/src/screens/inbox/DialogMessages.tsx +2 -7
- package/src/screens/inbox/{DialogsList.tsx → Inbox.tsx} +4 -4
- package/src/screens/inbox/components/CommonMessage.tsx +52 -0
- package/src/screens/inbox/components/DialogsListItem.tsx +63 -44
- package/src/screens/inbox/components/FilesList.tsx +41 -0
- package/src/screens/inbox/components/MessageInput.tsx +24 -22
- package/src/screens/inbox/components/MessageItem.tsx +34 -55
- package/src/screens/inbox/components/PlainMessage.tsx +16 -0
- package/src/screens/inbox/config/config.ts +6 -0
- package/src/screens/inbox/config/index.ts +1 -0
- package/src/screens/inbox/containers/ConversationView.tsx +158 -83
- package/src/screens/inbox/containers/Dialogs.tsx +93 -48
- package/src/screens/index.ts +1 -0
- package/lib/screens/inbox/DialogsList.d.ts +0 -2
- package/lib/screens/inbox/components/DialogsHeader.d.ts +0 -8
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import { Text, Box, Image, Pressable, HStack, VStack } from 'native-base';
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
|
+
import { Text, Image, Pressable, HStack, Box } from 'native-base';
|
|
4
3
|
import { format, isToday, isYesterday } from 'date-fns';
|
|
5
|
-
|
|
4
|
+
|
|
5
|
+
import { IChannel, IUserAccount, useMessagesQuery, useUserAccountQuery } from '@messenger-box/platform-client';
|
|
6
6
|
|
|
7
7
|
const createdAtText = (value: string) => {
|
|
8
8
|
if (!value) return '';
|
|
@@ -17,10 +17,11 @@ export interface IDialogListChannel extends IChannel {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
export interface IDialogListItemProps {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
currentUser?: any;
|
|
21
|
+
users?: any;
|
|
22
|
+
selectedChannelId?: any;
|
|
23
|
+
channel?: any;
|
|
24
|
+
onOpen: (id: any) => void;
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
/**
|
|
@@ -29,61 +30,79 @@ export interface IDialogListItemProps {
|
|
|
29
30
|
* - Add ability to get property information: name, logo
|
|
30
31
|
*/
|
|
31
32
|
export const DialogsListItem: React.FC<IDialogListItemProps> = function DialogsListItem({
|
|
32
|
-
|
|
33
|
+
currentUser,
|
|
34
|
+
users,
|
|
35
|
+
selectedChannelId,
|
|
33
36
|
channel,
|
|
34
|
-
currentUserId,
|
|
35
37
|
onOpen,
|
|
36
38
|
}) {
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
39
|
+
const { data: messagesQuery, loading: messageLoading } = useMessagesQuery({
|
|
40
|
+
variables: {
|
|
41
|
+
channelId: channel?.id?.toString(),
|
|
42
|
+
limit: 1,
|
|
43
|
+
},
|
|
44
|
+
fetchPolicy: 'cache-and-network',
|
|
40
45
|
});
|
|
41
46
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
[users],
|
|
47
|
+
const chatUser = useMemo(
|
|
48
|
+
() =>
|
|
49
|
+
users?.find(({ id }) => {
|
|
50
|
+
const isNotCurrentUser = id !== currentUser?.id;
|
|
51
|
+
if (isNotCurrentUser) {
|
|
52
|
+
return channel?.members?.find(({ user }: any) => user.id === id);
|
|
53
|
+
}
|
|
54
|
+
return isNotCurrentUser;
|
|
55
|
+
}),
|
|
56
|
+
[users, currentUser, channel],
|
|
53
57
|
);
|
|
54
58
|
|
|
55
|
-
const
|
|
56
|
-
|
|
59
|
+
const { data: userQuery } = useUserAccountQuery({
|
|
60
|
+
variables: {
|
|
61
|
+
userId: chatUser?.id,
|
|
62
|
+
},
|
|
63
|
+
skip: !chatUser?.id,
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
const lastMessage = useMemo(() => {
|
|
67
|
+
if (!messagesQuery?.messages?.data?.length) {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
const { data } = messagesQuery.messages;
|
|
71
|
+
return data[data.length - 1];
|
|
72
|
+
}, [messagesQuery]);
|
|
57
73
|
|
|
58
|
-
const
|
|
74
|
+
const channelType = useMemo(() => {
|
|
75
|
+
return channel?.type;
|
|
76
|
+
}, [channel]);
|
|
59
77
|
|
|
60
78
|
return (
|
|
61
|
-
<Pressable
|
|
62
|
-
|
|
79
|
+
<Pressable
|
|
80
|
+
onPress={() => channel?.id !== selectedChannelId && onOpen(channel?.id)}
|
|
81
|
+
borderWidth={'1'}
|
|
82
|
+
borderRadius={10}
|
|
83
|
+
borderColor={'gray.200'}
|
|
84
|
+
shadow={'6'}
|
|
85
|
+
>
|
|
86
|
+
<HStack m={3} space={2}>
|
|
63
87
|
<Image
|
|
64
88
|
alt={'image'}
|
|
65
89
|
width={16}
|
|
66
|
-
borderRadius=
|
|
90
|
+
borderRadius={10}
|
|
67
91
|
height={16}
|
|
68
|
-
source={{ uri: 'https://picsum.photos/220' }}
|
|
92
|
+
source={{ uri: userQuery?.getUserAccount?.picture || 'https://picsum.photos/220' }}
|
|
69
93
|
/>
|
|
70
|
-
<
|
|
94
|
+
<Box width={'80%'}>
|
|
71
95
|
<HStack alignItems="center" justifyContent="space-between">
|
|
72
|
-
{/* TODO: change to valid status */}
|
|
73
96
|
<Text fontSize="xs" color="red.500">
|
|
74
|
-
|
|
97
|
+
{channelType}
|
|
75
98
|
</Text>
|
|
76
|
-
<Text color="gray.500">{
|
|
99
|
+
<Text color="gray.500">{lastMessage ? createdAtText(lastMessage?.createdAt) : ''}</Text>
|
|
77
100
|
</HStack>
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
<Text color="gray.600">{text}</Text>
|
|
84
|
-
{/* TODO: change to valid reservation date */}
|
|
85
|
-
<Text>Sep 12-16, 2019. Private room fully furnis...</Text>
|
|
86
|
-
</VStack>
|
|
101
|
+
<Text color="gray.600" fontSize="lg" fontWeight="semibold">
|
|
102
|
+
{chatUser?.givenName + ' ' + chatUser?.familyName}
|
|
103
|
+
</Text>
|
|
104
|
+
<Text color="gray.600">{lastMessage?.message}</Text>
|
|
105
|
+
</Box>
|
|
87
106
|
</HStack>
|
|
88
107
|
</Pressable>
|
|
89
108
|
);
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
|
+
import { Image, HStack, Box } from 'native-base';
|
|
3
|
+
|
|
4
|
+
interface FilesListProps {
|
|
5
|
+
files: any;
|
|
6
|
+
uploaded?: boolean;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function FilesList({ files, uploaded = false }: FilesListProps) {
|
|
10
|
+
return (
|
|
11
|
+
<HStack space={2} mt={2}>
|
|
12
|
+
<FilesList.FilesView files={files} uploaded={uploaded} />
|
|
13
|
+
</HStack>
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
FilesList.FilesView = function MessageItemFiles({ files = [], uploaded }: { files: any[]; uploaded?: boolean }) {
|
|
18
|
+
if (!files.length) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<Box>
|
|
24
|
+
{files.map((file) => {
|
|
25
|
+
const url = useMemo(() => (uploaded ? file.url : URL.createObjectURL(file)), [file, uploaded]);
|
|
26
|
+
return (
|
|
27
|
+
<Image
|
|
28
|
+
alt={'image'}
|
|
29
|
+
mr={2}
|
|
30
|
+
height="16"
|
|
31
|
+
width="16"
|
|
32
|
+
source={{
|
|
33
|
+
uri: url,
|
|
34
|
+
scale: 0.2,
|
|
35
|
+
}}
|
|
36
|
+
/>
|
|
37
|
+
);
|
|
38
|
+
})}
|
|
39
|
+
</Box>
|
|
40
|
+
);
|
|
41
|
+
};
|
|
@@ -1,23 +1,29 @@
|
|
|
1
|
-
import { TextField, View, Image, Pressable, HStack, VStack } from 'native-base';
|
|
1
|
+
import { TextField, View, Image, Pressable, HStack, VStack, Toast } from 'native-base';
|
|
2
2
|
import { FontAwesome } from '@expo/vector-icons';
|
|
3
3
|
import * as ImagePicker from 'expo-image-picker';
|
|
4
|
-
import React, { forwardRef, useImperativeHandle, useState } from 'react';
|
|
4
|
+
import React, { forwardRef, useImperativeHandle, useState, useCallback } from 'react';
|
|
5
|
+
import { FilesList } from './FilesList';
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
type MessageInputProps = {
|
|
8
|
+
channelId?: string;
|
|
9
|
+
handleSend: (message: string, files: any) => Promise<void>;
|
|
10
|
+
};
|
|
9
11
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
export const MessageInput = forwardRef(function MessageInput({ handleSend: handleSendProp }: MessageInputProps) {
|
|
13
|
+
const [message, setMessage] = useState('');
|
|
14
|
+
const [sending, setSending] = useState(false);
|
|
15
|
+
const [files, setFiles] = useState<File[]>([]);
|
|
14
16
|
|
|
15
|
-
|
|
17
|
+
const handleSend = useCallback(() => {
|
|
18
|
+
setSending(true);
|
|
19
|
+
handleSendProp(message, files)
|
|
20
|
+
.then(() => {
|
|
21
|
+
setMessage('');
|
|
22
|
+
setFiles([]);
|
|
23
|
+
})
|
|
24
|
+
.finally(() => setSending(false));
|
|
25
|
+
}, [files, handleSendProp, message]);
|
|
16
26
|
|
|
17
|
-
const onSendMessage = () => {
|
|
18
|
-
onSend(text, files);
|
|
19
|
-
};
|
|
20
|
-
const onRemoveImage = (url: string) => setFiles((files) => files.filter((file) => file !== url));
|
|
21
27
|
const onSelectImages = async () => {
|
|
22
28
|
// No permissions request is necessary for launching the image library
|
|
23
29
|
await ImagePicker.requestMediaLibraryPermissionsAsync();
|
|
@@ -38,23 +44,19 @@ export const MessageInput = forwardRef(function MessageInput({ onSend }: any, re
|
|
|
38
44
|
<TextField
|
|
39
45
|
placeholder="Message..."
|
|
40
46
|
borderColor="gray.400"
|
|
41
|
-
value={
|
|
42
|
-
onChange={(e) =>
|
|
47
|
+
value={sending ? '' : message}
|
|
48
|
+
onChange={(e) => setMessage(e.nativeEvent.text)}
|
|
43
49
|
fontSize={14}
|
|
44
50
|
/>
|
|
45
51
|
</View>
|
|
46
52
|
{files.length ? (
|
|
47
53
|
<View mb={4} flexDirection="row">
|
|
48
|
-
{files
|
|
49
|
-
<Pressable onPress={() => onRemoveImage(file)} key={index}>
|
|
50
|
-
<Image alt={'image'} mr={2} height={10} width={10} source={{ uri: file }} />
|
|
51
|
-
</Pressable>
|
|
52
|
-
))}
|
|
54
|
+
<FilesList files={files} />
|
|
53
55
|
</View>
|
|
54
56
|
) : null}
|
|
55
57
|
<HStack alignContent="center" justifyContent="space-between">
|
|
56
58
|
<FontAwesome onPress={onSelectImages} size={20} style={{ marginRight: 5 }} name="file-image-o" />
|
|
57
|
-
<FontAwesome onPress={
|
|
59
|
+
<FontAwesome onPress={handleSend} size={20} name="send" />
|
|
58
60
|
</HStack>
|
|
59
61
|
</VStack>
|
|
60
62
|
);
|
|
@@ -1,62 +1,41 @@
|
|
|
1
|
-
import React
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Box } from 'native-base';
|
|
3
|
+
import { IPost, IPostTypeEnum } from '@messenger-box/platform-client';
|
|
4
|
+
import { PlainMessage } from './PlainMessage';
|
|
5
|
+
import { CommonMessage } from './CommonMessage';
|
|
6
|
+
import { Slot } from '@common-stack/components-pro';
|
|
5
7
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
export function MessageItem({
|
|
9
|
+
message,
|
|
10
|
+
channelId,
|
|
11
|
+
currentUser,
|
|
12
|
+
totalCount,
|
|
13
|
+
}: {
|
|
14
|
+
message: IPost;
|
|
15
|
+
channelId: number;
|
|
16
|
+
currentUser: any;
|
|
17
|
+
totalCount: number;
|
|
18
|
+
}) {
|
|
19
|
+
if (typeof message === 'string') {
|
|
20
|
+
return <PlainMessage message={message} />;
|
|
21
|
+
}
|
|
13
22
|
|
|
14
|
-
|
|
15
|
-
const isOwnMessage = useMemo(() => message.editedBy?.alias?.includes(userId) || false, [message.author, userId]);
|
|
16
|
-
const author = useMemo(
|
|
17
|
-
() => (message.author ? `${message.author?.givenName} ${message.author?.familyName}` : null),
|
|
18
|
-
[message.author],
|
|
19
|
-
);
|
|
23
|
+
const { type } = message;
|
|
20
24
|
|
|
21
|
-
|
|
22
|
-
<
|
|
23
|
-
{isOwnMessage ? <Box flexGrow={1} /> : null}
|
|
24
|
-
<Box borderRadius="md" backgroundColor="gray.200" paddingX={3} paddingY="1.5" flexGrow={3}>
|
|
25
|
-
<Box flexDirection="row" alignContent="flex-start" mb={1}>
|
|
26
|
-
<Text flexGrow={1} fontWeight="semibold">
|
|
27
|
-
{author}
|
|
28
|
-
</Text>
|
|
29
|
-
<Text fontSize="xs" color="gray.500">
|
|
30
|
-
{createdAtText(message.createdAt)}
|
|
31
|
-
</Text>
|
|
32
|
-
</Box>
|
|
33
|
-
<Text flexGrow={1}>{message.message}</Text>
|
|
34
|
-
<MessageItem.FilesView files={message.files?.data as IFileInfo[]} />
|
|
35
|
-
</Box>
|
|
36
|
-
{!isOwnMessage ? <Box flexGrow={1} /> : null}
|
|
37
|
-
</HStack>
|
|
38
|
-
);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
MessageItem.FilesView = function MessageItemFiles({ files = [] }: { files: IFileInfo[] }) {
|
|
42
|
-
if (!files.length) {
|
|
43
|
-
return null;
|
|
25
|
+
if (!type || type === IPostTypeEnum.Simple) {
|
|
26
|
+
return <CommonMessage message={message} currentUser={currentUser} />;
|
|
44
27
|
}
|
|
45
28
|
|
|
46
29
|
return (
|
|
47
|
-
<
|
|
48
|
-
{
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}}
|
|
58
|
-
/>
|
|
59
|
-
))}
|
|
60
|
-
</HStack>
|
|
30
|
+
<Slot
|
|
31
|
+
name={(type as string)?.toLowerCase()}
|
|
32
|
+
fillProps={{
|
|
33
|
+
active: true,
|
|
34
|
+
message,
|
|
35
|
+
currentUser,
|
|
36
|
+
}}
|
|
37
|
+
>
|
|
38
|
+
{(item) => <Box>{item}</Box>}
|
|
39
|
+
</Slot>
|
|
61
40
|
);
|
|
62
|
-
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Flex, Text } from 'native-base';
|
|
3
|
+
|
|
4
|
+
interface IPlainMessageProps {
|
|
5
|
+
message: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const PlainMessage = ({ message }: IPlainMessageProps) => {
|
|
9
|
+
return (
|
|
10
|
+
<Flex w="full" justifyContent={'center'} mb="7">
|
|
11
|
+
<Text fontSize="14px" fontWeight={'bold'}>
|
|
12
|
+
{message}
|
|
13
|
+
</Text>
|
|
14
|
+
</Flex>
|
|
15
|
+
);
|
|
16
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { config } from './config';
|