@webinex/chatify 1.0.0-build2 → 1.0.0-rc2

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.
Files changed (56) hide show
  1. package/package.json +90 -90
  2. package/src/ChatifyContext.tsx +41 -41
  3. package/src/core/action.tsx +319 -319
  4. package/src/core/client.ts +137 -137
  5. package/src/core/index.ts +14 -14
  6. package/src/core/models.tsx +75 -75
  7. package/src/core/reducer.tsx +86 -86
  8. package/src/core/state.ts +38 -38
  9. package/src/core/useAccounts.tsx +11 -11
  10. package/src/core/useAddChat.tsx +12 -12
  11. package/src/core/useAddMember.tsx +12 -12
  12. package/src/core/useAddMessage.tsx +40 -40
  13. package/src/core/useChat.tsx +12 -12
  14. package/src/core/useChatList.tsx +10 -10
  15. package/src/core/useLoadMore.tsx +42 -42
  16. package/src/core/useMessages.tsx +23 -23
  17. package/src/core/useMutation.tsx +48 -48
  18. package/src/core/useQuery.tsx +45 -45
  19. package/src/core/useReadMonitor.tsx +31 -31
  20. package/src/core/useRemoveMember.tsx +12 -12
  21. package/src/core/useSignalRMonitor.tsx +52 -52
  22. package/src/index.ts +3 -3
  23. package/src/ui/AddChat.tsx +55 -55
  24. package/src/ui/AddChatButton.tsx +19 -19
  25. package/src/ui/Aside.tsx +41 -41
  26. package/src/ui/Avatar.tsx +18 -18
  27. package/src/ui/Chat.tsx +26 -26
  28. package/src/ui/ChatBody.tsx +43 -43
  29. package/src/ui/ChatHeader.tsx +33 -33
  30. package/src/ui/ChatHeaderMembers.tsx +30 -30
  31. package/src/ui/ChatHeaderSettingsButton.tsx +26 -26
  32. package/src/ui/ChatListItem.tsx +101 -101
  33. package/src/ui/ChatName.tsx +15 -15
  34. package/src/ui/ChatSettings.tsx +59 -59
  35. package/src/ui/Chatify.tsx +106 -106
  36. package/src/ui/Footer.tsx +7 -7
  37. package/src/ui/Header.tsx +14 -14
  38. package/src/ui/Icon.tsx +21 -21
  39. package/src/ui/InputForm.tsx +51 -51
  40. package/src/ui/LoadMore.tsx +40 -40
  41. package/src/ui/Main.tsx +16 -16
  42. package/src/ui/Message.tsx +118 -118
  43. package/src/ui/MessageSkeleton.tsx +19 -19
  44. package/src/ui/SendingMessage.tsx +50 -50
  45. package/src/ui/SystemMessage.tsx +32 -32
  46. package/src/ui/index.ts +11 -11
  47. package/src/ui/localizer.tsx +68 -68
  48. package/src/ui/styles/aside.scss +94 -94
  49. package/src/ui/styles/index.scss +248 -248
  50. package/src/ui/styles/keyframes.scss +14 -14
  51. package/src/ui/styles/mixins.scss +20 -20
  52. package/src/ui/styles/variables.scss +10 -10
  53. package/src/util/customize.tsx +45 -45
  54. package/src/util/index.ts +3 -3
  55. package/src/util/uniqBy.tsx +17 -17
  56. package/src/util/uniqId.tsx +3 -3
@@ -1,12 +1,12 @@
1
- import { useClient } from '../ChatifyContext';
2
- import { RemoveMemberRequest } from './models';
3
- import { useMutation } from './useMutation';
4
-
5
- export function useRemoveMember() {
6
- const client = useClient();
7
-
8
- return useMutation({
9
- key: 'remove-member',
10
- queryFn: (args: RemoveMemberRequest) => client.removeMember(args),
11
- });
12
- }
1
+ import { useClient } from '../ChatifyContext';
2
+ import { RemoveMemberRequest } from './models';
3
+ import { useMutation } from './useMutation';
4
+
5
+ export function useRemoveMember() {
6
+ const client = useClient();
7
+
8
+ return useMutation({
9
+ key: 'remove-member',
10
+ queryFn: (args: RemoveMemberRequest) => client.removeMember(args),
11
+ });
12
+ }
@@ -1,52 +1,52 @@
1
- import { useEffect } from 'react';
2
- import { useDispatch } from './reducer';
3
- import { Account, ChatListItem, Message, ReadEvent } from './models';
4
- import { ChatifyClient } from './client';
5
-
6
- export function useSignalRMonitor(me: string, client: ChatifyClient) {
7
- const dispatch = useDispatch();
8
-
9
- useEffect(() => {
10
- let unsubscribes: Array<() => void> = [];
11
-
12
- client.connect().then(() => {
13
- unsubscribes.push(
14
- client.subscribe('chatify://new-message', ([message, requestId]: [Message, string]) => {
15
- dispatch({ type: 'message_received', data: { message, requestId } });
16
- }),
17
- );
18
- unsubscribes.push(
19
- client.subscribe('chatify://chat-created', ([chat, requestId]: [ChatListItem, string]) => {
20
- dispatch({ type: 'chat_created', data: { chat, requestId } });
21
- }),
22
- );
23
- unsubscribes.push(
24
- client.subscribe('chatify://read', ([events]: [ReadEvent[]]) => {
25
- dispatch({ type: 'read_received', data: { events } });
26
- }),
27
- );
28
- unsubscribes.push(
29
- client.subscribe(
30
- 'chatify://member-added',
31
- ([chatId, chatName, account, message]: [string, string, Account, Message]) => {
32
- dispatch({ type: 'member_added', data: { chatId, chatName, account, me, message } });
33
- },
34
- ),
35
- );
36
- unsubscribes.push(
37
- client.subscribe(
38
- 'chatify://member-removed',
39
- ([chatId, accountId, deleteHistory]: [string, string, boolean]) => {
40
- dispatch({ type: 'member_removed', data: { chatId, accountId, deleteHistory, me } });
41
- },
42
- ),
43
- );
44
- });
45
-
46
- return () => {
47
- unsubscribes.forEach((x) => x());
48
- };
49
-
50
- // eslint-disable-next-line react-hooks/exhaustive-deps
51
- }, []);
52
- }
1
+ import { useEffect } from 'react';
2
+ import { useDispatch } from './reducer';
3
+ import { Account, ChatListItem, Message, ReadEvent } from './models';
4
+ import { ChatifyClient } from './client';
5
+
6
+ export function useSignalRMonitor(me: string, client: ChatifyClient) {
7
+ const dispatch = useDispatch();
8
+
9
+ useEffect(() => {
10
+ let unsubscribes: Array<() => void> = [];
11
+
12
+ client.connect().then(() => {
13
+ unsubscribes.push(
14
+ client.subscribe('chatify://new-message', ([message, requestId]: [Message, string]) => {
15
+ dispatch({ type: 'message_received', data: { message, requestId } });
16
+ }),
17
+ );
18
+ unsubscribes.push(
19
+ client.subscribe('chatify://chat-created', ([chat, requestId]: [ChatListItem, string]) => {
20
+ dispatch({ type: 'chat_created', data: { chat, requestId } });
21
+ }),
22
+ );
23
+ unsubscribes.push(
24
+ client.subscribe('chatify://read', ([events]: [ReadEvent[]]) => {
25
+ dispatch({ type: 'read_received', data: { events } });
26
+ }),
27
+ );
28
+ unsubscribes.push(
29
+ client.subscribe(
30
+ 'chatify://member-added',
31
+ ([chatId, chatName, account, message]: [string, string, Account, Message]) => {
32
+ dispatch({ type: 'member_added', data: { chatId, chatName, account, me, message } });
33
+ },
34
+ ),
35
+ );
36
+ unsubscribes.push(
37
+ client.subscribe(
38
+ 'chatify://member-removed',
39
+ ([chatId, accountId, deleteHistory]: [string, string, boolean]) => {
40
+ dispatch({ type: 'member_removed', data: { chatId, accountId, deleteHistory, me } });
41
+ },
42
+ ),
43
+ );
44
+ });
45
+
46
+ return () => {
47
+ unsubscribes.forEach((x) => x());
48
+ };
49
+
50
+ // eslint-disable-next-line react-hooks/exhaustive-deps
51
+ }, []);
52
+ }
package/src/index.ts CHANGED
@@ -1,3 +1,3 @@
1
- export * from './ui';
2
- export * from './core';
3
- export * from './ChatifyContext';
1
+ export * from './ui';
2
+ export * from './core';
3
+ export * from './ChatifyContext';
@@ -1,55 +1,55 @@
1
- import { Button, Form, Input, Select } from 'antd';
2
- import { useAccounts, useAddChat } from '../core';
3
- import { useCallback, useMemo } from 'react';
4
- import { uniqId } from '../util';
5
- import { useLocalizer } from './localizer';
6
-
7
- type FormValue = {
8
- name: string;
9
- members: string[];
10
- };
11
-
12
- export function AddChat() {
13
- const [add, { isFetching: adding }] = useAddChat();
14
- const { data: accounts, isFetching } = useAccounts();
15
- const localizer = useLocalizer();
16
- const options = useMemo(() => accounts?.map((x) => ({ value: x.id, label: x.name })), [accounts]);
17
-
18
- const onSubmit = useCallback(
19
- (value: FormValue) =>
20
- add({
21
- name: value.name,
22
- members: value.members,
23
- requestId: uniqId(),
24
- }),
25
- [add],
26
- );
27
-
28
- return (
29
- <div className="wxchtf-add-chat">
30
- <h3>{localizer.addChat.title()}</h3>
31
- <Form onFinish={onSubmit} layout="vertical" disabled={adding}>
32
- <Form.Item
33
- name="name"
34
- label={localizer.addChat.name.label()}
35
- rules={[
36
- { required: true, message: localizer.addChat.name.required() },
37
- { max: 250, message: localizer.addChat.name.max250() },
38
- ]}
39
- >
40
- <Input />
41
- </Form.Item>
42
- <Form.Item
43
- name="members"
44
- label={localizer.addChat.members.label()}
45
- rules={[{ required: true, message: localizer.addChat.members.required() }]}
46
- >
47
- <Select mode="multiple" loading={isFetching} options={options} />
48
- </Form.Item>
49
- <Button loading={adding} type="primary" block htmlType="submit">
50
- {localizer.addChat.submitBtn()}
51
- </Button>
52
- </Form>
53
- </div>
54
- );
55
- }
1
+ import { Button, Form, Input, Select } from 'antd';
2
+ import { useAccounts, useAddChat } from '../core';
3
+ import { useCallback, useMemo } from 'react';
4
+ import { uniqId } from '../util';
5
+ import { useLocalizer } from './localizer';
6
+
7
+ type FormValue = {
8
+ name: string;
9
+ members: string[];
10
+ };
11
+
12
+ export function AddChat() {
13
+ const [add, { isFetching: adding }] = useAddChat();
14
+ const { data: accounts, isFetching } = useAccounts();
15
+ const localizer = useLocalizer();
16
+ const options = useMemo(() => accounts?.map((x) => ({ value: x.id, label: x.name })), [accounts]);
17
+
18
+ const onSubmit = useCallback(
19
+ (value: FormValue) =>
20
+ add({
21
+ name: value.name,
22
+ members: value.members,
23
+ requestId: uniqId(),
24
+ }),
25
+ [add],
26
+ );
27
+
28
+ return (
29
+ <div className="wxchtf-add-chat">
30
+ <h3>{localizer.addChat.title()}</h3>
31
+ <Form onFinish={onSubmit} layout="vertical" disabled={adding}>
32
+ <Form.Item
33
+ name="name"
34
+ label={localizer.addChat.name.label()}
35
+ rules={[
36
+ { required: true, message: localizer.addChat.name.required() },
37
+ { max: 250, message: localizer.addChat.name.max250() },
38
+ ]}
39
+ >
40
+ <Input />
41
+ </Form.Item>
42
+ <Form.Item
43
+ name="members"
44
+ label={localizer.addChat.members.label()}
45
+ rules={[{ required: true, message: localizer.addChat.members.required() }]}
46
+ >
47
+ <Select mode="multiple" loading={isFetching} options={options} />
48
+ </Form.Item>
49
+ <Button loading={adding} type="primary" block htmlType="submit">
50
+ {localizer.addChat.submitBtn()}
51
+ </Button>
52
+ </Form>
53
+ </div>
54
+ );
55
+ }
@@ -1,19 +1,19 @@
1
- import { Button } from 'antd';
2
- import { useDispatch } from '../core';
3
- import { FC, useCallback } from 'react';
4
- import { customize } from '../util';
5
-
6
- const _AddChatButton: FC = () => {
7
- const dispatch = useDispatch();
8
- const onAddChat = useCallback(() => dispatch({ type: 'new_chat_open', data: undefined }), [dispatch]);
9
-
10
- return (
11
- <Button onClick={onAddChat} icon={'+'} type="link">
12
- Add chat
13
- </Button>
14
- );
15
- };
16
-
17
- _AddChatButton.displayName = 'AddChatButton';
18
-
19
- export const AddChatButton = customize('AddChatButton', _AddChatButton);
1
+ import { Button } from 'antd';
2
+ import { useDispatch } from '../core';
3
+ import { FC, useCallback } from 'react';
4
+ import { customize } from '../util';
5
+
6
+ const _AddChatButton: FC = () => {
7
+ const dispatch = useDispatch();
8
+ const onAddChat = useCallback(() => dispatch({ type: 'new_chat_open', data: undefined }), [dispatch]);
9
+
10
+ return (
11
+ <Button onClick={onAddChat} icon={'+'} type="link">
12
+ Add chat
13
+ </Button>
14
+ );
15
+ };
16
+
17
+ _AddChatButton.displayName = 'AddChatButton';
18
+
19
+ export const AddChatButton = customize('AddChatButton', _AddChatButton);
package/src/ui/Aside.tsx CHANGED
@@ -1,41 +1,41 @@
1
- import { Menu, MenuProps } from 'antd';
2
- import { useCallback, useEffect, useMemo } from 'react';
3
- import type { MenuItemType } from 'antd/es/menu/hooks/useItems';
4
- import { useChatList, useDispatch, useSelect } from '../core';
5
- import { ChatListItemBox } from './ChatListItem';
6
-
7
- export function Aside() {
8
- const activeChatId = useSelect((x) => x.ui.chatId, []);
9
- const dispatch = useDispatch();
10
- const selected = useMemo(() => (activeChatId ? [activeChatId] : []), [activeChatId]);
11
-
12
- const onSelect = useCallback(
13
- (info: Parameters<NonNullable<MenuProps['onSelect']>>[0]) =>
14
- dispatch({ type: 'chat_open', data: { chatId: info.selectedKeys[0] } }),
15
- [dispatch],
16
- );
17
-
18
- const { data: chats } = useChatList();
19
-
20
- const items = useMemo<MenuItemType[]>(() => {
21
- if (!chats) {
22
- return [];
23
- }
24
-
25
- return chats.map((x) => ({ key: x.id, label: <ChatListItemBox chat={x} /> }));
26
- }, [chats]);
27
-
28
- useEffect(() => {
29
- if (!activeChatId && chats && chats.length > 0) {
30
- dispatch({ type: 'chat_open', data: { chatId: chats[0].id } });
31
- }
32
-
33
- // eslint-disable-next-line react-hooks/exhaustive-deps
34
- }, [chats, dispatch]);
35
-
36
- return (
37
- <div className="wxchtf-aside">
38
- {chats && <Menu className="wxchtf-chats" selectedKeys={selected} onSelect={onSelect} items={items} />}
39
- </div>
40
- );
41
- }
1
+ import { Menu, MenuProps } from 'antd';
2
+ import { useCallback, useEffect, useMemo } from 'react';
3
+ import type { MenuItemType } from 'antd/es/menu/hooks/useItems';
4
+ import { useChatList, useDispatch, useSelect } from '../core';
5
+ import { ChatListItemBox } from './ChatListItem';
6
+
7
+ export function Aside() {
8
+ const activeChatId = useSelect((x) => x.ui.chatId, []);
9
+ const dispatch = useDispatch();
10
+ const selected = useMemo(() => (activeChatId ? [activeChatId] : []), [activeChatId]);
11
+
12
+ const onSelect = useCallback(
13
+ (info: Parameters<NonNullable<MenuProps['onSelect']>>[0]) =>
14
+ dispatch({ type: 'chat_open', data: { chatId: info.selectedKeys[0] } }),
15
+ [dispatch],
16
+ );
17
+
18
+ const { data: chats } = useChatList();
19
+
20
+ const items = useMemo<MenuItemType[]>(() => {
21
+ if (!chats) {
22
+ return [];
23
+ }
24
+
25
+ return chats.map((x) => ({ key: x.id, label: <ChatListItemBox chat={x} /> }));
26
+ }, [chats]);
27
+
28
+ useEffect(() => {
29
+ if (!activeChatId && chats && chats.length > 0) {
30
+ dispatch({ type: 'chat_open', data: { chatId: chats[0].id } });
31
+ }
32
+
33
+ // eslint-disable-next-line react-hooks/exhaustive-deps
34
+ }, [chats, dispatch]);
35
+
36
+ return (
37
+ <div className="wxchtf-aside">
38
+ {chats && <Menu className="wxchtf-chats" selectedKeys={selected} onSelect={onSelect} items={items} />}
39
+ </div>
40
+ );
41
+ }
package/src/ui/Avatar.tsx CHANGED
@@ -1,18 +1,18 @@
1
- import { FC } from 'react';
2
- import { Account } from '../core';
3
- import { Avatar as AntdAvatar } from 'antd';
4
- import { customize } from '../util';
5
-
6
- export interface AvatarProps {
7
- account: Account;
8
- }
9
-
10
- const _Avatar: FC<AvatarProps> = (props: AvatarProps) => {
11
- const { account } = props;
12
-
13
- return <AntdAvatar src={account.avatar} />;
14
- };
15
-
16
- _Avatar.displayName = 'Avatar';
17
-
18
- export const Avatar = customize('Avatar', _Avatar);
1
+ import { FC } from 'react';
2
+ import { Account } from '../core';
3
+ import { Avatar as AntdAvatar } from 'antd';
4
+ import { customize } from '../util';
5
+
6
+ export interface AvatarProps {
7
+ account: Account;
8
+ }
9
+
10
+ const _Avatar: FC<AvatarProps> = (props: AvatarProps) => {
11
+ const { account } = props;
12
+
13
+ return <AntdAvatar src={account.avatar} />;
14
+ };
15
+
16
+ _Avatar.displayName = 'Avatar';
17
+
18
+ export const Avatar = customize('Avatar', _Avatar);
package/src/ui/Chat.tsx CHANGED
@@ -1,26 +1,26 @@
1
- import { ChatHeader } from './ChatHeader';
2
- import { ChatBody } from './ChatBody';
3
- import { InputForm } from './InputForm';
4
- import { useChat } from '../core';
5
- import { useMe } from '../ChatifyContext';
6
-
7
- export interface ChatProps {
8
- id: string;
9
- }
10
-
11
- export function Chat(props: ChatProps) {
12
- const { id } = props;
13
- const me = useMe();
14
- const { data: chat } = useChat({ chatId: id });
15
- const isMember = chat?.members.map((x) => x.id).includes(me) === true;
16
-
17
- return (
18
- <>
19
- <div className="wxchtf-chat">
20
- <ChatHeader id={id} />
21
- <ChatBody id={id} />
22
- </div>
23
- {isMember && <InputForm />}
24
- </>
25
- );
26
- }
1
+ import { ChatHeader } from './ChatHeader';
2
+ import { ChatBody } from './ChatBody';
3
+ import { InputForm } from './InputForm';
4
+ import { useChat } from '../core';
5
+ import { useMe } from '../ChatifyContext';
6
+
7
+ export interface ChatProps {
8
+ id: string;
9
+ }
10
+
11
+ export function Chat(props: ChatProps) {
12
+ const { id } = props;
13
+ const me = useMe();
14
+ const { data: chat } = useChat({ chatId: id });
15
+ const isMember = chat?.members.map((x) => x.id).includes(me) === true;
16
+
17
+ return (
18
+ <>
19
+ <div className="wxchtf-chat">
20
+ <ChatHeader id={id} />
21
+ <ChatBody id={id} />
22
+ </div>
23
+ {isMember && <InputForm />}
24
+ </>
25
+ );
26
+ }
@@ -1,43 +1,43 @@
1
- import { MessageBox } from './Message';
2
- import { useMessages } from '../core';
3
- import { LoadMore } from './LoadMore';
4
- import { SendingMessage } from './SendingMessage';
5
- import { SystemMessage } from './SystemMessage';
6
- import { MessageSkeleton } from './MessageSkeleton';
7
-
8
- export interface ChatBodyProps {
9
- id: string;
10
- }
11
-
12
- export function ChatBody(props: ChatBodyProps) {
13
- const { id } = props;
14
- const { data: messages } = useMessages({ chatId: id });
15
-
16
- return (
17
- <div className="wxchtf-chat-body">
18
- {!messages && <MessageSkeleton count={5} />}
19
- {messages?.map((x, index) => {
20
- if (x.type === 'message' && x.sentBy.id === 'chatify::system') {
21
- return <SystemMessage text={x.text} sentAt={x.sentAt} />;
22
- }
23
-
24
- switch (x.type) {
25
- case 'message': {
26
- return <MessageBox message={x} key={x.id} />;
27
- }
28
-
29
- case 'sending': {
30
- return <SendingMessage key={x.requestId} text={x.text} files={x.files} />;
31
- }
32
-
33
- case 'more': {
34
- return <LoadMore key={index} chatId={id} />;
35
- }
36
-
37
- default:
38
- return null;
39
- }
40
- })}
41
- </div>
42
- );
43
- }
1
+ import { MessageBox } from './Message';
2
+ import { useMessages } from '../core';
3
+ import { LoadMore } from './LoadMore';
4
+ import { SendingMessage } from './SendingMessage';
5
+ import { SystemMessage } from './SystemMessage';
6
+ import { MessageSkeleton } from './MessageSkeleton';
7
+
8
+ export interface ChatBodyProps {
9
+ id: string;
10
+ }
11
+
12
+ export function ChatBody(props: ChatBodyProps) {
13
+ const { id } = props;
14
+ const { data: messages } = useMessages({ chatId: id });
15
+
16
+ return (
17
+ <div className="wxchtf-chat-body">
18
+ {!messages && <MessageSkeleton count={5} />}
19
+ {messages?.map((x, index) => {
20
+ if (x.type === 'message' && x.sentBy.id === 'chatify::system') {
21
+ return <SystemMessage text={x.text} sentAt={x.sentAt} />;
22
+ }
23
+
24
+ switch (x.type) {
25
+ case 'message': {
26
+ return <MessageBox message={x} key={x.id} />;
27
+ }
28
+
29
+ case 'sending': {
30
+ return <SendingMessage key={x.requestId} text={x.text} files={x.files} />;
31
+ }
32
+
33
+ case 'more': {
34
+ return <LoadMore key={index} chatId={id} />;
35
+ }
36
+
37
+ default:
38
+ return null;
39
+ }
40
+ })}
41
+ </div>
42
+ );
43
+ }
@@ -1,33 +1,33 @@
1
- import { useChat, useSelect, ChatListItem } from '../core';
2
- import { Col, Row, Space } from 'antd';
3
- import { ChatHeaderMembers } from './ChatHeaderMembers';
4
- import { ChatSettingsButton } from './ChatHeaderSettingsButton';
5
- import { ChatName } from './ChatName';
6
-
7
- export interface ChatHeaderProps {
8
- id: string;
9
- }
10
-
11
- export function ChatHeader(props: ChatHeaderProps) {
12
- const { id } = props;
13
- const { data: chat } = useChat({ chatId: id });
14
- const chatListItem = useSelect(
15
- (x) => x.query['chat-list'].data?.find((x: ChatListItem) => x.id === id),
16
- [id],
17
- );
18
- const name = chat?.name ?? chatListItem?.name;
19
-
20
- return (
21
- <div className="wxchtf-chat-header">
22
- <Row justify="space-between" align="middle">
23
- <Col className="wxchtf-chat-name">{name && <ChatName name={name} />}</Col>
24
- <Col className="wxchtf-chat-members">
25
- <Space align="center">
26
- <ChatHeaderMembers id={id} />
27
- <ChatSettingsButton id={id} />
28
- </Space>
29
- </Col>
30
- </Row>
31
- </div>
32
- );
33
- }
1
+ import { useChat, useSelect, ChatListItem } from '../core';
2
+ import { Col, Row, Space } from 'antd';
3
+ import { ChatHeaderMembers } from './ChatHeaderMembers';
4
+ import { ChatSettingsButton } from './ChatHeaderSettingsButton';
5
+ import { ChatName } from './ChatName';
6
+
7
+ export interface ChatHeaderProps {
8
+ id: string;
9
+ }
10
+
11
+ export function ChatHeader(props: ChatHeaderProps) {
12
+ const { id } = props;
13
+ const { data: chat } = useChat({ chatId: id });
14
+ const chatListItem = useSelect(
15
+ (x) => x.query['chat-list'].data?.find((x: ChatListItem) => x.id === id),
16
+ [id],
17
+ );
18
+ const name = chat?.name ?? chatListItem?.name;
19
+
20
+ return (
21
+ <div className="wxchtf-chat-header">
22
+ <Row justify="space-between" align="middle">
23
+ <Col className="wxchtf-chat-name">{name && <ChatName name={name} />}</Col>
24
+ <Col className="wxchtf-chat-members">
25
+ <Space align="center">
26
+ <ChatHeaderMembers id={id} />
27
+ <ChatSettingsButton id={id} />
28
+ </Space>
29
+ </Col>
30
+ </Row>
31
+ </div>
32
+ );
33
+ }