@webinex/chatify 1.0.0-rc2 → 1.0.0-rc3

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 (267) hide show
  1. package/dist/css/chatify.css +183 -141
  2. package/dist/esm/index.js +1 -1
  3. package/dist/esm/index.js.map +1 -1
  4. package/dist/esm/types/core/action.d.ts +110 -42
  5. package/dist/esm/types/core/client.d.ts +2 -1
  6. package/dist/esm/types/core/index.d.ts +11 -8
  7. package/dist/esm/types/core/models.d.ts +10 -4
  8. package/dist/esm/types/core/state.d.ts +36 -7
  9. package/dist/esm/types/core/useAddChatMutation.d.ts +2 -0
  10. package/dist/esm/types/core/useAddMemberMutation.d.ts +2 -0
  11. package/dist/esm/types/core/useFetchNextMutation.d.ts +3 -0
  12. package/dist/esm/types/core/useGetAccountsQuery.d.ts +1 -0
  13. package/dist/esm/types/core/useGetChatListQuery.d.ts +1 -0
  14. package/dist/{cjs/types/core/useChat.d.ts → esm/types/core/useGetChatQuery.d.ts} +1 -1
  15. package/dist/esm/types/core/useGetMessagesQuery.d.ts +4 -0
  16. package/dist/esm/types/core/useRemoveMemberMutation.d.ts +2 -0
  17. package/dist/esm/types/core/useSendMutation.d.ts +2 -0
  18. package/dist/esm/types/core/useUpdateChatNameMutation.d.ts +2 -0
  19. package/dist/esm/types/ui/AddChatButton.d.ts +2 -2
  20. package/dist/esm/types/ui/Avatar.d.ts +2 -2
  21. package/dist/esm/types/ui/ChatList/ChatList.d.ts +2 -0
  22. package/dist/esm/types/ui/ChatList/ChatListItemBox.d.ts +6 -0
  23. package/dist/esm/types/ui/ChatList/ChatListItemLastMessage.d.ts +3 -0
  24. package/dist/esm/types/ui/ChatList/ChatListItemLastMessageAuthor.d.ts +3 -0
  25. package/dist/esm/types/ui/ChatList/ChatListItemLastMessageContent.d.ts +3 -0
  26. package/dist/esm/types/ui/ChatList/ChatListItemName.d.ts +3 -0
  27. package/dist/esm/types/ui/ChatList/ChatListItemUnreadCount.d.ts +3 -0
  28. package/dist/esm/types/ui/ChatList/index.d.ts +7 -0
  29. package/dist/esm/types/ui/ChatName.d.ts +2 -2
  30. package/dist/esm/types/ui/ChatPanel/ChatBody.d.ts +5 -0
  31. package/dist/esm/types/ui/ChatPanel/ChatHeader.d.ts +5 -0
  32. package/dist/esm/types/ui/ChatPanel/ChatHeaderMembers.d.ts +5 -0
  33. package/dist/esm/types/ui/ChatPanel/ChatHeaderName.d.ts +5 -0
  34. package/dist/esm/types/ui/ChatPanel/ChatMembersButton.d.ts +5 -0
  35. package/dist/esm/types/ui/ChatPanel/ChatMembersPanel.d.ts +5 -0
  36. package/dist/esm/types/ui/ChatPanel/ChatPanel.d.ts +5 -0
  37. package/dist/esm/types/ui/ChatPanel/index.d.ts +6 -0
  38. package/dist/esm/types/ui/Chatify.d.ts +45 -23
  39. package/dist/esm/types/ui/CreateChatPanel/CreateChatForm.d.ts +11 -0
  40. package/dist/esm/types/ui/CreateChatPanel/CreateChatMemberInput.d.ts +5 -0
  41. package/dist/esm/types/ui/CreateChatPanel/CreateChatNameInput.d.ts +5 -0
  42. package/dist/esm/types/ui/CreateChatPanel/CreateChatPanel.d.ts +2 -0
  43. package/dist/esm/types/ui/CreateChatPanel/index.d.ts +4 -0
  44. package/dist/esm/types/ui/Icon.d.ts +13 -4
  45. package/dist/esm/types/ui/InputBox/InputBox.d.ts +2 -0
  46. package/dist/esm/types/ui/InputBox/InputFilesBox.d.ts +2 -0
  47. package/dist/esm/types/ui/InputBox/InputSubmitButtonBox.d.ts +5 -0
  48. package/dist/esm/types/ui/InputBox/InputTextBox.d.ts +7 -0
  49. package/dist/esm/types/ui/InputBox/index.d.ts +4 -0
  50. package/dist/esm/types/ui/Layout/Aside.d.ts +2 -0
  51. package/dist/esm/types/ui/Layout/Body.d.ts +2 -0
  52. package/dist/esm/types/ui/Layout/Footer.d.ts +2 -0
  53. package/dist/esm/types/ui/Layout/Header.d.ts +2 -0
  54. package/dist/esm/types/ui/Layout/Main.d.ts +2 -0
  55. package/dist/esm/types/ui/Layout/index.d.ts +5 -0
  56. package/dist/esm/types/ui/Message/MessageAuthor.d.ts +3 -0
  57. package/dist/esm/types/ui/Message/MessageBox.d.ts +6 -0
  58. package/dist/esm/types/ui/Message/MessageContent.d.ts +3 -0
  59. package/dist/esm/types/ui/Message/MessageInfoBox.d.ts +3 -0
  60. package/dist/esm/types/ui/Message/MessageRow.d.ts +6 -0
  61. package/dist/esm/types/ui/Message/MessageText.d.ts +3 -0
  62. package/dist/esm/types/ui/Message/index.d.ts +6 -0
  63. package/dist/esm/types/ui/MessageReadObserver.d.ts +6 -0
  64. package/dist/esm/types/ui/Next.d.ts +4 -0
  65. package/dist/esm/types/ui/SendingMessage/SendingMessageBox.d.ts +7 -0
  66. package/dist/esm/types/ui/SendingMessage/SendingMessageContent.d.ts +3 -0
  67. package/dist/esm/types/ui/SendingMessage/SendingMessageInfoBox.d.ts +3 -0
  68. package/dist/esm/types/ui/SendingMessage/SendingMessageText.d.ts +3 -0
  69. package/dist/esm/types/ui/SendingMessage/index.d.ts +4 -0
  70. package/dist/esm/types/ui/SystemMessage/SystemMessageBox.d.ts +6 -0
  71. package/dist/esm/types/ui/SystemMessage/SystemMessageRow.d.ts +9 -0
  72. package/dist/esm/types/ui/SystemMessage/index.d.ts +2 -0
  73. package/dist/esm/types/{util → ui}/customize.d.ts +2 -3
  74. package/dist/esm/types/ui/index.d.ts +6 -6
  75. package/dist/esm/types/ui/localizer.d.ts +5 -0
  76. package/dist/esm/types/util/index.d.ts +0 -1
  77. package/dist/index.d.ts +353 -142
  78. package/package.json +3 -1
  79. package/src/core/action.tsx +319 -233
  80. package/src/core/client.ts +6 -0
  81. package/src/core/index.ts +11 -8
  82. package/src/core/models.tsx +11 -4
  83. package/src/core/reducer.tsx +2 -1
  84. package/src/core/state.ts +68 -14
  85. package/src/core/useAddChatMutation.tsx +22 -0
  86. package/src/core/useAddMemberMutation.tsx +25 -0
  87. package/src/core/useFetchNextMutation.tsx +28 -0
  88. package/src/core/useGetAccountsQuery.tsx +33 -0
  89. package/src/core/useGetChatListQuery.tsx +33 -0
  90. package/src/core/useGetChatQuery.tsx +34 -0
  91. package/src/core/useGetMessagesQuery.tsx +35 -0
  92. package/src/core/useReadMonitor.tsx +8 -7
  93. package/src/core/useRemoveMemberMutation.tsx +23 -0
  94. package/src/core/useSendMutation.tsx +24 -0
  95. package/src/core/useSignalRMonitor.tsx +19 -5
  96. package/src/core/useUpdateChatNameMutation.tsx +23 -0
  97. package/src/{ui/styles → styles}/aside.scss +1 -1
  98. package/src/styles/chat.scss +222 -0
  99. package/src/styles/index.scss +79 -0
  100. package/src/styles/settings.scss +5 -0
  101. package/src/ui/AddChatButton.tsx +4 -8
  102. package/src/ui/Avatar.tsx +1 -1
  103. package/src/ui/ChatList/ChatList.tsx +42 -0
  104. package/src/ui/ChatList/ChatListItemBox.tsx +22 -0
  105. package/src/ui/ChatList/ChatListItemLastMessage.tsx +13 -0
  106. package/src/ui/ChatList/ChatListItemLastMessageAuthor.tsx +20 -0
  107. package/src/ui/ChatList/ChatListItemLastMessageContent.tsx +21 -0
  108. package/src/ui/ChatList/ChatListItemName.tsx +13 -0
  109. package/src/ui/ChatList/ChatListItemUnreadCount.tsx +12 -0
  110. package/src/ui/ChatList/index.ts +7 -0
  111. package/src/ui/ChatName.tsx +3 -8
  112. package/src/ui/ChatPanel/ChatBody.tsx +44 -0
  113. package/src/ui/ChatPanel/ChatHeader.tsx +33 -0
  114. package/src/ui/{ChatHeaderMembers.tsx → ChatPanel/ChatHeaderMembers.tsx} +5 -9
  115. package/src/ui/ChatPanel/ChatHeaderName.tsx +67 -0
  116. package/src/ui/ChatPanel/ChatMembersButton.tsx +21 -0
  117. package/src/ui/ChatPanel/ChatMembersPanel.tsx +117 -0
  118. package/src/ui/ChatPanel/ChatPanel.tsx +27 -0
  119. package/src/ui/ChatPanel/index.ts +6 -0
  120. package/src/ui/Chatify.tsx +78 -36
  121. package/src/ui/CreateChatPanel/CreateChatForm.tsx +36 -0
  122. package/src/ui/CreateChatPanel/CreateChatMemberInput.tsx +66 -0
  123. package/src/ui/CreateChatPanel/CreateChatNameInput.tsx +25 -0
  124. package/src/ui/CreateChatPanel/CreateChatPanel.tsx +33 -0
  125. package/src/ui/CreateChatPanel/index.ts +4 -0
  126. package/src/ui/Icon.tsx +18 -6
  127. package/src/ui/InputBox/InputBox.tsx +38 -0
  128. package/src/ui/InputBox/InputFilesBox.tsx +9 -0
  129. package/src/ui/InputBox/InputSubmitButtonBox.tsx +17 -0
  130. package/src/ui/InputBox/InputTextBox.tsx +50 -0
  131. package/src/ui/InputBox/index.ts +4 -0
  132. package/src/ui/Layout/Aside.tsx +10 -0
  133. package/src/ui/Layout/Body.tsx +10 -0
  134. package/src/ui/Layout/Footer.tsx +3 -0
  135. package/src/ui/Layout/Header.tsx +10 -0
  136. package/src/ui/Layout/Main.tsx +15 -0
  137. package/src/ui/Layout/index.ts +5 -0
  138. package/src/ui/Message/MessageAuthor.tsx +13 -0
  139. package/src/ui/Message/MessageBox.tsx +20 -0
  140. package/src/ui/Message/MessageContent.tsx +13 -0
  141. package/src/ui/Message/MessageInfoBox.tsx +25 -0
  142. package/src/ui/Message/MessageRow.tsx +24 -0
  143. package/src/ui/Message/MessageText.tsx +7 -0
  144. package/src/ui/Message/index.ts +6 -0
  145. package/src/ui/MessageReadObserver.tsx +45 -0
  146. package/src/ui/{LoadMore.tsx → Next.tsx} +16 -8
  147. package/src/ui/SendingMessage/SendingMessageBox.tsx +16 -0
  148. package/src/ui/SendingMessage/SendingMessageContent.tsx +13 -0
  149. package/src/ui/SendingMessage/SendingMessageInfoBox.tsx +13 -0
  150. package/src/ui/SendingMessage/SendingMessageText.tsx +7 -0
  151. package/src/ui/SendingMessage/index.ts +4 -0
  152. package/src/ui/SystemMessage/SystemMessageBox.tsx +20 -0
  153. package/src/ui/SystemMessage/SystemMessageRow.tsx +43 -0
  154. package/src/ui/SystemMessage/index.ts +2 -0
  155. package/src/{util → ui}/customize.tsx +5 -5
  156. package/src/ui/index.ts +6 -6
  157. package/src/ui/localizer.tsx +12 -0
  158. package/src/util/index.ts +0 -1
  159. package/dist/cjs/index.js +0 -2
  160. package/dist/cjs/index.js.map +0 -1
  161. package/dist/cjs/types/ChatifyContext.d.ts +0 -11
  162. package/dist/cjs/types/core/action.d.ts +0 -76
  163. package/dist/cjs/types/core/client.d.ts +0 -35
  164. package/dist/cjs/types/core/index.d.ts +0 -14
  165. package/dist/cjs/types/core/models.d.ts +0 -64
  166. package/dist/cjs/types/core/reducer.d.ts +0 -11
  167. package/dist/cjs/types/core/state.d.ts +0 -25
  168. package/dist/cjs/types/core/useAccounts.d.ts +0 -1
  169. package/dist/cjs/types/core/useAddChat.d.ts +0 -2
  170. package/dist/cjs/types/core/useAddMember.d.ts +0 -2
  171. package/dist/cjs/types/core/useAddMessage.d.ts +0 -5
  172. package/dist/cjs/types/core/useChatList.d.ts +0 -1
  173. package/dist/cjs/types/core/useLoadMore.d.ts +0 -3
  174. package/dist/cjs/types/core/useMessages.d.ts +0 -15
  175. package/dist/cjs/types/core/useMutation.d.ts +0 -12
  176. package/dist/cjs/types/core/useQuery.d.ts +0 -7
  177. package/dist/cjs/types/core/useReadMonitor.d.ts +0 -1
  178. package/dist/cjs/types/core/useRemoveMember.d.ts +0 -2
  179. package/dist/cjs/types/core/useSignalRMonitor.d.ts +0 -2
  180. package/dist/cjs/types/index.d.ts +0 -3
  181. package/dist/cjs/types/ui/AddChat.d.ts +0 -1
  182. package/dist/cjs/types/ui/AddChatButton.d.ts +0 -2
  183. package/dist/cjs/types/ui/Aside.d.ts +0 -1
  184. package/dist/cjs/types/ui/Avatar.d.ts +0 -6
  185. package/dist/cjs/types/ui/Chat.d.ts +0 -4
  186. package/dist/cjs/types/ui/ChatBody.d.ts +0 -4
  187. package/dist/cjs/types/ui/ChatHeader.d.ts +0 -4
  188. package/dist/cjs/types/ui/ChatHeaderMembers.d.ts +0 -5
  189. package/dist/cjs/types/ui/ChatHeaderSettingsButton.d.ts +0 -5
  190. package/dist/cjs/types/ui/ChatListItem.d.ts +0 -11
  191. package/dist/cjs/types/ui/ChatName.d.ts +0 -5
  192. package/dist/cjs/types/ui/ChatSettings.d.ts +0 -1
  193. package/dist/cjs/types/ui/Chatify.d.ts +0 -49
  194. package/dist/cjs/types/ui/Footer.d.ts +0 -2
  195. package/dist/cjs/types/ui/Header.d.ts +0 -2
  196. package/dist/cjs/types/ui/Icon.d.ts +0 -7
  197. package/dist/cjs/types/ui/InputForm.d.ts +0 -1
  198. package/dist/cjs/types/ui/LoadMore.d.ts +0 -4
  199. package/dist/cjs/types/ui/Main.d.ts +0 -1
  200. package/dist/cjs/types/ui/Message.d.ts +0 -18
  201. package/dist/cjs/types/ui/MessageSkeleton.d.ts +0 -4
  202. package/dist/cjs/types/ui/SendingMessage.d.ts +0 -10
  203. package/dist/cjs/types/ui/SystemMessage.d.ts +0 -8
  204. package/dist/cjs/types/ui/index.d.ts +0 -11
  205. package/dist/cjs/types/ui/localizer.d.ts +0 -32
  206. package/dist/cjs/types/util/customize.d.ts +0 -12
  207. package/dist/cjs/types/util/index.d.ts +0 -3
  208. package/dist/cjs/types/util/uniqBy.d.ts +0 -1
  209. package/dist/cjs/types/util/uniqId.d.ts +0 -1
  210. package/dist/esm/types/core/useAccounts.d.ts +0 -1
  211. package/dist/esm/types/core/useAddChat.d.ts +0 -2
  212. package/dist/esm/types/core/useAddMember.d.ts +0 -2
  213. package/dist/esm/types/core/useAddMessage.d.ts +0 -5
  214. package/dist/esm/types/core/useChat.d.ts +0 -3
  215. package/dist/esm/types/core/useChatList.d.ts +0 -1
  216. package/dist/esm/types/core/useLoadMore.d.ts +0 -3
  217. package/dist/esm/types/core/useMessages.d.ts +0 -15
  218. package/dist/esm/types/core/useMutation.d.ts +0 -12
  219. package/dist/esm/types/core/useQuery.d.ts +0 -7
  220. package/dist/esm/types/core/useRemoveMember.d.ts +0 -2
  221. package/dist/esm/types/ui/AddChat.d.ts +0 -1
  222. package/dist/esm/types/ui/Aside.d.ts +0 -1
  223. package/dist/esm/types/ui/Chat.d.ts +0 -4
  224. package/dist/esm/types/ui/ChatBody.d.ts +0 -4
  225. package/dist/esm/types/ui/ChatHeader.d.ts +0 -4
  226. package/dist/esm/types/ui/ChatHeaderMembers.d.ts +0 -5
  227. package/dist/esm/types/ui/ChatHeaderSettingsButton.d.ts +0 -5
  228. package/dist/esm/types/ui/ChatListItem.d.ts +0 -11
  229. package/dist/esm/types/ui/ChatSettings.d.ts +0 -1
  230. package/dist/esm/types/ui/Footer.d.ts +0 -2
  231. package/dist/esm/types/ui/Header.d.ts +0 -2
  232. package/dist/esm/types/ui/InputForm.d.ts +0 -1
  233. package/dist/esm/types/ui/LoadMore.d.ts +0 -4
  234. package/dist/esm/types/ui/Main.d.ts +0 -1
  235. package/dist/esm/types/ui/Message.d.ts +0 -18
  236. package/dist/esm/types/ui/SendingMessage.d.ts +0 -10
  237. package/dist/esm/types/ui/SystemMessage.d.ts +0 -8
  238. package/src/core/useAccounts.tsx +0 -11
  239. package/src/core/useAddChat.tsx +0 -12
  240. package/src/core/useAddMember.tsx +0 -12
  241. package/src/core/useAddMessage.tsx +0 -40
  242. package/src/core/useChat.tsx +0 -12
  243. package/src/core/useChatList.tsx +0 -10
  244. package/src/core/useLoadMore.tsx +0 -42
  245. package/src/core/useMessages.tsx +0 -23
  246. package/src/core/useMutation.tsx +0 -48
  247. package/src/core/useQuery.tsx +0 -45
  248. package/src/core/useRemoveMember.tsx +0 -12
  249. package/src/ui/AddChat.tsx +0 -55
  250. package/src/ui/Aside.tsx +0 -41
  251. package/src/ui/Chat.tsx +0 -26
  252. package/src/ui/ChatBody.tsx +0 -43
  253. package/src/ui/ChatHeader.tsx +0 -33
  254. package/src/ui/ChatHeaderSettingsButton.tsx +0 -26
  255. package/src/ui/ChatListItem.tsx +0 -101
  256. package/src/ui/ChatSettings.tsx +0 -59
  257. package/src/ui/Footer.tsx +0 -7
  258. package/src/ui/Header.tsx +0 -14
  259. package/src/ui/InputForm.tsx +0 -51
  260. package/src/ui/Main.tsx +0 -16
  261. package/src/ui/Message.tsx +0 -118
  262. package/src/ui/SendingMessage.tsx +0 -50
  263. package/src/ui/SystemMessage.tsx +0 -32
  264. package/src/ui/styles/index.scss +0 -248
  265. /package/src/{ui/styles → styles}/keyframes.scss +0 -0
  266. /package/src/{ui/styles → styles}/mixins.scss +0 -0
  267. /package/src/{ui/styles → styles}/variables.scss +0 -0
@@ -0,0 +1,67 @@
1
+ import { Input, Tooltip } from 'antd';
2
+ import { useSelect, useUpdateChatNameMutation } from '../../core';
3
+ import { ChatName } from '../ChatName';
4
+ import { customize } from '../customize';
5
+ import { useEffect, useState } from 'react';
6
+ import isHotkey from 'is-hotkey';
7
+
8
+ export interface ChatHeaderNameProps {
9
+ id: string;
10
+ }
11
+
12
+ const isEscape = isHotkey('escape');
13
+ const isEnter = isHotkey('enter');
14
+
15
+ function useUpdateChatName(id: string, value: string) {
16
+ const [updateChatName] = useUpdateChatNameMutation();
17
+ return () => updateChatName({ id, name: value });
18
+ }
19
+
20
+ export const ChatHeaderName = customize('ChatHeaderName', (props: ChatHeaderNameProps) => {
21
+ const { id } = props;
22
+ const chat = useSelect((x) => x.query.chatList.data!.find((x) => x.id === id)!, [id]);
23
+ const name = chat.name;
24
+ const [editNameValue, setEditNameValue] = useState('');
25
+ const [edit, setEdit] = useState(false);
26
+ const updateChatName = useUpdateChatName(id, editNameValue);
27
+
28
+ useEffect(() => {
29
+ if (edit) {
30
+ setEditNameValue(name);
31
+ }
32
+ }, [edit, name]);
33
+
34
+ if (!chat.active) {
35
+ return <span className="wxchtf-chat-name">{name}</span>;
36
+ }
37
+
38
+ if (edit) {
39
+ return (
40
+ <Input
41
+ value={editNameValue}
42
+ onChange={(e) => setEditNameValue(e.target.value)}
43
+ onBlur={() => setEdit(false)}
44
+ onKeyDown={(e) => {
45
+ if (isEscape(e)) {
46
+ setEdit(false);
47
+ } else if (isEnter(e)) {
48
+ setEdit(false);
49
+
50
+ if (editNameValue !== name) {
51
+ updateChatName();
52
+ }
53
+ }
54
+ }}
55
+ autoFocus
56
+ />
57
+ );
58
+ }
59
+
60
+ return (
61
+ <Tooltip title="Click to edit name...">
62
+ <span className="wxchtf-chat-name --editable" onClick={() => setEdit(true)}>
63
+ <ChatName name={name} />
64
+ </span>
65
+ </Tooltip>
66
+ );
67
+ });
@@ -0,0 +1,21 @@
1
+ import { useDispatch } from '../../core';
2
+ import { Button } from 'antd';
3
+ import { useCallback } from 'react';
4
+ import { customize } from '../customize';
5
+ import { Icon } from '../Icon';
6
+
7
+ export interface ChatMembersButtonProps {
8
+ id: string;
9
+ }
10
+
11
+ export const ChatMembersButton = customize('ChatMembersButton', (_: ChatMembersButtonProps) => {
12
+ const dispatch = useDispatch();
13
+ const onSettingsClick = useCallback(
14
+ () => dispatch({ type: 'toggle_members_view', data: void 0 }),
15
+
16
+ // eslint-disable-next-line react-hooks/exhaustive-deps
17
+ [dispatch],
18
+ );
19
+
20
+ return <Button onClick={onSettingsClick} type="link" icon={<Icon type="team" />} />;
21
+ });
@@ -0,0 +1,117 @@
1
+ import { Button, List, Space, Tooltip } from 'antd';
2
+ import {
3
+ useAddMemberMutation,
4
+ useGetAccountsQuery,
5
+ useGetChatQuery,
6
+ useRemoveMemberMutation,
7
+ } from '../../core';
8
+ import { customize } from '../customize';
9
+ import { useCallback, useMemo } from 'react';
10
+ import { Icon } from '../Icon';
11
+ import { Avatar } from '../Avatar';
12
+
13
+ export interface ChatMembersPanelProps {
14
+ id: string;
15
+ }
16
+
17
+ interface ChatMemberListItemProps {
18
+ id: string;
19
+ chatId: string;
20
+ }
21
+
22
+ function useAdd(chatId: string, accountId: string, withHistory: boolean) {
23
+ const [add, state] = useAddMemberMutation();
24
+ const onAdd = useCallback(
25
+ () => add({ chatId, accountId, withHistory }),
26
+ [add, chatId, accountId, withHistory],
27
+ );
28
+ return [onAdd, state] as const;
29
+ }
30
+
31
+ function useRemove(chatId: string, accountId: string, deleteHistory: boolean) {
32
+ const [remove, state] = useRemoveMemberMutation();
33
+ const onRemove = useCallback(
34
+ () => remove({ chatId, accountId, deleteHistory }),
35
+ [remove, chatId, accountId, deleteHistory],
36
+ );
37
+ return [onRemove, state] as const;
38
+ }
39
+
40
+ const ChatMemberListItem = customize('ChatMemberListItem', (props: ChatMemberListItemProps) => {
41
+ const { chatId } = props;
42
+ const { data: chat } = useGetChatQuery({ chatId });
43
+ const { data: accounts } = useGetAccountsQuery();
44
+ const account = accounts!.find((x) => x.id === props.id)!;
45
+ const isMember = chat!.members.some((x) => x.id === account.id);
46
+ const [onAddWithoutHistory] = useAdd(chatId, account.id, false);
47
+ const [onAddWithHistory] = useAdd(chatId, account.id, true);
48
+ const [onRemoveKeepHistory] = useRemove(chatId, account.id, false);
49
+ const [onRemoveDeleteHistory] = useRemove(chatId, account.id, true);
50
+
51
+ return (
52
+ <List.Item
53
+ className="wxchtf-chat-members-list-item"
54
+ actions={
55
+ isMember
56
+ ? [
57
+ <Tooltip key="remove" title="Remove (keep history)">
58
+ <Button onClick={onRemoveKeepHistory} type="link" icon={<Icon type="remove" />} />
59
+ </Tooltip>,
60
+ <Tooltip key="remove_delete_history" title="Remove (delete history)">
61
+ <Button
62
+ onClick={onRemoveDeleteHistory}
63
+ type="link"
64
+ icon={<Icon type="remove_delete_history" />}
65
+ />
66
+ </Tooltip>,
67
+ ]
68
+ : [
69
+ <Tooltip key="add_no_history" title="Add (no history)">
70
+ <Button onClick={onAddWithoutHistory} type="link" icon={<Icon type="add" />} />
71
+ </Tooltip>,
72
+ <Tooltip key="add" title="Add (share history)">
73
+ <Button onClick={onAddWithHistory} type="link" icon={<Icon type="add_with_history" />} />
74
+ </Tooltip>,
75
+ ]
76
+ }
77
+ >
78
+ <Space>
79
+ <Avatar account={account} />
80
+ <span>{account.name}</span>
81
+ </Space>
82
+ </List.Item>
83
+ );
84
+ });
85
+
86
+ export const ChatMembersPanel = customize('ChatMembersPanel', (props: ChatMembersPanelProps) => {
87
+ const { id } = props;
88
+
89
+ const { data: chat } = useGetChatQuery({ chatId: id });
90
+ const { data: accounts } = useGetAccountsQuery();
91
+ const ordered = useMemo(
92
+ () =>
93
+ accounts
94
+ ?.slice()
95
+ .sort(
96
+ (a, b) =>
97
+ (chat?.members.some((m) => m.id === a.id) ? -100 : 0) -
98
+ (chat?.members.some((m) => m.id === b.id) ? -100 : 0) +
99
+ a.name.localeCompare(b.name),
100
+ ),
101
+ [accounts, chat],
102
+ );
103
+
104
+ if (!chat?.members || !accounts) {
105
+ return null;
106
+ }
107
+
108
+ return (
109
+ <div className="wxchtf-chat-members-panel">
110
+ <List
111
+ className="wxchtf-chat-members-list"
112
+ dataSource={ordered}
113
+ renderItem={(item) => <ChatMemberListItem id={item.id} chatId={id} />}
114
+ />
115
+ </div>
116
+ );
117
+ });
@@ -0,0 +1,27 @@
1
+ import { ChatHeader } from './ChatHeader';
2
+ import { ChatBody } from './ChatBody';
3
+ import { InputBox } from '../InputBox/InputBox';
4
+ import { useSelect } from '../../core';
5
+ import { customize } from '../customize';
6
+ import { ChatMembersPanel } from './ChatMembersPanel';
7
+
8
+ export interface ChatPanelProps {
9
+ id: string;
10
+ }
11
+
12
+ export const ChatPanel = customize('ChatPanel', (props: ChatPanelProps) => {
13
+ const { id } = props;
14
+ const chat = useSelect((x) => x.query.chatList.data!.find((x) => x.id === id)!, [id]);
15
+ const chatMembersOpen = useSelect((x) => x.ui.showMembers, []);
16
+
17
+ return (
18
+ <div className="wxchtf-chat-panel">
19
+ <div className="wxchtf-chat-main">
20
+ <ChatHeader id={id} />
21
+ <ChatBody id={id} />
22
+ {chat.active && <InputBox />}
23
+ </div>
24
+ {chatMembersOpen && <ChatMembersPanel id={id} />}
25
+ </div>
26
+ );
27
+ });
@@ -0,0 +1,6 @@
1
+ export * from './ChatBody';
2
+ export * from './ChatHeader';
3
+ export * from './ChatHeaderMembers';
4
+ export * from './ChatHeaderName';
5
+ export * from './ChatPanel';
6
+ export * from './ChatMembersButton';
@@ -1,68 +1,113 @@
1
1
  import { CSSProperties, FC } from 'react';
2
2
  import { useReadMonitor } from '../core';
3
- import { Aside } from './Aside';
4
- import { Main } from './Main';
5
3
  import { Localizer, LocalizerContext, defaultLocalizer } from './localizer';
6
4
  import { Avatar } from './Avatar';
7
- import { CustomizeProvider } from '../util';
8
- import { ChatHeaderMembers } from './ChatHeaderMembers';
9
- import { ChatSettingsButton } from './ChatHeaderSettingsButton';
10
- import { Header } from './Header';
5
+ import { CustomizeProvider } from './customize';
6
+ import { ChatHeaderMembers } from './ChatPanel/ChatHeaderMembers';
7
+ import { ChatMembersButton } from './ChatPanel/ChatMembersButton';
11
8
  import { AddChatButton } from './AddChatButton';
12
- import { Footer } from './Footer';
13
9
  import { ChatName } from './ChatName';
10
+
11
+ import { Aside, Main, Body, Footer, Header } from './Layout';
12
+
14
13
  import {
15
14
  ChatListItemBox,
16
- ChatListItemLastMessage,
17
- ChatListItemLastMessageAuthor,
18
15
  ChatListItemLastMessageContent,
19
- ChatListItemName,
16
+ ChatListItemLastMessageAuthor,
17
+ ChatListItemLastMessage,
20
18
  ChatListItemUnreadCount,
21
- } from './ChatListItem';
19
+ ChatListItemName,
20
+ } from './ChatList';
21
+
22
22
  import {
23
- SendingMessage,
23
+ SendingMessageBox,
24
24
  SendingMessageContent,
25
25
  SendingMessageInfoBox,
26
26
  SendingMessageText,
27
27
  } from './SendingMessage';
28
+
28
29
  import {
29
- MessageAuthor,
30
- MessageContent,
31
30
  MessageBox,
32
- MessageInfoBox,
33
- MessageReadObserver,
34
31
  MessageRow,
32
+ MessageContent,
35
33
  MessageText,
34
+ MessageAuthor,
35
+ MessageInfoBox,
36
36
  } from './Message';
37
+
38
+ import { MessageReadObserver } from './MessageReadObserver';
37
39
  import { Icon } from './Icon';
38
- import { SystemMessage } from './SystemMessage';
40
+ import { SystemMessageRow } from './SystemMessage/SystemMessageRow';
41
+ import { ChatList } from './ChatList';
42
+ import { ChatBody, ChatHeader, ChatHeaderName, ChatPanel } from './ChatPanel';
43
+ import { InputBox, InputFilesBox, InputSubmitButtonBox, InputTextBox } from './InputBox';
44
+ import { SystemMessageBox } from './SystemMessage';
45
+ import {
46
+ CreateChatForm,
47
+ CreateChatMemberInput,
48
+ CreateChatNameInput,
49
+ CreateChatPanel,
50
+ } from './CreateChatPanel';
39
51
 
40
52
  export interface ChatifyCustomizeValue {
41
- Avatar?: typeof Avatar.Component | null;
42
- Header?: typeof Header.Component | null;
43
- Footer?: typeof Footer.Component | null;
44
- AddChatButton?: typeof AddChatButton.Component | null;
45
- ChatHeaderMembers?: typeof ChatHeaderMembers.Component | null;
46
- ChatSettingsButton?: typeof ChatSettingsButton.Component | null;
47
- ChatName?: typeof ChatName.Component | null;
53
+ // ./ChatList
54
+ ChatList?: typeof ChatList.Component | null;
48
55
  ChatListItemBox?: typeof ChatListItemBox.Component | null;
49
56
  ChatListItemName?: typeof ChatListItemName.Component | null;
50
57
  ChatListItemUnreadCount?: typeof ChatListItemUnreadCount.Component | null;
51
58
  ChatListItemLastMessage?: typeof ChatListItemLastMessage.Component | null;
52
59
  ChatListItemLastMessageAuthor?: typeof ChatListItemLastMessageAuthor.Component | null;
53
60
  ChatListItemLastMessageContent?: typeof ChatListItemLastMessageContent.Component | null;
54
- SystemMessage?: typeof SystemMessage.Component | null;
55
- SendingMessage?: typeof SendingMessage.Component | null;
56
- SendingMessageBody?: typeof SendingMessageContent.Component | null;
57
- SendingMessageInfoBox?: typeof SendingMessageInfoBox.Component | null;
58
- SendingMessageText?: typeof SendingMessageText.Component | null;
61
+
62
+ // ./Layout
63
+ Header?: typeof Header.Component | null;
64
+ Footer?: typeof Footer.Component | null;
65
+ Body?: typeof Body.Component | null;
66
+ Main?: typeof Main.Component | null;
67
+ Aside?: typeof Aside.Component | null;
68
+
69
+ // ./Message
70
+ MessageAuthor?: typeof MessageAuthor.Component | null;
59
71
  MessageBox?: typeof MessageBox.Component | null;
60
- MessageReadObserver?: typeof MessageReadObserver.Component | null;
61
- MessageRow?: typeof MessageRow.Component | null;
62
72
  MessageContent?: typeof MessageContent.Component | null;
63
73
  MessageInfoBox?: typeof MessageInfoBox.Component | null;
74
+ MessageRow?: typeof MessageRow.Component | null;
64
75
  MessageText?: typeof MessageText.Component | null;
65
- MessageAuthor?: typeof MessageAuthor.Component | null;
76
+
77
+ // ./SendingMessage
78
+ SendingMessageBox?: typeof SendingMessageBox.Component | null;
79
+ SendingMessageContent?: typeof SendingMessageContent.Component | null;
80
+ SendingMessageInfoBox?: typeof SendingMessageInfoBox.Component | null;
81
+ SendingMessageText?: typeof SendingMessageText.Component | null;
82
+
83
+ // ./ChatPanel
84
+ ChatBody?: typeof ChatBody.Component | null;
85
+ ChatHeader?: typeof ChatHeader.Component | null;
86
+ ChatHeaderMembers?: typeof ChatHeaderMembers.Component | null;
87
+ ChatHeaderName?: typeof ChatHeaderName.Component | null;
88
+ ChatPanel?: typeof ChatPanel.Component | null;
89
+ ChatMembersButton?: typeof ChatMembersButton.Component | null;
90
+
91
+ // ./InputBox
92
+ InputBox?: typeof InputBox.Component | null;
93
+ InputFilesBox?: typeof InputFilesBox.Component | null;
94
+ InputSubmitButtonBox?: typeof InputSubmitButtonBox.Component | null;
95
+ InputTextBox?: typeof InputTextBox.Component | null;
96
+
97
+ // ./SystemMessage
98
+ SystemMessageBox?: typeof SystemMessageBox.Component | null;
99
+ SystemMessageRow?: typeof SystemMessageRow.Component | null;
100
+
101
+ // ./CreateChatPanel
102
+ CreateChatForm?: typeof CreateChatForm.Component | null;
103
+ CreateChatMemberInput?: typeof CreateChatMemberInput.Component | null;
104
+ CreateChatNameInput?: typeof CreateChatNameInput.Component | null;
105
+ CreateChatPanel?: typeof CreateChatPanel.Component | null;
106
+
107
+ MessageReadObserver?: typeof MessageReadObserver.Component | null;
108
+ Avatar?: typeof Avatar.Component | null;
109
+ AddChatButton?: typeof AddChatButton.Component | null;
110
+ ChatName?: typeof ChatName.Component | null;
66
111
  Icon?: typeof Icon.Component | null;
67
112
  }
68
113
 
@@ -80,10 +125,7 @@ function Content(props: Pick<ChatifyProps, 'className' | 'style'>) {
80
125
  return (
81
126
  <div className={className + ' wxchtf-chatify'} style={style}>
82
127
  <Header />
83
- <div className="wxchtf-body">
84
- <Aside />
85
- <Main />
86
- </div>
128
+ <Body />
87
129
  <Footer />
88
130
  </div>
89
131
  );
@@ -0,0 +1,36 @@
1
+ import { Button, Form } from 'antd';
2
+ import { customize } from '../customize';
3
+ import { CreateChatNameInput } from './CreateChatNameInput';
4
+ import { CreateChatMemberInput } from './CreateChatMemberInput';
5
+ import { useLocalizer } from '../localizer';
6
+
7
+ export interface CreateChatFormValue {
8
+ name: string;
9
+ members: string[];
10
+ }
11
+
12
+ export interface CreateChatFormProps {
13
+ value?: CreateChatFormValue;
14
+ onSubmit: (value: CreateChatFormValue) => void;
15
+ busy?: boolean;
16
+ }
17
+
18
+ const INITIAL_VALUE: CreateChatFormValue = {
19
+ name: '',
20
+ members: [],
21
+ };
22
+
23
+ export const CreateChatForm = customize('CreateChatForm', (props: CreateChatFormProps) => {
24
+ const { value = INITIAL_VALUE, onSubmit, busy = false } = props;
25
+ const localizer = useLocalizer();
26
+
27
+ return (
28
+ <Form onFinish={onSubmit} layout="vertical" disabled={busy} initialValues={value}>
29
+ <CreateChatNameInput name="name" />
30
+ <CreateChatMemberInput name="members" />
31
+ <Button loading={busy} type="primary" block htmlType="submit">
32
+ {localizer.addChat.submitBtn()}
33
+ </Button>
34
+ </Form>
35
+ );
36
+ });
@@ -0,0 +1,66 @@
1
+ import { useMemo } from 'react';
2
+ import { useGetAccountsQuery } from '../../core';
3
+ import { customize } from '../customize';
4
+ import { Checkbox, Form, List } from 'antd';
5
+ import { useLocalizer } from '../localizer';
6
+ import { useMe } from '../../ChatifyContext';
7
+ import { Avatar } from '../Avatar';
8
+
9
+ export interface CreateChatMemberInputProps {
10
+ name: string;
11
+ }
12
+
13
+ interface CheckboxListProps {
14
+ value?: string[];
15
+ onChange?: (value: string[]) => void;
16
+ }
17
+
18
+ function CheckboxList(props: CheckboxListProps) {
19
+ const { value, onChange } = props;
20
+ const { data: accounts, isFetching } = useGetAccountsQuery();
21
+ const me = useMe();
22
+ const dataSource = useMemo(() => accounts?.filter((x) => x.id !== me) ?? [], [accounts, me]);
23
+
24
+ return (
25
+ <List
26
+ rowKey="id"
27
+ className="wxchtf-create-chat-member-input-list"
28
+ loading={isFetching}
29
+ dataSource={dataSource}
30
+ renderItem={(x) => {
31
+ const checked = value!.includes(x.id);
32
+
33
+ return (
34
+ <List.Item className={checked ? '--selected' : ''}>
35
+ <Checkbox
36
+ checked={checked}
37
+ onChange={() =>
38
+ onChange!(value!.includes(x.id) ? value!.filter((y) => y !== x.id) : [...value!, x.id])
39
+ }
40
+ >
41
+ <List.Item.Meta avatar={<Avatar account={x} />} title={x.name} />
42
+ </Checkbox>
43
+ </List.Item>
44
+ );
45
+ }}
46
+ />
47
+ );
48
+ }
49
+
50
+ export const CreateChatMemberInput = customize(
51
+ 'CreateChatMemberInput',
52
+ (props: CreateChatMemberInputProps) => {
53
+ const { name } = props;
54
+ const localizer = useLocalizer();
55
+
56
+ return (
57
+ <Form.Item
58
+ label={localizer.addChat.members.label()}
59
+ rules={[{ required: true, message: localizer.addChat.members.required() }]}
60
+ name={name}
61
+ >
62
+ <CheckboxList />
63
+ </Form.Item>
64
+ );
65
+ },
66
+ );
@@ -0,0 +1,25 @@
1
+ import { Form, Input } from 'antd';
2
+ import { customize } from '../customize';
3
+ import { useLocalizer } from '../localizer';
4
+
5
+ export interface CreateChatNameInputProps {
6
+ name: string;
7
+ }
8
+
9
+ export const CreateChatNameInput = customize('CreateChatNameInput', (props: CreateChatNameInputProps) => {
10
+ const { name } = props;
11
+ const localizer = useLocalizer();
12
+
13
+ return (
14
+ <Form.Item
15
+ name={name}
16
+ label={localizer.addChat.name.label()}
17
+ rules={[
18
+ { required: true, message: localizer.addChat.name.required() },
19
+ { max: 250, message: localizer.addChat.name.max250() },
20
+ ]}
21
+ >
22
+ <Input />
23
+ </Form.Item>
24
+ );
25
+ });
@@ -0,0 +1,33 @@
1
+ import { useAddChatMutation } from '../../core';
2
+ import { useCallback } from 'react';
3
+ import { uniqId } from '../../util';
4
+ import { useLocalizer } from '../localizer';
5
+ import { CreateChatForm, CreateChatFormValue } from './CreateChatForm';
6
+ import { customize } from '../customize';
7
+
8
+ function useSubmit() {
9
+ const [add, { isFetching }] = useAddChatMutation();
10
+ const onSubmit = useCallback(
11
+ (value: CreateChatFormValue) =>
12
+ add({
13
+ name: value.name,
14
+ members: value.members,
15
+ requestId: uniqId(),
16
+ }),
17
+ [add],
18
+ );
19
+
20
+ return [onSubmit, isFetching] as const;
21
+ }
22
+
23
+ export const CreateChatPanel = customize('CreateChatPanel', () => {
24
+ const localizer = useLocalizer();
25
+ const [onSubmit, submitting] = useSubmit();
26
+
27
+ return (
28
+ <div className="wxchtf-create-chat">
29
+ <h3>{localizer.addChat.title()}</h3>
30
+ <CreateChatForm busy={submitting ?? false} onSubmit={onSubmit} />
31
+ </div>
32
+ );
33
+ });
@@ -0,0 +1,4 @@
1
+ export * from './CreateChatForm';
2
+ export * from './CreateChatMemberInput';
3
+ export * from './CreateChatNameInput';
4
+ export * from './CreateChatPanel';
package/src/ui/Icon.tsx CHANGED
@@ -1,20 +1,32 @@
1
1
  import { FC } from 'react';
2
- import { customize } from '../util';
2
+ import { customize } from './customize';
3
3
  import SendOutlined from '@ant-design/icons/SendOutlined';
4
- import FileAddOutlined from '@ant-design/icons/FileAddOutlined';
4
+ import PaperClipOutlined from '@ant-design/icons/PaperClipOutlined';
5
+ import UserAddOutlined from '@ant-design/icons/UserAddOutlined';
6
+ import UsergroupAddOutlined from '@ant-design/icons/UsergroupAddOutlined';
7
+ import UserDeleteOutlined from '@ant-design/icons/UserDeleteOutlined';
8
+ import UsergroupDeleteOutlined from '@ant-design/icons/UsergroupDeleteOutlined';
9
+ import TeamOutlined from '@ant-design/icons/TeamOutlined';
10
+ import EditOutlined from '@ant-design/icons/EditOutlined';
5
11
 
6
- export type IconType = 'attach' | 'send';
12
+ export type IconType = keyof typeof ICONS;
7
13
 
8
14
  export interface IconProps {
9
15
  type: IconType;
10
16
  }
11
17
 
12
- export const ICONS: Record<IconType, React.ComponentType> = {
13
- attach: FileAddOutlined,
18
+ export const ICONS = {
19
+ attach: PaperClipOutlined,
14
20
  send: SendOutlined,
21
+ remove: UserDeleteOutlined,
22
+ remove_delete_history: UsergroupDeleteOutlined,
23
+ add: UserAddOutlined,
24
+ add_with_history: UsergroupAddOutlined,
25
+ team: TeamOutlined,
26
+ edit: EditOutlined,
15
27
  };
16
28
 
17
- export const Icon = customize<FC<IconProps>, string>('Icon', (props) => {
29
+ export const Icon = customize<FC<IconProps>>('Icon', (props) => {
18
30
  const { type } = props;
19
31
  const IconComponent = ICONS[type];
20
32
  return IconComponent ? <IconComponent /> : null;
@@ -0,0 +1,38 @@
1
+ import { useCallback, useState } from 'react';
2
+ import { useSelect, useSendMutation } from '../../core';
3
+ import { uniqId } from '../../util';
4
+ import { InputFilesBox } from './InputFilesBox';
5
+ import { InputTextBox } from './InputTextBox';
6
+ import { customize } from '../customize';
7
+ import { InputSubmitButtonBox } from './InputSubmitButtonBox';
8
+
9
+ function useSend(text: string, setText: (value: string) => void) {
10
+ const chatId = useSelect((x) => x.ui.chatId!, []);
11
+ const [add] = useSendMutation();
12
+
13
+ return useCallback(() => {
14
+ if (text.length === 0) {
15
+ return;
16
+ }
17
+
18
+ setText('');
19
+ add({ chatId, text: text, files: [], requestId: uniqId() });
20
+
21
+ // eslint-disable-next-line react-hooks/exhaustive-deps
22
+ }, [chatId, text]);
23
+ }
24
+
25
+ export const InputBox = customize('InputBox', () => {
26
+ const [text, setText] = useState('');
27
+ const onSend = useSend(text, setText);
28
+
29
+ return (
30
+ <div className="wxchtf-input-form">
31
+ <div className="wxchtf-input-box">
32
+ <InputFilesBox />
33
+ <InputTextBox value={text} onSend={onSend} onChange={setText} />
34
+ <InputSubmitButtonBox onSubmit={onSend} />
35
+ </div>
36
+ </div>
37
+ );
38
+ });
@@ -0,0 +1,9 @@
1
+ import { Button } from 'antd';
2
+ import { customize } from '../customize';
3
+ import { Icon } from '../Icon';
4
+
5
+ export const InputFilesBox = customize('InputFilesBox', () => (
6
+ <div className="wxchtf-add-files-box">
7
+ <Button type="link" icon={<Icon type="attach" />} className="wxchtf-add-files-btn" />
8
+ </div>
9
+ ));
@@ -0,0 +1,17 @@
1
+ import { Button } from 'antd';
2
+ import { customize } from '../customize';
3
+ import { Icon } from '../Icon';
4
+
5
+ export interface InputSubmitButtonBoxProps {
6
+ onSubmit: () => void;
7
+ }
8
+
9
+ export const InputSubmitButtonBox = customize('InputSubmitButtonBox', (props: InputSubmitButtonBoxProps) => {
10
+ const { onSubmit } = props;
11
+
12
+ return (
13
+ <div className="wxchtf-submit-btn-box">
14
+ <Button onClick={onSubmit} type="link" icon={<Icon type="send" />} className="wxchtf-submit-btn" />
15
+ </div>
16
+ );
17
+ });