@webinex/chatify 1.0.0-rc3 → 1.0.2-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 (98) hide show
  1. package/dist/esm/index.js +1 -1
  2. package/dist/esm/index.js.map +1 -1
  3. package/dist/esm/types/core/action.d.ts +10 -4
  4. package/dist/esm/types/core/state.d.ts +2 -1
  5. package/dist/esm/types/core/useGetAccountsQuery.d.ts +3 -1
  6. package/dist/esm/types/core/useGetChatListQuery.d.ts +3 -1
  7. package/dist/esm/types/core/useGetChatQuery.d.ts +3 -1
  8. package/dist/esm/types/ui/Icon.d.ts +8 -8
  9. package/dist/index.d.ts +21 -14
  10. package/package.json +92 -92
  11. package/src/ChatifyContext.tsx +41 -41
  12. package/src/core/action.tsx +421 -405
  13. package/src/core/client.ts +143 -143
  14. package/src/core/index.ts +17 -17
  15. package/src/core/models.tsx +82 -82
  16. package/src/core/reducer.tsx +87 -87
  17. package/src/core/state.ts +93 -92
  18. package/src/core/useAddChatMutation.tsx +22 -22
  19. package/src/core/useAddMemberMutation.tsx +25 -25
  20. package/src/core/useFetchNextMutation.tsx +28 -28
  21. package/src/core/useGetAccountsQuery.tsx +30 -33
  22. package/src/core/useGetChatListQuery.tsx +30 -33
  23. package/src/core/useGetChatQuery.tsx +31 -34
  24. package/src/core/useGetMessagesQuery.tsx +35 -35
  25. package/src/core/useReadMonitor.tsx +32 -32
  26. package/src/core/useRemoveMemberMutation.tsx +23 -23
  27. package/src/core/useSendMutation.tsx +24 -24
  28. package/src/core/useSignalRMonitor.tsx +66 -66
  29. package/src/core/useUpdateChatNameMutation.tsx +23 -23
  30. package/src/index.ts +3 -3
  31. package/src/styles/aside.scss +94 -94
  32. package/src/styles/chat.scss +222 -222
  33. package/src/styles/index.scss +79 -79
  34. package/src/styles/keyframes.scss +14 -14
  35. package/src/styles/mixins.scss +20 -20
  36. package/src/styles/settings.scss +5 -5
  37. package/src/styles/variables.scss +10 -10
  38. package/src/ui/AddChatButton.tsx +15 -15
  39. package/src/ui/Avatar.tsx +18 -18
  40. package/src/ui/ChatList/ChatList.tsx +42 -42
  41. package/src/ui/ChatList/ChatListItemBox.tsx +22 -22
  42. package/src/ui/ChatList/ChatListItemLastMessage.tsx +13 -13
  43. package/src/ui/ChatList/ChatListItemLastMessageAuthor.tsx +20 -20
  44. package/src/ui/ChatList/ChatListItemLastMessageContent.tsx +21 -21
  45. package/src/ui/ChatList/ChatListItemName.tsx +13 -13
  46. package/src/ui/ChatList/ChatListItemUnreadCount.tsx +12 -12
  47. package/src/ui/ChatList/index.ts +7 -7
  48. package/src/ui/ChatName.tsx +10 -10
  49. package/src/ui/ChatPanel/ChatBody.tsx +44 -44
  50. package/src/ui/ChatPanel/ChatHeader.tsx +33 -33
  51. package/src/ui/ChatPanel/ChatHeaderMembers.tsx +26 -26
  52. package/src/ui/ChatPanel/ChatHeaderName.tsx +67 -67
  53. package/src/ui/ChatPanel/ChatMembersButton.tsx +21 -21
  54. package/src/ui/ChatPanel/ChatMembersPanel.tsx +117 -117
  55. package/src/ui/ChatPanel/ChatPanel.tsx +27 -27
  56. package/src/ui/ChatPanel/index.ts +6 -6
  57. package/src/ui/Chatify.tsx +148 -148
  58. package/src/ui/CreateChatPanel/CreateChatForm.tsx +36 -36
  59. package/src/ui/CreateChatPanel/CreateChatMemberInput.tsx +66 -66
  60. package/src/ui/CreateChatPanel/CreateChatNameInput.tsx +25 -25
  61. package/src/ui/CreateChatPanel/CreateChatPanel.tsx +33 -33
  62. package/src/ui/CreateChatPanel/index.ts +4 -4
  63. package/src/ui/Icon.tsx +33 -33
  64. package/src/ui/InputBox/InputBox.tsx +38 -38
  65. package/src/ui/InputBox/InputFilesBox.tsx +9 -9
  66. package/src/ui/InputBox/InputSubmitButtonBox.tsx +17 -17
  67. package/src/ui/InputBox/InputTextBox.tsx +50 -50
  68. package/src/ui/InputBox/index.ts +4 -4
  69. package/src/ui/Layout/Aside.tsx +10 -10
  70. package/src/ui/Layout/Body.tsx +10 -10
  71. package/src/ui/Layout/Footer.tsx +3 -3
  72. package/src/ui/Layout/Header.tsx +10 -10
  73. package/src/ui/Layout/Main.tsx +15 -15
  74. package/src/ui/Layout/index.ts +5 -5
  75. package/src/ui/Message/MessageAuthor.tsx +13 -13
  76. package/src/ui/Message/MessageBox.tsx +20 -20
  77. package/src/ui/Message/MessageContent.tsx +13 -13
  78. package/src/ui/Message/MessageInfoBox.tsx +25 -25
  79. package/src/ui/Message/MessageRow.tsx +24 -24
  80. package/src/ui/Message/MessageText.tsx +7 -7
  81. package/src/ui/Message/index.ts +6 -6
  82. package/src/ui/MessageReadObserver.tsx +45 -45
  83. package/src/ui/MessageSkeleton.tsx +19 -19
  84. package/src/ui/Next.tsx +48 -48
  85. package/src/ui/SendingMessage/SendingMessageBox.tsx +16 -16
  86. package/src/ui/SendingMessage/SendingMessageContent.tsx +13 -13
  87. package/src/ui/SendingMessage/SendingMessageInfoBox.tsx +13 -13
  88. package/src/ui/SendingMessage/SendingMessageText.tsx +7 -7
  89. package/src/ui/SendingMessage/index.ts +4 -4
  90. package/src/ui/SystemMessage/SystemMessageBox.tsx +20 -20
  91. package/src/ui/SystemMessage/SystemMessageRow.tsx +43 -43
  92. package/src/ui/SystemMessage/index.ts +2 -2
  93. package/src/ui/customize.tsx +45 -45
  94. package/src/ui/index.ts +11 -11
  95. package/src/ui/localizer.tsx +80 -80
  96. package/src/util/index.ts +2 -2
  97. package/src/util/uniqBy.tsx +17 -17
  98. package/src/util/uniqId.tsx +3 -3
package/src/core/state.ts CHANGED
@@ -1,92 +1,93 @@
1
- import { Account, Chat, ChatListItem, Message, SendMessageRequest, File } from './models';
2
-
3
- export type MessageState =
4
- | ({ type: 'message' } & Message)
5
- | { type: 'next' }
6
- | { type: 'sending'; text: string; files: File[]; requestId: string };
7
-
8
- export interface UIState {
9
- view?: 'chat' | 'new-chat';
10
- showMembers: boolean;
11
- chatId?: string;
12
- }
13
-
14
- export interface QueryState<TData> {
15
- uninitialized: boolean;
16
- isFetching: boolean;
17
- error?: any;
18
- data?: TData;
19
- }
20
-
21
- export interface MutationState {
22
- isFetching: boolean;
23
- error?: any;
24
- }
25
-
26
- export interface QueueState<TValue> {
27
- queued: TValue[];
28
- processing: TValue[];
29
- timestamp: number;
30
- }
31
-
32
- export interface State {
33
- ui: UIState;
34
- query: {
35
- messages: Record<string, QueryState<MessageState[]>>;
36
- chats: Record<string, QueryState<Chat>>;
37
- chatList: QueryState<ChatListItem[]>;
38
- accounts: QueryState<Account[]>;
39
- };
40
- mutation: {
41
- fetchNext: MutationState;
42
- removeMember: MutationState;
43
- addMember: MutationState;
44
- updateChatName: MutationState;
45
- addChat: MutationState;
46
- send: MutationState;
47
- };
48
- queue: {
49
- read: QueueState<string>;
50
- send: QueueState<SendMessageRequest>;
51
- };
52
- }
53
-
54
- export const INITIAL_QUERY_STATE: QueryState<any> = {
55
- uninitialized: false,
56
- isFetching: true,
57
- data: undefined,
58
- error: undefined,
59
- };
60
-
61
- export const INITIAL_STATE: State = {
62
- ui: {
63
- showMembers: false,
64
- },
65
- query: {
66
- messages: {},
67
- chats: {},
68
- chatList: { uninitialized: true, isFetching: false, data: undefined, error: undefined },
69
- accounts: { uninitialized: true, isFetching: false, data: undefined, error: undefined },
70
- },
71
- mutation: {
72
- fetchNext: { isFetching: false, error: undefined },
73
- removeMember: { isFetching: false, error: undefined },
74
- addMember: { isFetching: false, error: undefined },
75
- updateChatName: { isFetching: false, error: undefined },
76
- addChat: { isFetching: false, error: undefined },
77
- send: { isFetching: false, error: undefined },
78
- },
79
- queue: {
80
- read: {
81
- queued: [],
82
- processing: [],
83
- timestamp: 0,
84
- },
85
-
86
- send: {
87
- queued: [],
88
- processing: [],
89
- timestamp: 0,
90
- },
91
- },
92
- };
1
+ import { Account, Chat, ChatListItem, Message, SendMessageRequest, File } from './models';
2
+
3
+ export type MessageState =
4
+ | ({ type: 'message' } & Message)
5
+ | { type: 'next' }
6
+ | { type: 'sending'; text: string; files: File[]; requestId: string };
7
+
8
+ export interface UIState {
9
+ view?: 'chat' | 'new-chat';
10
+ showMembers: boolean;
11
+ chatId?: string;
12
+ }
13
+
14
+ export interface QueryState<TData> {
15
+ uninitialized: boolean;
16
+ isFetching: boolean;
17
+ error?: any;
18
+ data?: TData;
19
+ requestId?: string;
20
+ }
21
+
22
+ export interface MutationState {
23
+ isFetching: boolean;
24
+ error?: any;
25
+ }
26
+
27
+ export interface QueueState<TValue> {
28
+ queued: TValue[];
29
+ processing: TValue[];
30
+ timestamp: number;
31
+ }
32
+
33
+ export interface State {
34
+ ui: UIState;
35
+ query: {
36
+ messages: Record<string, QueryState<MessageState[]>>;
37
+ chats: Record<string, QueryState<Chat>>;
38
+ chatList: QueryState<ChatListItem[]>;
39
+ accounts: QueryState<Account[]>;
40
+ };
41
+ mutation: {
42
+ fetchNext: MutationState;
43
+ removeMember: MutationState;
44
+ addMember: MutationState;
45
+ updateChatName: MutationState;
46
+ addChat: MutationState;
47
+ send: MutationState;
48
+ };
49
+ queue: {
50
+ read: QueueState<string>;
51
+ send: QueueState<SendMessageRequest>;
52
+ };
53
+ }
54
+
55
+ export const FETCH_QUERY_STATE: QueryState<any> = Object.freeze({
56
+ uninitialized: false,
57
+ isFetching: true,
58
+ data: undefined,
59
+ error: undefined,
60
+ });
61
+
62
+ export const INITIAL_STATE: State = {
63
+ ui: {
64
+ showMembers: false,
65
+ },
66
+ query: {
67
+ messages: {},
68
+ chats: {},
69
+ chatList: { uninitialized: true, isFetching: false, data: undefined, error: undefined },
70
+ accounts: { uninitialized: true, isFetching: false, data: undefined, error: undefined },
71
+ },
72
+ mutation: {
73
+ fetchNext: { isFetching: false, error: undefined },
74
+ removeMember: { isFetching: false, error: undefined },
75
+ addMember: { isFetching: false, error: undefined },
76
+ updateChatName: { isFetching: false, error: undefined },
77
+ addChat: { isFetching: false, error: undefined },
78
+ send: { isFetching: false, error: undefined },
79
+ },
80
+ queue: {
81
+ read: {
82
+ queued: [],
83
+ processing: [],
84
+ timestamp: 0,
85
+ },
86
+
87
+ send: {
88
+ queued: [],
89
+ processing: [],
90
+ timestamp: 0,
91
+ },
92
+ },
93
+ };
@@ -1,22 +1,22 @@
1
- import { useCallback } from 'react';
2
- import { useClient } from '../ChatifyContext';
3
- import { AddChatRequest } from './models';
4
- import { useDispatch, useStateRef } from './reducer';
5
-
6
- export function useAddChatMutation() {
7
- const client = useClient();
8
- const dispatch = useDispatch();
9
- const stateRef = useStateRef();
10
-
11
- const invoke = useCallback((args: AddChatRequest) => {
12
- dispatch({ type: 'addChat_fetch', data: void 0 });
13
- client
14
- .addChat(args)
15
- .then(() => dispatch({ type: 'addChat_fulfilled', data: void 0 }))
16
- .catch((error) => dispatch({ type: 'addChat_rejected', data: { error } }));
17
-
18
- // eslint-disable-next-line react-hooks/exhaustive-deps
19
- }, []);
20
-
21
- return [invoke, stateRef.current.mutation.addChat] as const;
22
- }
1
+ import { useCallback } from 'react';
2
+ import { useClient } from '../ChatifyContext';
3
+ import { AddChatRequest } from './models';
4
+ import { useDispatch, useStateRef } from './reducer';
5
+
6
+ export function useAddChatMutation() {
7
+ const client = useClient();
8
+ const dispatch = useDispatch();
9
+ const stateRef = useStateRef();
10
+
11
+ const invoke = useCallback((args: AddChatRequest) => {
12
+ dispatch({ type: 'addChat_fetch', data: void 0 });
13
+ client
14
+ .addChat(args)
15
+ .then(() => dispatch({ type: 'addChat_fulfilled', data: void 0 }))
16
+ .catch((error) => dispatch({ type: 'addChat_rejected', data: { error } }));
17
+
18
+ // eslint-disable-next-line react-hooks/exhaustive-deps
19
+ }, []);
20
+
21
+ return [invoke, stateRef.current.mutation.addChat] as const;
22
+ }
@@ -1,25 +1,25 @@
1
- import { useCallback } from 'react';
2
- import { useClient } from '../ChatifyContext';
3
- import { AddMemberRequest } from './models';
4
- import { useDispatch, useSelect, useStateRef } from './reducer';
5
-
6
- export function useAddMemberMutation() {
7
- const client = useClient();
8
- const dispatch = useDispatch();
9
- const state = useStateRef();
10
- useSelect((x) => x.mutation.addMember, []);
11
-
12
- const invoke = useCallback(
13
- (args: AddMemberRequest) => {
14
- dispatch({ type: 'addMember_fetch', data: void 0 });
15
- client
16
- .addMember(args)
17
- .then(() => dispatch({ type: 'addMember_fulfilled', data: void 0 }))
18
- .catch((error) => dispatch({ type: 'addMember_rejected', data: { error } }));
19
- },
20
- // eslint-disable-next-line react-hooks/exhaustive-deps
21
- [dispatch],
22
- );
23
-
24
- return [invoke, state.current.mutation.addMember] as const;
25
- }
1
+ import { useCallback } from 'react';
2
+ import { useClient } from '../ChatifyContext';
3
+ import { AddMemberRequest } from './models';
4
+ import { useDispatch, useSelect, useStateRef } from './reducer';
5
+
6
+ export function useAddMemberMutation() {
7
+ const client = useClient();
8
+ const dispatch = useDispatch();
9
+ const state = useStateRef();
10
+ useSelect((x) => x.mutation.addMember, []);
11
+
12
+ const invoke = useCallback(
13
+ (args: AddMemberRequest) => {
14
+ dispatch({ type: 'addMember_fetch', data: void 0 });
15
+ client
16
+ .addMember(args)
17
+ .then(() => dispatch({ type: 'addMember_fulfilled', data: void 0 }))
18
+ .catch((error) => dispatch({ type: 'addMember_rejected', data: { error } }));
19
+ },
20
+ // eslint-disable-next-line react-hooks/exhaustive-deps
21
+ [dispatch],
22
+ );
23
+
24
+ return [invoke, state.current.mutation.addMember] as const;
25
+ }
@@ -1,28 +1,28 @@
1
- import { useClient } from '../ChatifyContext';
2
- import { useDispatch, useSelect, useStateRef } from './reducer';
3
- import { useCallback } from 'react';
4
-
5
- export function useFetchNextMutation({ chatId }: { chatId: string }) {
6
- const state = useStateRef();
7
- useSelect((x) => x.mutation.fetchNext, []);
8
- const dispatch = useDispatch();
9
- const client = useClient();
10
-
11
- const fetchNext = useCallback(() => {
12
- const skip = state.current.query.messages[chatId].data?.filter((x) => x.type === 'message').length;
13
- dispatch({ type: 'fetchNext_fetch', data: { chatId } });
14
- client
15
- .messages({ chatId, skip, take: 16 })
16
- .then((messages) =>
17
- dispatch({
18
- type: 'fetchNext_fulfilled',
19
- data: { chatId, messages: messages.slice(0, 15), hasMore: messages.length === 16 },
20
- }),
21
- )
22
- .catch((error) => dispatch({ type: 'fetchNext_rejected', data: { chatId, error } }));
23
-
24
- // eslint-disable-next-line react-hooks/exhaustive-deps
25
- }, [chatId]);
26
-
27
- return [fetchNext, state.current.mutation.fetchNext] as const;
28
- }
1
+ import { useClient } from '../ChatifyContext';
2
+ import { useDispatch, useSelect, useStateRef } from './reducer';
3
+ import { useCallback } from 'react';
4
+
5
+ export function useFetchNextMutation({ chatId }: { chatId: string }) {
6
+ const state = useStateRef();
7
+ useSelect((x) => x.mutation.fetchNext, []);
8
+ const dispatch = useDispatch();
9
+ const client = useClient();
10
+
11
+ const fetchNext = useCallback(() => {
12
+ const skip = state.current.query.messages[chatId].data?.filter((x) => x.type === 'message').length;
13
+ dispatch({ type: 'fetchNext_fetch', data: { chatId } });
14
+ client
15
+ .messages({ chatId, skip, take: 16 })
16
+ .then((messages) =>
17
+ dispatch({
18
+ type: 'fetchNext_fulfilled',
19
+ data: { chatId, messages: messages.slice(0, 15), hasMore: messages.length === 16 },
20
+ }),
21
+ )
22
+ .catch((error) => dispatch({ type: 'fetchNext_rejected', data: { chatId, error } }));
23
+
24
+ // eslint-disable-next-line react-hooks/exhaustive-deps
25
+ }, [chatId]);
26
+
27
+ return [fetchNext, state.current.mutation.fetchNext] as const;
28
+ }
@@ -1,33 +1,30 @@
1
- import { useEffect, useMemo } from 'react';
2
- import { useClient } from '../ChatifyContext';
3
- import { useDispatch, useSelect, useStateRef } from './reducer';
4
-
5
- export function useGetAccountsQuery() {
6
- const client = useClient();
7
- const stateRef = useStateRef();
8
- useSelect((x) => x.query.accounts, []);
9
- const dispatch = useDispatch();
10
-
11
- const uninitialized = useMemo(() => {
12
- const uninitialized = stateRef.current.query.accounts.uninitialized !== false;
13
- uninitialized && dispatch({ type: 'accounts_fetch', data: void 0 });
14
- return uninitialized;
15
-
16
- // eslint-disable-next-line react-hooks/exhaustive-deps
17
- }, []);
18
-
19
- useEffect(() => {
20
- if (!uninitialized) {
21
- return;
22
- }
23
-
24
- client
25
- .accounts()
26
- .then((accounts) => dispatch({ type: 'accounts_fulfilled', data: { accounts } }))
27
- .catch((error) => dispatch({ type: 'accounts_rejected', data: { error } }));
28
-
29
- // eslint-disable-next-line react-hooks/exhaustive-deps
30
- }, [uninitialized]);
31
-
32
- return stateRef.current.query.accounts;
33
- }
1
+ import { useEffect, useRef } from 'react';
2
+ import { useClient } from '../ChatifyContext';
3
+ import { useDispatch, useSelect, useStateRef } from './reducer';
4
+ import { FETCH_QUERY_STATE, QueryState } from './state';
5
+ import { uniqId } from '../util';
6
+ import { Account } from './models';
7
+
8
+ export function useGetAccountsQuery(): QueryState<Account[]> {
9
+ const id = useRef(uniqId());
10
+ const client = useClient();
11
+ const stateRef = useStateRef();
12
+ const queryState = useSelect((x) => x.query.accounts, []) ?? FETCH_QUERY_STATE;
13
+ const dispatch = useDispatch();
14
+
15
+ useEffect(() => {
16
+ if (stateRef.current.query.accounts.uninitialized === false) {
17
+ return;
18
+ }
19
+
20
+ dispatch({ type: 'accounts_fetch', data: { requestId: id.current } });
21
+ client
22
+ .accounts()
23
+ .then((accounts) => dispatch({ type: 'accounts_fulfilled', data: { accounts } }))
24
+ .catch((error) => dispatch({ type: 'accounts_rejected', data: { error } }));
25
+
26
+ // eslint-disable-next-line react-hooks/exhaustive-deps
27
+ }, []);
28
+
29
+ return queryState ?? FETCH_QUERY_STATE;
30
+ }
@@ -1,33 +1,30 @@
1
- import { useEffect, useMemo } from 'react';
2
- import { useClient } from '../ChatifyContext';
3
- import { useDispatch, useSelect, useStateRef } from './reducer';
4
-
5
- export function useGetChatListQuery() {
6
- const stateRef = useStateRef();
7
- const client = useClient();
8
- useSelect((x) => x.query.chatList, []);
9
- const dispatch = useDispatch();
10
-
11
- const uninitialized = useMemo(() => {
12
- const uninitialized = stateRef.current.query.chatList.uninitialized !== false;
13
- uninitialized && dispatch({ type: 'chatList_fetch', data: void 0 });
14
- return uninitialized;
15
-
16
- // eslint-disable-next-line react-hooks/exhaustive-deps
17
- }, []);
18
-
19
- useEffect(() => {
20
- if (!uninitialized) {
21
- return;
22
- }
23
-
24
- client
25
- .chats()
26
- .then((chats) => dispatch({ type: 'chatList_fulfilled', data: { chats } }))
27
- .catch((error) => dispatch({ type: 'chatList_rejected', data: { error } }));
28
-
29
- // eslint-disable-next-line react-hooks/exhaustive-deps
30
- }, []);
31
-
32
- return stateRef.current.query.chatList;
33
- }
1
+ import { useEffect, useRef } from 'react';
2
+ import { useClient } from '../ChatifyContext';
3
+ import { useDispatch, useSelect, useStateRef } from './reducer';
4
+ import { uniqId } from '../util';
5
+ import { FETCH_QUERY_STATE, QueryState } from './state';
6
+ import { ChatListItem } from './models';
7
+
8
+ export function useGetChatListQuery(): QueryState<ChatListItem[]> {
9
+ const id = useRef(uniqId());
10
+ const stateRef = useStateRef();
11
+ const client = useClient();
12
+ const queryState = useSelect((x) => x.query.chatList, []) ?? FETCH_QUERY_STATE;
13
+ const dispatch = useDispatch();
14
+
15
+ useEffect(() => {
16
+ if (stateRef.current.query.chatList.uninitialized === false) {
17
+ return;
18
+ }
19
+
20
+ dispatch({ type: 'chatList_fetch', data: { requestId: id.current } });
21
+ client
22
+ .chats()
23
+ .then((chats) => dispatch({ type: 'chatList_fulfilled', data: { chats } }))
24
+ .catch((error) => dispatch({ type: 'chatList_rejected', data: { error } }));
25
+
26
+ // eslint-disable-next-line react-hooks/exhaustive-deps
27
+ }, []);
28
+
29
+ return queryState ?? FETCH_QUERY_STATE;
30
+ }
@@ -1,34 +1,31 @@
1
- import { useEffect, useMemo } from 'react';
2
- import { useClient } from '../ChatifyContext';
3
- import { useDispatch, useSelect, useStateRef } from './reducer';
4
-
5
- export function useGetChatQuery(args: { chatId: string }) {
6
- const { chatId } = args;
7
- const client = useClient();
8
- const stateRef = useStateRef();
9
- useSelect((x) => x.query.chats[chatId], [chatId]);
10
- const dispatch = useDispatch();
11
-
12
- const uninitialized = useMemo(() => {
13
- const uninitialized = stateRef.current.query.chats[chatId]?.uninitialized !== false;
14
- uninitialized && dispatch({ type: 'chat_fetch', data: { chatId } });
15
- return uninitialized;
16
-
17
- // eslint-disable-next-line react-hooks/exhaustive-deps
18
- }, [chatId]);
19
-
20
- useEffect(() => {
21
- if (!uninitialized) {
22
- return;
23
- }
24
-
25
- client
26
- .chat(chatId)
27
- .then((chat) => dispatch({ type: 'chat_fulfilled', data: { chat } }))
28
- .catch((error) => dispatch({ type: 'chat_rejected', data: { chatId, error } }));
29
-
30
- // eslint-disable-next-line react-hooks/exhaustive-deps
31
- }, [uninitialized, chatId]);
32
-
33
- return stateRef.current.query.chats[chatId];
34
- }
1
+ import { useEffect, useRef } from 'react';
2
+ import { useClient } from '../ChatifyContext';
3
+ import { useDispatch, useSelect, useStateRef } from './reducer';
4
+ import { uniqId } from '../util';
5
+ import { FETCH_QUERY_STATE, QueryState } from './state';
6
+ import { Chat } from './models';
7
+
8
+ export function useGetChatQuery(args: { chatId: string }): QueryState<Chat> {
9
+ const id = useRef(uniqId());
10
+ const { chatId } = args;
11
+ const client = useClient();
12
+ const stateRef = useStateRef();
13
+ const queryState = useSelect((x) => x.query.chats[chatId], [chatId]) ?? FETCH_QUERY_STATE;
14
+ const dispatch = useDispatch();
15
+
16
+ useEffect(() => {
17
+ if (stateRef.current.query.chats[chatId]?.uninitialized === true) {
18
+ return;
19
+ }
20
+
21
+ dispatch({ type: 'chat_fetch', data: { chatId, requestId: id.current } });
22
+ client
23
+ .chat(chatId)
24
+ .then((chat) => dispatch({ type: 'chat_fulfilled', data: { chat } }))
25
+ .catch((error) => dispatch({ type: 'chat_rejected', data: { chatId, error } }));
26
+
27
+ // eslint-disable-next-line react-hooks/exhaustive-deps
28
+ }, [chatId]);
29
+
30
+ return queryState ?? FETCH_QUERY_STATE;
31
+ }
@@ -1,35 +1,35 @@
1
- import { useEffect, useMemo } from 'react';
2
- import { useClient } from '../ChatifyContext';
3
- import { MessageState, QueryState } from './state';
4
- import { useDispatch, useSelect, useStateRef } from './reducer';
5
-
6
- export function useGetMessagesQuery(args: { chatId: string }): QueryState<MessageState[]> {
7
- const { chatId } = args;
8
- const stateRef = useStateRef();
9
- const dispatch = useDispatch();
10
- useSelect((x) => x.query.messages[chatId], [chatId]);
11
- const client = useClient();
12
-
13
- const uninitialized = useMemo(() => {
14
- const uninitialized = stateRef.current.query.messages[chatId]?.uninitialized !== false;
15
- uninitialized && dispatch({ type: 'messages_fetch', data: { chatId } });
16
- return uninitialized;
17
- }, [chatId, dispatch, stateRef]);
18
-
19
- useEffect(() => {
20
- if (!uninitialized) {
21
- return;
22
- }
23
-
24
- client.messages({ chatId, skip: 0, take: 16 }).then((messages) =>
25
- dispatch({
26
- type: 'messages_fulfilled',
27
- data: { chatId, messages: messages.slice(0, 15), hasMore: messages.length === 16 },
28
- }),
29
- );
30
-
31
- // eslint-disable-next-line react-hooks/exhaustive-deps
32
- }, [chatId]);
33
-
34
- return stateRef.current.query.messages[chatId];
35
- }
1
+ import { useEffect, useRef } from 'react';
2
+ import { useClient } from '../ChatifyContext';
3
+ import { FETCH_QUERY_STATE, MessageState, QueryState } from './state';
4
+ import { useDispatch, useSelect, useStateRef } from './reducer';
5
+ import { uniqId } from '../util';
6
+
7
+ export function useGetMessagesQuery(args: { chatId: string }): QueryState<MessageState[]> {
8
+ const { chatId } = args;
9
+ const id = useRef(uniqId());
10
+ const stateRef = useStateRef();
11
+ const dispatch = useDispatch();
12
+ useSelect((x) => x.query.messages[chatId], [chatId]);
13
+ const client = useClient();
14
+
15
+ useEffect(() => {
16
+ if (stateRef.current.query.messages[chatId]?.uninitialized === false) {
17
+ return;
18
+ }
19
+
20
+ dispatch({ type: 'messages_fetch', data: { requestId: id.current, chatId } });
21
+ client
22
+ .messages({ chatId, skip: 0, take: 16 })
23
+ .then((messages) =>
24
+ dispatch({
25
+ type: 'messages_fulfilled',
26
+ data: { chatId, messages: messages.slice(0, 15), hasMore: messages.length === 16 },
27
+ }),
28
+ )
29
+ .catch((error) => dispatch({ type: 'messages_rejected', data: { chatId, error } }));
30
+
31
+ // eslint-disable-next-line react-hooks/exhaustive-deps
32
+ }, [chatId]);
33
+
34
+ return stateRef.current.query.messages[chatId] ?? FETCH_QUERY_STATE;
35
+ }