@webinex/chatify 1.0.0-alpha04 → 1.0.0-alpha06
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/dist/cjs/index.js +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/types/ui/ChatListItem.d.ts +11 -0
- package/dist/cjs/types/ui/Chatify.d.ts +20 -0
- package/dist/cjs/types/ui/Message.d.ts +14 -1
- package/dist/cjs/types/ui/SendingMessage.d.ts +5 -1
- package/dist/cjs/types/ui/index.d.ts +1 -0
- package/dist/css/chatify.css +67 -11
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/types/ui/ChatListItem.d.ts +11 -0
- package/dist/esm/types/ui/Chatify.d.ts +20 -0
- package/dist/esm/types/ui/Message.d.ts +14 -1
- package/dist/esm/types/ui/SendingMessage.d.ts +5 -1
- package/dist/esm/types/ui/index.d.ts +1 -0
- package/dist/index.d.ts +60 -7
- package/package.json +1 -1
- package/src/ui/Aside.tsx +3 -33
- package/src/ui/ChatListItem.tsx +101 -0
- package/src/ui/Chatify.tsx +40 -0
- package/src/ui/Message.tsx +102 -35
- package/src/ui/SendingMessage.tsx +41 -5
- package/src/ui/index.ts +1 -0
- package/src/ui/styles/index.scss +11 -6
- package/dist/cjs/types/ui/MessageMd.d.ts +0 -13
- package/dist/esm/types/ui/MessageMd.d.ts +0 -13
- package/src/ui/MessageMd.tsx +0 -47
|
@@ -1,5 +1,18 @@
|
|
|
1
|
+
import { FC, Ref, RefObject } from 'react';
|
|
1
2
|
import { Message as MessageModel } from '../core';
|
|
2
3
|
export interface MessageProps {
|
|
3
4
|
message: MessageModel;
|
|
4
5
|
}
|
|
5
|
-
export
|
|
6
|
+
export interface MessageBoxProps extends MessageProps {
|
|
7
|
+
containerRef?: Ref<HTMLDivElement>;
|
|
8
|
+
}
|
|
9
|
+
export declare const MessageAuthor: import("../util").Customizable<FC<MessageProps>, string>;
|
|
10
|
+
export declare const MessageText: import("../util").Customizable<FC<MessageProps>, string>;
|
|
11
|
+
export declare const MessageInfoBox: import("../util").Customizable<FC<MessageProps>, string>;
|
|
12
|
+
export declare const MessageBody: import("../util").Customizable<FC<MessageProps>, string>;
|
|
13
|
+
export declare const MessageBox: import("../util").Customizable<FC<MessageBoxProps>, string>;
|
|
14
|
+
export declare const Message: import("../util").Customizable<FC<MessageProps>, string>;
|
|
15
|
+
export interface MessageReadObserverProps extends MessageProps {
|
|
16
|
+
messageRef: RefObject<HTMLDivElement | null>;
|
|
17
|
+
}
|
|
18
|
+
export declare const MessageReadObserver: import("../util").Customizable<FC<MessageReadObserverProps>, string>;
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
import { FC } from 'react';
|
|
1
2
|
import { File } from '../core';
|
|
2
3
|
export interface SendingMessageProps {
|
|
3
4
|
text: string;
|
|
4
5
|
files: File[];
|
|
5
6
|
}
|
|
6
|
-
export declare
|
|
7
|
+
export declare const SendingMessageText: import("../util").Customizable<FC<SendingMessageProps>, string>;
|
|
8
|
+
export declare const SendingMessageInfoBox: import("../util").Customizable<FC<SendingMessageProps>, string>;
|
|
9
|
+
export declare const SendingMessageBody: import("../util").Customizable<FC<SendingMessageProps>, string>;
|
|
10
|
+
export declare const SendingMessage: import("../util").Customizable<FC<SendingMessageProps>, string>;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { PropsWithChildren, FC, CSSProperties } from 'react';
|
|
1
|
+
import React, { PropsWithChildren, FC, Ref, RefObject, CSSProperties } from 'react';
|
|
2
2
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
3
|
import { AxiosInstance } from 'axios';
|
|
4
4
|
|
|
@@ -45,7 +45,7 @@ interface Account {
|
|
|
45
45
|
name: string;
|
|
46
46
|
avatar: string;
|
|
47
47
|
}
|
|
48
|
-
interface Message {
|
|
48
|
+
interface Message$1 {
|
|
49
49
|
id: string;
|
|
50
50
|
chatId: string;
|
|
51
51
|
text: string;
|
|
@@ -63,7 +63,7 @@ interface Chat {
|
|
|
63
63
|
interface ChatListItem {
|
|
64
64
|
id: string;
|
|
65
65
|
name: string;
|
|
66
|
-
message: Message;
|
|
66
|
+
message: Message$1;
|
|
67
67
|
unreadCount: number;
|
|
68
68
|
}
|
|
69
69
|
interface SendMessageRequest {
|
|
@@ -127,7 +127,7 @@ declare class ChatifyClient {
|
|
|
127
127
|
chatId: string;
|
|
128
128
|
skip?: number;
|
|
129
129
|
take?: number;
|
|
130
|
-
}) => Promise<Message[]>;
|
|
130
|
+
}) => Promise<Message$1[]>;
|
|
131
131
|
send: (request: SendMessageRequest) => Promise<void>;
|
|
132
132
|
read: (request: ReadRequest) => Promise<void>;
|
|
133
133
|
removeMember: (request: RemoveMemberRequest) => Promise<void>;
|
|
@@ -192,7 +192,7 @@ declare const ACTIONS: {
|
|
|
192
192
|
chatId: string;
|
|
193
193
|
}) => State;
|
|
194
194
|
message_received: (state: State, { message, requestId }: {
|
|
195
|
-
message: Message;
|
|
195
|
+
message: Message$1;
|
|
196
196
|
requestId: string;
|
|
197
197
|
}) => State;
|
|
198
198
|
chat_created: (state: State, { chat }: {
|
|
@@ -251,7 +251,7 @@ declare function useLoadMore({ chatId }: {
|
|
|
251
251
|
|
|
252
252
|
type MessageState = ({
|
|
253
253
|
type: 'message';
|
|
254
|
-
} & Message) | {
|
|
254
|
+
} & Message$1) | {
|
|
255
255
|
type: 'more';
|
|
256
256
|
} | {
|
|
257
257
|
type: 'sending';
|
|
@@ -301,6 +301,42 @@ interface ChatNameProps {
|
|
|
301
301
|
}
|
|
302
302
|
declare const ChatName: Customizable<FC<ChatNameProps>, "ChatName">;
|
|
303
303
|
|
|
304
|
+
interface ChatListItemBoxProps {
|
|
305
|
+
chat: ChatListItem;
|
|
306
|
+
}
|
|
307
|
+
declare const ChatListItemName: Customizable<FC<ChatListItemBoxProps>, "ChatListItemName">;
|
|
308
|
+
declare const ChatListItemUnreadCount: Customizable<FC<ChatListItemBoxProps>, "ChatListItemUnreadCount">;
|
|
309
|
+
declare const ChatListItemLastMessage: Customizable<FC<ChatListItemBoxProps>, "ChatListItemLastMessage">;
|
|
310
|
+
declare const ChatListItemLastMessageAuthor: Customizable<FC<ChatListItemBoxProps>, string>;
|
|
311
|
+
declare const ChatListItemLastMessageContent: Customizable<FC<ChatListItemBoxProps>, string>;
|
|
312
|
+
declare const ChatListItemBox: Customizable<FC<ChatListItemBoxProps>, "ChatListItemBox">;
|
|
313
|
+
|
|
314
|
+
interface SendingMessageProps {
|
|
315
|
+
text: string;
|
|
316
|
+
files: File[];
|
|
317
|
+
}
|
|
318
|
+
declare const SendingMessageText: Customizable<FC<SendingMessageProps>, string>;
|
|
319
|
+
declare const SendingMessageInfoBox: Customizable<FC<SendingMessageProps>, string>;
|
|
320
|
+
declare const SendingMessageBody: Customizable<FC<SendingMessageProps>, string>;
|
|
321
|
+
declare const SendingMessage: Customizable<FC<SendingMessageProps>, string>;
|
|
322
|
+
|
|
323
|
+
interface MessageProps {
|
|
324
|
+
message: Message$1;
|
|
325
|
+
}
|
|
326
|
+
interface MessageBoxProps extends MessageProps {
|
|
327
|
+
containerRef?: Ref<HTMLDivElement>;
|
|
328
|
+
}
|
|
329
|
+
declare const MessageAuthor: Customizable<FC<MessageProps>, string>;
|
|
330
|
+
declare const MessageText: Customizable<FC<MessageProps>, string>;
|
|
331
|
+
declare const MessageInfoBox: Customizable<FC<MessageProps>, string>;
|
|
332
|
+
declare const MessageBody: Customizable<FC<MessageProps>, string>;
|
|
333
|
+
declare const MessageBox: Customizable<FC<MessageBoxProps>, string>;
|
|
334
|
+
declare const Message: Customizable<FC<MessageProps>, string>;
|
|
335
|
+
interface MessageReadObserverProps extends MessageProps {
|
|
336
|
+
messageRef: RefObject<HTMLDivElement | null>;
|
|
337
|
+
}
|
|
338
|
+
declare const MessageReadObserver: Customizable<FC<MessageReadObserverProps>, string>;
|
|
339
|
+
|
|
304
340
|
interface ChatifyCustomizeValue {
|
|
305
341
|
Avatar?: typeof Avatar.Component | null;
|
|
306
342
|
Header?: typeof Header.Component | null;
|
|
@@ -309,6 +345,23 @@ interface ChatifyCustomizeValue {
|
|
|
309
345
|
ChatHeaderMembers?: typeof ChatHeaderMembers.Component | null;
|
|
310
346
|
ChatSettingsButton?: typeof ChatSettingsButton.Component | null;
|
|
311
347
|
ChatName?: typeof ChatName.Component | null;
|
|
348
|
+
ChatListItemBox?: typeof ChatListItemBox.Component | null;
|
|
349
|
+
ChatListItemName?: typeof ChatListItemName.Component | null;
|
|
350
|
+
ChatListItemUnreadCount?: typeof ChatListItemUnreadCount.Component | null;
|
|
351
|
+
ChatListItemLastMessage?: typeof ChatListItemLastMessage.Component | null;
|
|
352
|
+
ChatListItemLastMessageAuthor?: typeof ChatListItemLastMessageAuthor.Component | null;
|
|
353
|
+
ChatListItemLastMessageContent?: typeof ChatListItemLastMessageContent.Component | null;
|
|
354
|
+
SendingMessage?: typeof SendingMessage.Component | null;
|
|
355
|
+
SendingMessageBody?: typeof SendingMessageBody.Component | null;
|
|
356
|
+
SendingMessageInfoBox?: typeof SendingMessageInfoBox.Component | null;
|
|
357
|
+
SendingMessageText?: typeof SendingMessageText.Component | null;
|
|
358
|
+
Message?: typeof Message.Component | null;
|
|
359
|
+
MessageReadObserver?: typeof MessageReadObserver.Component | null;
|
|
360
|
+
MessageBox?: typeof MessageBox.Component | null;
|
|
361
|
+
MessageBody?: typeof MessageBody.Component | null;
|
|
362
|
+
MessageInfoBox?: typeof MessageInfoBox.Component | null;
|
|
363
|
+
MessageText?: typeof MessageText.Component | null;
|
|
364
|
+
MessageAuthor?: typeof MessageAuthor.Component | null;
|
|
312
365
|
}
|
|
313
366
|
interface ChatifyProps {
|
|
314
367
|
className?: string;
|
|
@@ -333,4 +386,4 @@ declare function ChatifyContext({ value, children }: PropsWithChildren<{
|
|
|
333
386
|
value: ChatifyContextValue;
|
|
334
387
|
}>): react_jsx_runtime.JSX.Element;
|
|
335
388
|
|
|
336
|
-
export { ACTIONS, Account, Action, AddChatButton, AddChatRequest, AddMemberRequest, Avatar, AvatarProps, Chat, ChatHeader, ChatHeaderMembers, ChatHeaderMembersProps, ChatHeaderProps, ChatListItem, Chatify, ChatifyClient, ChatifyClientConfig, ChatifyContext, ChatifyContextValue, ChatifyCustomizeValue, ChatifyProps, ChatifySignalRConfig, File, Header, Localizer, LocalizerContext, Message, MessageContent, MessageState, ReadEvent, ReadRequest, Reducer, ReducerProvider, RemoveMemberRequest, SendMessageRequest, defaultLocalizer, useAccounts, useAddChat, useAddMember, useChat, useChatList, useClient, useDispatch, useLoadMore, useLocalizer, useMe, useMessages, useReadMonitor, useReducer, useRemoveMember, useSelect, useSignalRMonitor, useStateRef };
|
|
389
|
+
export { ACTIONS, Account, Action, AddChatButton, AddChatRequest, AddMemberRequest, Avatar, AvatarProps, Chat, ChatHeader, ChatHeaderMembers, ChatHeaderMembersProps, ChatHeaderProps, ChatListItem, ChatListItemBox, ChatListItemBoxProps, ChatListItemLastMessage, ChatListItemLastMessageAuthor, ChatListItemLastMessageContent, ChatListItemName, ChatListItemUnreadCount, Chatify, ChatifyClient, ChatifyClientConfig, ChatifyContext, ChatifyContextValue, ChatifyCustomizeValue, ChatifyProps, ChatifySignalRConfig, File, Header, Localizer, LocalizerContext, Message$1 as Message, MessageContent, MessageState, ReadEvent, ReadRequest, Reducer, ReducerProvider, RemoveMemberRequest, SendMessageRequest, defaultLocalizer, useAccounts, useAddChat, useAddMember, useChat, useChatList, useClient, useDispatch, useLoadMore, useLocalizer, useMe, useMessages, useReadMonitor, useReducer, useRemoveMember, useSelect, useSignalRMonitor, useStateRef };
|
package/package.json
CHANGED
package/src/ui/Aside.tsx
CHANGED
|
@@ -1,38 +1,8 @@
|
|
|
1
1
|
import { Menu, MenuProps } from 'antd';
|
|
2
2
|
import { useCallback, useEffect, useMemo } from 'react';
|
|
3
3
|
import type { MenuItemType } from 'antd/es/menu/hooks/useItems';
|
|
4
|
-
import { useChatList, useDispatch, useSelect
|
|
5
|
-
import {
|
|
6
|
-
import { formatSystemMessage } from './SystemMessage';
|
|
7
|
-
import { Avatar } from './Avatar';
|
|
8
|
-
import { ChatName } from './ChatName';
|
|
9
|
-
|
|
10
|
-
function Chat(props: { chat: ChatListItem }) {
|
|
11
|
-
const { chat } = props;
|
|
12
|
-
const { name, message, unreadCount } = chat;
|
|
13
|
-
const localizer = useLocalizer();
|
|
14
|
-
|
|
15
|
-
return (
|
|
16
|
-
<div className={'wxchtf-chat' + (!message.read ? ' --unread' : '')}>
|
|
17
|
-
<div className="wxchtf-chat-name">
|
|
18
|
-
<ChatName name={name} />
|
|
19
|
-
</div>
|
|
20
|
-
{unreadCount > 0 && <div className="wxchtf-unread-count">{unreadCount}</div>}
|
|
21
|
-
<div className="wxchtf-chat-last">
|
|
22
|
-
{message.sentBy.id !== 'chatify::system' && (
|
|
23
|
-
<div className="wxchtf-chat-last-author">
|
|
24
|
-
<Avatar account={message.sentBy} /> {message.sentBy.name}
|
|
25
|
-
</div>
|
|
26
|
-
)}
|
|
27
|
-
<div className="wxchtf-chat-last-message">
|
|
28
|
-
{message.sentBy.id === 'chatify::system'
|
|
29
|
-
? formatSystemMessage(localizer, message.text)
|
|
30
|
-
: message.text}
|
|
31
|
-
</div>
|
|
32
|
-
</div>
|
|
33
|
-
</div>
|
|
34
|
-
);
|
|
35
|
-
}
|
|
4
|
+
import { useChatList, useDispatch, useSelect } from '../core';
|
|
5
|
+
import { ChatListItemBox } from './ChatListItem';
|
|
36
6
|
|
|
37
7
|
export function Aside() {
|
|
38
8
|
const activeChatId = useSelect((x) => x.ui.chatId, []);
|
|
@@ -52,7 +22,7 @@ export function Aside() {
|
|
|
52
22
|
return [];
|
|
53
23
|
}
|
|
54
24
|
|
|
55
|
-
return chats.map((x) => ({ key: x.id, label: <
|
|
25
|
+
return chats.map((x) => ({ key: x.id, label: <ChatListItemBox chat={x} /> }));
|
|
56
26
|
}, [chats]);
|
|
57
27
|
|
|
58
28
|
useEffect(() => {
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { useLocalizer } from './localizer';
|
|
2
|
+
import { formatSystemMessage } from './SystemMessage';
|
|
3
|
+
import { Avatar } from './Avatar';
|
|
4
|
+
import { ChatName } from './ChatName';
|
|
5
|
+
import { ChatListItem as ChatListItemModel } from '../core';
|
|
6
|
+
import { FC } from 'react';
|
|
7
|
+
import { customize } from '../util';
|
|
8
|
+
|
|
9
|
+
export interface ChatListItemBoxProps {
|
|
10
|
+
chat: ChatListItemModel;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const _ChatListItemName: FC<ChatListItemBoxProps> = (props) => {
|
|
14
|
+
const { name } = props.chat;
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<div className="wxchtf-chat-name">
|
|
18
|
+
<ChatName name={name} />
|
|
19
|
+
</div>
|
|
20
|
+
);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
_ChatListItemName.displayName = 'ChatListItemName';
|
|
24
|
+
|
|
25
|
+
export const ChatListItemName = customize('ChatListItemName', _ChatListItemName);
|
|
26
|
+
|
|
27
|
+
const _ChatListItemUnreadCount: FC<ChatListItemBoxProps> = (props) => {
|
|
28
|
+
const { unreadCount } = props.chat;
|
|
29
|
+
|
|
30
|
+
if (unreadCount <= 0) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return <div className="wxchtf-unread-count">{unreadCount}</div>;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
_ChatListItemUnreadCount.displayName = 'ChatListItemUnreadCount';
|
|
38
|
+
|
|
39
|
+
export const ChatListItemUnreadCount = customize('ChatListItemUnreadCount', _ChatListItemUnreadCount);
|
|
40
|
+
|
|
41
|
+
const _ChatListItemLastMessage: FC<ChatListItemBoxProps> = (props) => {
|
|
42
|
+
return (
|
|
43
|
+
<div className="wxchtf-chat-last">
|
|
44
|
+
<ChatListItemLastMessageAuthor {...props} />
|
|
45
|
+
<ChatListItemLastMessageContent {...props} />
|
|
46
|
+
</div>
|
|
47
|
+
);
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
_ChatListItemLastMessage.displayName = 'ChatListItemLastMessage';
|
|
51
|
+
|
|
52
|
+
export const ChatListItemLastMessage = customize('ChatListItemLastMessage', _ChatListItemLastMessage);
|
|
53
|
+
|
|
54
|
+
export const ChatListItemLastMessageAuthor = customize<FC<ChatListItemBoxProps>, string>(
|
|
55
|
+
'ChatListItemLastMessageAuthor',
|
|
56
|
+
(props) => {
|
|
57
|
+
const { message } = props.chat;
|
|
58
|
+
|
|
59
|
+
if (message.sentBy.id === 'chatify::system') {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
<div className="wxchtf-chat-last-author">
|
|
65
|
+
<Avatar account={message.sentBy} /> {message.sentBy.name}
|
|
66
|
+
</div>
|
|
67
|
+
);
|
|
68
|
+
},
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
export const ChatListItemLastMessageContent = customize<FC<ChatListItemBoxProps>, string>(
|
|
72
|
+
'ChatListItemLastMessageContent',
|
|
73
|
+
(props) => {
|
|
74
|
+
const { message } = props.chat;
|
|
75
|
+
const localizer = useLocalizer();
|
|
76
|
+
|
|
77
|
+
return (
|
|
78
|
+
<div className="wxchtf-chat-last-message">
|
|
79
|
+
{message.sentBy.id === 'chatify::system'
|
|
80
|
+
? formatSystemMessage(localizer, message.text)
|
|
81
|
+
: message.text}
|
|
82
|
+
</div>
|
|
83
|
+
);
|
|
84
|
+
},
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
const _ChatListItemBox: FC<ChatListItemBoxProps> = (props) => {
|
|
88
|
+
const { message } = props.chat;
|
|
89
|
+
|
|
90
|
+
return (
|
|
91
|
+
<div className={'wxchtf-chat' + (!message.read ? ' --unread' : '')}>
|
|
92
|
+
<ChatListItemName {...props} />
|
|
93
|
+
<ChatListItemUnreadCount {...props} />
|
|
94
|
+
<ChatListItemLastMessage {...props} />
|
|
95
|
+
</div>
|
|
96
|
+
);
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
_ChatListItemBox.displayName = 'ChatListItemBox';
|
|
100
|
+
|
|
101
|
+
export const ChatListItemBox = customize('ChatListItemBox', _ChatListItemBox);
|
package/src/ui/Chatify.tsx
CHANGED
|
@@ -11,6 +11,29 @@ import { Header } from './Header';
|
|
|
11
11
|
import { AddChatButton } from './AddChatButton';
|
|
12
12
|
import { Footer } from './Footer';
|
|
13
13
|
import { ChatName } from './ChatName';
|
|
14
|
+
import {
|
|
15
|
+
ChatListItemBox,
|
|
16
|
+
ChatListItemLastMessage,
|
|
17
|
+
ChatListItemLastMessageAuthor,
|
|
18
|
+
ChatListItemLastMessageContent,
|
|
19
|
+
ChatListItemName,
|
|
20
|
+
ChatListItemUnreadCount,
|
|
21
|
+
} from './ChatListItem';
|
|
22
|
+
import {
|
|
23
|
+
SendingMessage,
|
|
24
|
+
SendingMessageBody,
|
|
25
|
+
SendingMessageInfoBox,
|
|
26
|
+
SendingMessageText,
|
|
27
|
+
} from './SendingMessage';
|
|
28
|
+
import {
|
|
29
|
+
Message,
|
|
30
|
+
MessageAuthor,
|
|
31
|
+
MessageBody,
|
|
32
|
+
MessageBox,
|
|
33
|
+
MessageInfoBox,
|
|
34
|
+
MessageReadObserver,
|
|
35
|
+
MessageText,
|
|
36
|
+
} from './Message';
|
|
14
37
|
|
|
15
38
|
export interface ChatifyCustomizeValue {
|
|
16
39
|
Avatar?: typeof Avatar.Component | null;
|
|
@@ -20,6 +43,23 @@ export interface ChatifyCustomizeValue {
|
|
|
20
43
|
ChatHeaderMembers?: typeof ChatHeaderMembers.Component | null;
|
|
21
44
|
ChatSettingsButton?: typeof ChatSettingsButton.Component | null;
|
|
22
45
|
ChatName?: typeof ChatName.Component | null;
|
|
46
|
+
ChatListItemBox?: typeof ChatListItemBox.Component | null;
|
|
47
|
+
ChatListItemName?: typeof ChatListItemName.Component | null;
|
|
48
|
+
ChatListItemUnreadCount?: typeof ChatListItemUnreadCount.Component | null;
|
|
49
|
+
ChatListItemLastMessage?: typeof ChatListItemLastMessage.Component | null;
|
|
50
|
+
ChatListItemLastMessageAuthor?: typeof ChatListItemLastMessageAuthor.Component | null;
|
|
51
|
+
ChatListItemLastMessageContent?: typeof ChatListItemLastMessageContent.Component | null;
|
|
52
|
+
SendingMessage?: typeof SendingMessage.Component | null;
|
|
53
|
+
SendingMessageBody?: typeof SendingMessageBody.Component | null;
|
|
54
|
+
SendingMessageInfoBox?: typeof SendingMessageInfoBox.Component | null;
|
|
55
|
+
SendingMessageText?: typeof SendingMessageText.Component | null;
|
|
56
|
+
Message?: typeof Message.Component | null;
|
|
57
|
+
MessageReadObserver?: typeof MessageReadObserver.Component | null;
|
|
58
|
+
MessageBox?: typeof MessageBox.Component | null;
|
|
59
|
+
MessageBody?: typeof MessageBody.Component | null;
|
|
60
|
+
MessageInfoBox?: typeof MessageInfoBox.Component | null;
|
|
61
|
+
MessageText?: typeof MessageText.Component | null;
|
|
62
|
+
MessageAuthor?: typeof MessageAuthor.Component | null;
|
|
23
63
|
}
|
|
24
64
|
|
|
25
65
|
export interface ChatifyProps {
|
package/src/ui/Message.tsx
CHANGED
|
@@ -1,50 +1,117 @@
|
|
|
1
1
|
import { useMe } from '../ChatifyContext';
|
|
2
|
-
import {
|
|
3
|
-
import { useEffect, useMemo, useRef } from 'react';
|
|
2
|
+
import { FC, Ref, RefObject, useEffect, useMemo, useRef } from 'react';
|
|
4
3
|
import { useDispatch, useSelect, Message as MessageModel } from '../core';
|
|
4
|
+
import { customize } from '../util';
|
|
5
|
+
import { useLocalizer } from './localizer';
|
|
6
|
+
import { Avatar } from './Avatar';
|
|
5
7
|
|
|
6
8
|
export interface MessageProps {
|
|
7
9
|
message: MessageModel;
|
|
8
10
|
}
|
|
9
11
|
|
|
10
|
-
export
|
|
12
|
+
export interface MessageBoxProps extends MessageProps {
|
|
13
|
+
containerRef?: Ref<HTMLDivElement>;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const MessageAuthor = customize<FC<MessageProps>, string>('MessageAuthor', (props) => {
|
|
17
|
+
const { sentBy } = props.message;
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<div className="wxchtf-message-author">
|
|
21
|
+
<Avatar account={sentBy} />
|
|
22
|
+
</div>
|
|
23
|
+
);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
export const MessageText = customize<FC<MessageProps>, string>('MessageText', (props) => {
|
|
27
|
+
const { text } = props.message;
|
|
28
|
+
return <div className="wxchtf-message-text">{text}</div>;
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
export const MessageInfoBox = customize<FC<MessageProps>, string>('MessageInfoBox', (props) => {
|
|
11
32
|
const { message } = props;
|
|
33
|
+
const { id, sentBy, sentAt, read } = message;
|
|
12
34
|
const me = useMe();
|
|
13
|
-
const my =
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}),
|
|
27
|
-
|
|
28
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
29
|
-
[],
|
|
35
|
+
const my = sentBy.id === me;
|
|
36
|
+
const localizer = useLocalizer();
|
|
37
|
+
const reading = useSelect((x) => x.read.queued.includes(id), []);
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<div className="wxchtf-message-info-box">
|
|
41
|
+
<div className="wxchtf-message-sent-at">{localizer.timestamp(sentAt)}</div>
|
|
42
|
+
{read !== undefined && !my && (
|
|
43
|
+
<div className="wxchtf-message-read-box">
|
|
44
|
+
{reading ? localizer.message.reading() : localizer.message.read()}
|
|
45
|
+
</div>
|
|
46
|
+
)}
|
|
47
|
+
</div>
|
|
30
48
|
);
|
|
49
|
+
});
|
|
31
50
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
51
|
+
export const MessageBody = customize<FC<MessageProps>, string>('MessageBody', (props) => {
|
|
52
|
+
return (
|
|
53
|
+
<div className="wxchtf-message-body">
|
|
54
|
+
<MessageText {...props} />
|
|
55
|
+
<MessageInfoBox {...props} />
|
|
56
|
+
</div>
|
|
57
|
+
);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
export const MessageBox = customize<FC<MessageBoxProps>, string>('MessageBox', (props) => {
|
|
61
|
+
const { message, containerRef } = props;
|
|
62
|
+
const { sentBy } = message;
|
|
63
|
+
const me = useMe();
|
|
64
|
+
const my = sentBy.id === me;
|
|
65
|
+
|
|
66
|
+
return (
|
|
67
|
+
<div ref={containerRef} className={'wxchtf-message' + (my ? ' --my' : '')}>
|
|
68
|
+
<MessageAuthor {...props} />
|
|
69
|
+
<MessageBody {...props} />
|
|
70
|
+
</div>
|
|
71
|
+
);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
export const Message = customize<FC<MessageProps>, string>('Message', (props) => {
|
|
75
|
+
const ref = useRef<HTMLDivElement | null>(null);
|
|
36
76
|
|
|
37
77
|
return (
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
files={message.files}
|
|
43
|
-
author={message.sentBy}
|
|
44
|
-
timestamp={message.sentAt}
|
|
45
|
-
read={message.read}
|
|
46
|
-
sending={false}
|
|
47
|
-
reading={reading}
|
|
48
|
-
/>
|
|
78
|
+
<>
|
|
79
|
+
<MessageReadObserver messageRef={ref} {...props} />
|
|
80
|
+
<MessageBox containerRef={ref} {...props} />
|
|
81
|
+
</>
|
|
49
82
|
);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
export interface MessageReadObserverProps extends MessageProps {
|
|
86
|
+
messageRef: RefObject<HTMLDivElement | null>;
|
|
50
87
|
}
|
|
88
|
+
export const MessageReadObserver = customize<FC<MessageReadObserverProps>, string>(
|
|
89
|
+
'MessageReadObserver',
|
|
90
|
+
(props) => {
|
|
91
|
+
const { message, messageRef } = props;
|
|
92
|
+
const dispatch = useDispatch();
|
|
93
|
+
const readRef = useRef(false);
|
|
94
|
+
|
|
95
|
+
const observer = useMemo(
|
|
96
|
+
() =>
|
|
97
|
+
new IntersectionObserver(([entry]) => {
|
|
98
|
+
if (entry.isIntersecting && !readRef.current && !message.read) {
|
|
99
|
+
readRef.current = true;
|
|
100
|
+
dispatch({ type: 'read', data: { id: message.id, timestamp: new Date().getTime() } });
|
|
101
|
+
}
|
|
102
|
+
}),
|
|
103
|
+
|
|
104
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
105
|
+
[],
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
useEffect(() => {
|
|
109
|
+
observer.observe(messageRef.current!);
|
|
110
|
+
return () => observer.disconnect();
|
|
111
|
+
|
|
112
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
113
|
+
}, [observer]);
|
|
114
|
+
|
|
115
|
+
return <></>;
|
|
116
|
+
},
|
|
117
|
+
);
|
|
@@ -1,14 +1,50 @@
|
|
|
1
|
+
import { FC } from 'react';
|
|
1
2
|
import { File } from '../core';
|
|
2
|
-
import {
|
|
3
|
+
import { customize } from '../util';
|
|
4
|
+
import { useLocalizer } from './localizer';
|
|
3
5
|
|
|
4
6
|
export interface SendingMessageProps {
|
|
5
7
|
text: string;
|
|
6
8
|
files: File[];
|
|
7
9
|
}
|
|
8
10
|
|
|
9
|
-
export
|
|
10
|
-
|
|
11
|
+
export const SendingMessageText = customize<FC<SendingMessageProps>, string>(
|
|
12
|
+
'SendingMessageText',
|
|
13
|
+
(props) => {
|
|
14
|
+
const { text } = props;
|
|
15
|
+
return <div className="wxchtf-sending-message-text">{text}</div>;
|
|
16
|
+
},
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
export const SendingMessageInfoBox = customize<FC<SendingMessageProps>, string>(
|
|
20
|
+
'SendingMessageInfoBox',
|
|
21
|
+
() => {
|
|
22
|
+
const localizer = useLocalizer();
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<div className="wxchtf-sending-message-info-box">
|
|
26
|
+
<div className="wxchtf-sending-message-sending-box">{localizer.message.sending()}</div>
|
|
27
|
+
</div>
|
|
28
|
+
);
|
|
29
|
+
},
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
export const SendingMessageBody = customize<FC<SendingMessageProps>, string>(
|
|
33
|
+
'SendingMessageBody',
|
|
34
|
+
(props) => {
|
|
35
|
+
return (
|
|
36
|
+
<div className="wxchtf-sending-message-body">
|
|
37
|
+
<SendingMessageText {...props} />
|
|
38
|
+
<SendingMessageInfoBox {...props} />
|
|
39
|
+
</div>
|
|
40
|
+
);
|
|
41
|
+
},
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
export const SendingMessage = customize<FC<SendingMessageProps>, string>('SendingMessage', (props) => {
|
|
11
45
|
return (
|
|
12
|
-
<
|
|
46
|
+
<div className="wxchtf-sending-message">
|
|
47
|
+
<SendingMessageBody {...props} />
|
|
48
|
+
</div>
|
|
13
49
|
);
|
|
14
|
-
}
|
|
50
|
+
});
|
package/src/ui/index.ts
CHANGED
package/src/ui/styles/index.scss
CHANGED
|
@@ -62,7 +62,8 @@
|
|
|
62
62
|
padding-right: 30%;
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
.wxchtf-message
|
|
65
|
+
.wxchtf-message,
|
|
66
|
+
.wxchtf-sending-message {
|
|
66
67
|
display: flex;
|
|
67
68
|
flex-flow: row nowrap;
|
|
68
69
|
width: 100%;
|
|
@@ -81,7 +82,8 @@
|
|
|
81
82
|
margin-left: 15px;
|
|
82
83
|
}
|
|
83
84
|
|
|
84
|
-
.wxchtf-message-body
|
|
85
|
+
.wxchtf-message-body,
|
|
86
|
+
.wxchtf-sending-message-body {
|
|
85
87
|
direction: ltr;
|
|
86
88
|
border-bottom-left-radius: 10px;
|
|
87
89
|
border-bottom-right-radius: 0;
|
|
@@ -98,7 +100,8 @@
|
|
|
98
100
|
}
|
|
99
101
|
}
|
|
100
102
|
|
|
101
|
-
.wxchtf-message-body
|
|
103
|
+
.wxchtf-message-body,
|
|
104
|
+
.wxchtf-sending-message-body {
|
|
102
105
|
min-width: 300px;
|
|
103
106
|
max-width: 70%;
|
|
104
107
|
border-radius: $messageBorderRadius;
|
|
@@ -111,12 +114,13 @@
|
|
|
111
114
|
white-space: pre-wrap;
|
|
112
115
|
overflow-wrap: break-word;
|
|
113
116
|
|
|
114
|
-
.wxchtf-message-info-box
|
|
117
|
+
.wxchtf-message-info-box,
|
|
118
|
+
.wxchtf-sending-message-info-box {
|
|
115
119
|
text-align: right;
|
|
116
120
|
|
|
117
121
|
.wxchtf-message-sent-at,
|
|
118
122
|
.wxchtf-message-read-box,
|
|
119
|
-
.wxchtf-message-sending-box {
|
|
123
|
+
.wxchtf-sending-message-sending-box {
|
|
120
124
|
display: inline-block;
|
|
121
125
|
font-style: italic;
|
|
122
126
|
font-size: 0.75em;
|
|
@@ -125,7 +129,7 @@
|
|
|
125
129
|
}
|
|
126
130
|
|
|
127
131
|
.wxchtf-message-read-box,
|
|
128
|
-
.wxchtf-message-sending-box {
|
|
132
|
+
.wxchtf-sending-message-sending-box {
|
|
129
133
|
margin-left: 5px;
|
|
130
134
|
}
|
|
131
135
|
}
|
|
@@ -150,6 +154,7 @@
|
|
|
150
154
|
}
|
|
151
155
|
|
|
152
156
|
.wxchtf-message,
|
|
157
|
+
.wxchtf-sending-message,
|
|
153
158
|
.wxchtf-system-message,
|
|
154
159
|
.wxchtf-message-skeleton {
|
|
155
160
|
margin-bottom: 2rem;
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { Account, File } from '../core';
|
|
2
|
-
import React from 'react';
|
|
3
|
-
export interface MessageMdProps {
|
|
4
|
-
author?: Account;
|
|
5
|
-
text: string;
|
|
6
|
-
files: File[];
|
|
7
|
-
my: boolean;
|
|
8
|
-
read?: boolean;
|
|
9
|
-
sending?: boolean;
|
|
10
|
-
reading?: boolean;
|
|
11
|
-
timestamp: string;
|
|
12
|
-
}
|
|
13
|
-
export declare const MessageMd: React.ForwardRefExoticComponent<MessageMdProps & React.RefAttributes<HTMLDivElement>>;
|