@ethora/chat-component-rn 26.7.4 → 26.7.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +0 -54
- package/README.md +8 -31
- package/lib/commonjs/assets/icons.js +2 -7
- package/lib/commonjs/assets/icons.js.map +1 -1
- package/lib/commonjs/components/Header/HeaderRoomList.js +6 -20
- package/lib/commonjs/components/Header/HeaderRoomList.js.map +1 -1
- package/lib/commonjs/components/MainComponents/ChatRoom.js +14 -36
- package/lib/commonjs/components/MainComponents/ChatRoom.js.map +1 -1
- package/lib/commonjs/components/MainComponents/MessageList.js +23 -7
- package/lib/commonjs/components/MainComponents/MessageList.js.map +1 -1
- package/lib/commonjs/components/MainComponents/ProfileImagePlaceholder.js +13 -14
- package/lib/commonjs/components/MainComponents/ProfileImagePlaceholder.js.map +1 -1
- package/lib/commonjs/components/MainComponents/RoomList.js +32 -62
- package/lib/commonjs/components/MainComponents/RoomList.js.map +1 -1
- package/lib/commonjs/components/Menu/HeaderRoomListMenu.js +98 -309
- package/lib/commonjs/components/Menu/HeaderRoomListMenu.js.map +1 -1
- package/lib/commonjs/components/Modals/AttachSheet/AttachSheet.js +110 -320
- package/lib/commonjs/components/Modals/AttachSheet/AttachSheet.js.map +1 -1
- package/lib/commonjs/components/Modals/ChatProfileModal/ChatProfileModal.js +213 -552
- package/lib/commonjs/components/Modals/ChatProfileModal/ChatProfileModal.js.map +1 -1
- package/lib/commonjs/components/Modals/FilePreviewModal/FilePreviewModal.js +2 -6
- package/lib/commonjs/components/Modals/FilePreviewModal/FilePreviewModal.js.map +1 -1
- package/lib/commonjs/components/Modals/Modal/Modal.js +0 -8
- package/lib/commonjs/components/Modals/Modal/Modal.js.map +1 -1
- package/lib/commonjs/components/Modals/NewChatModal/ModalContent.js +1 -2
- package/lib/commonjs/components/Modals/NewChatModal/ModalContent.js.map +1 -1
- package/lib/commonjs/components/Modals/NewChatModal/NewChatModal.js +104 -202
- package/lib/commonjs/components/Modals/NewChatModal/NewChatModal.js.map +1 -1
- package/lib/commonjs/components/Modals/NewChatModal/UpdNewChatModal.js +0 -8
- package/lib/commonjs/components/Modals/NewChatModal/UpdNewChatModal.js.map +1 -1
- package/lib/commonjs/components/Modals/SelectUsersModal/SelectUsersModal.js +2 -4
- package/lib/commonjs/components/Modals/SelectUsersModal/SelectUsersModal.js.map +1 -1
- package/lib/commonjs/components/Modals/UserProfileModal/EditUserModal.js +21 -7
- package/lib/commonjs/components/Modals/UserProfileModal/EditUserModal.js.map +1 -1
- package/lib/commonjs/components/Modals/UserProfileModal/UserProfileModal.js +244 -507
- package/lib/commonjs/components/Modals/UserProfileModal/UserProfileModal.js.map +1 -1
- package/lib/commonjs/components/Modals/UserSettingsModal/UserSettingsModal.js +46 -74
- package/lib/commonjs/components/Modals/UserSettingsModal/UserSettingsModal.js.map +1 -1
- package/lib/commonjs/components/Modals/styledModalComponents.js +2 -9
- package/lib/commonjs/components/Modals/styledModalComponents.js.map +1 -1
- package/lib/commonjs/components/RoomComponents/ChatRoomItem.js +7 -17
- package/lib/commonjs/components/RoomComponents/ChatRoomItem.js.map +1 -1
- package/lib/commonjs/components/styled/SendInput.js +11 -80
- package/lib/commonjs/components/styled/SendInput.js.map +1 -1
- package/lib/commonjs/components/styled/StyledComponents.js +3 -9
- package/lib/commonjs/components/styled/StyledComponents.js.map +1 -1
- package/lib/commonjs/components/styled/StyledInputComponents/StyledInputComponents.js +4 -11
- package/lib/commonjs/components/styled/StyledInputComponents/StyledInputComponents.js.map +1 -1
- package/lib/commonjs/context/xmppProvider.js +35 -6
- package/lib/commonjs/context/xmppProvider.js.map +1 -1
- package/lib/commonjs/helpers/updateMessagesTillLast.js +40 -12
- package/lib/commonjs/helpers/updateMessagesTillLast.js.map +1 -1
- package/lib/commonjs/hooks/useChatRoomFocus.js +9 -3
- package/lib/commonjs/hooks/useChatRoomFocus.js.map +1 -1
- package/lib/commonjs/hooks/useLogout.js +5 -0
- package/lib/commonjs/hooks/useLogout.js.map +1 -1
- package/lib/commonjs/hooks/useSendMessage.js +50 -23
- package/lib/commonjs/hooks/useSendMessage.js.map +1 -1
- package/lib/commonjs/i18n/strings.js +1 -121
- package/lib/commonjs/i18n/strings.js.map +1 -1
- package/lib/commonjs/main.js +0 -6
- package/lib/commonjs/main.js.map +1 -1
- package/lib/commonjs/networking/api-requests/user.api.js +0 -59
- package/lib/commonjs/networking/api-requests/user.api.js.map +1 -1
- package/lib/commonjs/networking/outboundQueue.js +18 -0
- package/lib/commonjs/networking/outboundQueue.js.map +1 -1
- package/lib/commonjs/networking/stanzaHandlers.js +10 -1
- package/lib/commonjs/networking/stanzaHandlers.js.map +1 -1
- package/lib/commonjs/networking/xmppClient.js +107 -7
- package/lib/commonjs/networking/xmppClient.js.map +1 -1
- package/lib/commonjs/roomStore/chatSettingsSlice.js +1 -3
- package/lib/commonjs/roomStore/chatSettingsSlice.js.map +1 -1
- package/lib/commonjs/roomStore/roomsSlice.js +22 -3
- package/lib/commonjs/roomStore/roomsSlice.js.map +1 -1
- package/lib/module/assets/icons.js +1 -6
- package/lib/module/assets/icons.js.map +1 -1
- package/lib/module/components/Header/HeaderRoomList.js +6 -20
- package/lib/module/components/Header/HeaderRoomList.js.map +1 -1
- package/lib/module/components/MainComponents/ChatRoom.js +14 -36
- package/lib/module/components/MainComponents/ChatRoom.js.map +1 -1
- package/lib/module/components/MainComponents/MessageList.js +24 -8
- package/lib/module/components/MainComponents/MessageList.js.map +1 -1
- package/lib/module/components/MainComponents/ProfileImagePlaceholder.js +13 -14
- package/lib/module/components/MainComponents/ProfileImagePlaceholder.js.map +1 -1
- package/lib/module/components/MainComponents/RoomList.js +32 -62
- package/lib/module/components/MainComponents/RoomList.js.map +1 -1
- package/lib/module/components/Menu/HeaderRoomListMenu.js +101 -311
- package/lib/module/components/Menu/HeaderRoomListMenu.js.map +1 -1
- package/lib/module/components/Modals/AttachSheet/AttachSheet.js +113 -311
- package/lib/module/components/Modals/AttachSheet/AttachSheet.js.map +1 -1
- package/lib/module/components/Modals/ChatProfileModal/ChatProfileModal.js +217 -555
- package/lib/module/components/Modals/ChatProfileModal/ChatProfileModal.js.map +1 -1
- package/lib/module/components/Modals/FilePreviewModal/FilePreviewModal.js +2 -6
- package/lib/module/components/Modals/FilePreviewModal/FilePreviewModal.js.map +1 -1
- package/lib/module/components/Modals/Modal/Modal.js +1 -9
- package/lib/module/components/Modals/Modal/Modal.js.map +1 -1
- package/lib/module/components/Modals/NewChatModal/ModalContent.js +1 -2
- package/lib/module/components/Modals/NewChatModal/ModalContent.js.map +1 -1
- package/lib/module/components/Modals/NewChatModal/NewChatModal.js +106 -205
- package/lib/module/components/Modals/NewChatModal/NewChatModal.js.map +1 -1
- package/lib/module/components/Modals/NewChatModal/UpdNewChatModal.js +0 -8
- package/lib/module/components/Modals/NewChatModal/UpdNewChatModal.js.map +1 -1
- package/lib/module/components/Modals/SelectUsersModal/SelectUsersModal.js +2 -4
- package/lib/module/components/Modals/SelectUsersModal/SelectUsersModal.js.map +1 -1
- package/lib/module/components/Modals/UserProfileModal/EditUserModal.js +23 -9
- package/lib/module/components/Modals/UserProfileModal/EditUserModal.js.map +1 -1
- package/lib/module/components/Modals/UserProfileModal/UserProfileModal.js +248 -509
- package/lib/module/components/Modals/UserProfileModal/UserProfileModal.js.map +1 -1
- package/lib/module/components/Modals/UserSettingsModal/UserSettingsModal.js +48 -76
- package/lib/module/components/Modals/UserSettingsModal/UserSettingsModal.js.map +1 -1
- package/lib/module/components/Modals/styledModalComponents.js +2 -9
- package/lib/module/components/Modals/styledModalComponents.js.map +1 -1
- package/lib/module/components/RoomComponents/ChatRoomItem.js +7 -17
- package/lib/module/components/RoomComponents/ChatRoomItem.js.map +1 -1
- package/lib/module/components/styled/SendInput.js +12 -81
- package/lib/module/components/styled/SendInput.js.map +1 -1
- package/lib/module/components/styled/StyledComponents.js +3 -9
- package/lib/module/components/styled/StyledComponents.js.map +1 -1
- package/lib/module/components/styled/StyledInputComponents/StyledInputComponents.js +4 -11
- package/lib/module/components/styled/StyledInputComponents/StyledInputComponents.js.map +1 -1
- package/lib/module/context/xmppProvider.js +35 -6
- package/lib/module/context/xmppProvider.js.map +1 -1
- package/lib/module/helpers/updateMessagesTillLast.js +41 -13
- package/lib/module/helpers/updateMessagesTillLast.js.map +1 -1
- package/lib/module/hooks/useChatRoomFocus.js +9 -3
- package/lib/module/hooks/useChatRoomFocus.js.map +1 -1
- package/lib/module/hooks/useLogout.js +5 -0
- package/lib/module/hooks/useLogout.js.map +1 -1
- package/lib/module/hooks/useSendMessage.js +51 -24
- package/lib/module/hooks/useSendMessage.js.map +1 -1
- package/lib/module/i18n/strings.js +1 -121
- package/lib/module/i18n/strings.js.map +1 -1
- package/lib/module/main.js +1 -1
- package/lib/module/main.js.map +1 -1
- package/lib/module/networking/api-requests/user.api.js +0 -56
- package/lib/module/networking/api-requests/user.api.js.map +1 -1
- package/lib/module/networking/outboundQueue.js +17 -0
- package/lib/module/networking/outboundQueue.js.map +1 -1
- package/lib/module/networking/stanzaHandlers.js +10 -1
- package/lib/module/networking/stanzaHandlers.js.map +1 -1
- package/lib/module/networking/xmppClient.js +107 -7
- package/lib/module/networking/xmppClient.js.map +1 -1
- package/lib/module/roomStore/chatSettingsSlice.js +1 -3
- package/lib/module/roomStore/chatSettingsSlice.js.map +1 -1
- package/lib/module/roomStore/roomsSlice.js +20 -2
- package/lib/module/roomStore/roomsSlice.js.map +1 -1
- package/lib/typescript/assets/icons.d.ts +0 -16
- package/lib/typescript/assets/icons.d.ts.map +1 -1
- package/lib/typescript/components/Header/HeaderRoomList.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/ChatRoom.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/MessageList.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/ProfileImagePlaceholder.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/RoomList.d.ts.map +1 -1
- package/lib/typescript/components/Menu/HeaderRoomListMenu.d.ts +0 -3
- package/lib/typescript/components/Menu/HeaderRoomListMenu.d.ts.map +1 -1
- package/lib/typescript/components/Modals/AttachSheet/AttachSheet.d.ts +0 -9
- package/lib/typescript/components/Modals/AttachSheet/AttachSheet.d.ts.map +1 -1
- package/lib/typescript/components/Modals/ChatProfileModal/ChatProfileModal.d.ts +0 -10
- package/lib/typescript/components/Modals/ChatProfileModal/ChatProfileModal.d.ts.map +1 -1
- package/lib/typescript/components/Modals/FilePreviewModal/FilePreviewModal.d.ts.map +1 -1
- package/lib/typescript/components/Modals/Modal/Modal.d.ts.map +1 -1
- package/lib/typescript/components/Modals/NewChatModal/ModalContent.d.ts +2 -4
- package/lib/typescript/components/Modals/NewChatModal/ModalContent.d.ts.map +1 -1
- package/lib/typescript/components/Modals/NewChatModal/NewChatModal.d.ts +1 -1
- package/lib/typescript/components/Modals/NewChatModal/NewChatModal.d.ts.map +1 -1
- package/lib/typescript/components/Modals/NewChatModal/UpdNewChatModal.d.ts.map +1 -1
- package/lib/typescript/components/Modals/SelectUsersModal/SelectUsersModal.d.ts +1 -6
- package/lib/typescript/components/Modals/SelectUsersModal/SelectUsersModal.d.ts.map +1 -1
- package/lib/typescript/components/Modals/UserProfileModal/EditUserModal.d.ts.map +1 -1
- package/lib/typescript/components/Modals/UserProfileModal/UserProfileModal.d.ts +0 -16
- package/lib/typescript/components/Modals/UserProfileModal/UserProfileModal.d.ts.map +1 -1
- package/lib/typescript/components/Modals/UserSettingsModal/UserSettingsModal.d.ts +0 -1
- package/lib/typescript/components/Modals/UserSettingsModal/UserSettingsModal.d.ts.map +1 -1
- package/lib/typescript/components/Modals/styledModalComponents.d.ts.map +1 -1
- package/lib/typescript/components/RoomComponents/ChatRoomItem.d.ts.map +1 -1
- package/lib/typescript/components/styled/SendInput.d.ts.map +1 -1
- package/lib/typescript/components/styled/StyledComponents.d.ts.map +1 -1
- package/lib/typescript/components/styled/StyledInputComponents/StyledInputComponents.d.ts.map +1 -1
- package/lib/typescript/context/xmppProvider.d.ts.map +1 -1
- package/lib/typescript/helpers/updateMessagesTillLast.d.ts.map +1 -1
- package/lib/typescript/hooks/useChatRoomFocus.d.ts.map +1 -1
- package/lib/typescript/hooks/useLogout.d.ts.map +1 -1
- package/lib/typescript/hooks/useSendMessage.d.ts.map +1 -1
- package/lib/typescript/i18n/strings.d.ts.map +1 -1
- package/lib/typescript/main.d.ts +1 -1
- package/lib/typescript/main.d.ts.map +1 -1
- package/lib/typescript/networking/api-requests/user.api.d.ts +0 -27
- package/lib/typescript/networking/api-requests/user.api.d.ts.map +1 -1
- package/lib/typescript/networking/outboundQueue.d.ts +16 -0
- package/lib/typescript/networking/outboundQueue.d.ts.map +1 -1
- package/lib/typescript/networking/stanzaHandlers.d.ts.map +1 -1
- package/lib/typescript/networking/xmppClient.d.ts +33 -1
- package/lib/typescript/networking/xmppClient.d.ts.map +1 -1
- package/lib/typescript/roomStore/chatSettingsSlice.d.ts.map +1 -1
- package/lib/typescript/roomStore/roomsSlice.d.ts +18 -1
- package/lib/typescript/roomStore/roomsSlice.d.ts.map +1 -1
- package/lib/typescript/types/models/room.model.d.ts +15 -0
- package/lib/typescript/types/models/room.model.d.ts.map +1 -1
- package/lib/typescript/types/types.d.ts +20 -20
- package/lib/typescript/types/types.d.ts.map +1 -1
- package/package.json +1 -6
- package/src/assets/icons.tsx +9 -48
- package/src/components/Header/HeaderRoomList.tsx +5 -20
- package/src/components/MainComponents/ChatRoom.tsx +20 -38
- package/src/components/MainComponents/MessageList.tsx +24 -8
- package/src/components/MainComponents/ProfileImagePlaceholder.tsx +14 -21
- package/src/components/MainComponents/RoomList.tsx +34 -65
- package/src/components/Menu/HeaderRoomListMenu.tsx +71 -310
- package/src/components/Modals/AttachSheet/AttachSheet.tsx +97 -331
- package/src/components/Modals/ChatProfileModal/ChatProfileModal.tsx +279 -598
- package/src/components/Modals/FilePreviewModal/FilePreviewModal.tsx +2 -4
- package/src/components/Modals/Modal/Modal.tsx +0 -7
- package/src/components/Modals/NewChatModal/ModalContent.tsx +3 -6
- package/src/components/Modals/NewChatModal/NewChatModal.tsx +117 -219
- package/src/components/Modals/NewChatModal/UpdNewChatModal.tsx +1 -12
- package/src/components/Modals/SelectUsersModal/SelectUsersModal.tsx +4 -14
- package/src/components/Modals/UserProfileModal/EditUserModal.tsx +25 -9
- package/src/components/Modals/UserProfileModal/UserProfileModal.tsx +307 -617
- package/src/components/Modals/UserSettingsModal/UserSettingsModal.tsx +58 -75
- package/src/components/Modals/styledModalComponents.tsx +2 -9
- package/src/components/RoomComponents/ChatRoomItem.tsx +7 -14
- package/src/components/styled/SendInput.tsx +12 -83
- package/src/components/styled/StyledComponents.ts +3 -9
- package/src/components/styled/StyledInputComponents/StyledInputComponents.tsx +4 -11
- package/src/context/xmppProvider.tsx +41 -8
- package/src/helpers/updateMessagesTillLast.tsx +42 -17
- package/src/hooks/useChatRoomFocus.ts +11 -3
- package/src/hooks/useLogout.tsx +7 -0
- package/src/hooks/useSendMessage.tsx +60 -24
- package/src/i18n/strings.ts +1 -121
- package/src/main.ts +1 -1
- package/src/networking/api-requests/user.api.ts +0 -71
- package/src/networking/outboundQueue.ts +29 -0
- package/src/networking/stanzaHandlers.ts +9 -1
- package/src/networking/xmppClient.ts +118 -7
- package/src/roomStore/chatSettingsSlice.ts +1 -3
- package/src/roomStore/roomsSlice.ts +20 -2
- package/src/types/models/room.model.ts +15 -0
- package/src/types/types.ts +20 -22
- package/lib/commonjs/components/Modals/ChatProfileModal/ReportChatModal.js +0 -226
- package/lib/commonjs/components/Modals/ChatProfileModal/ReportChatModal.js.map +0 -1
- package/lib/commonjs/components/Modals/ProfileHeader/ProfileHeader.js +0 -556
- package/lib/commonjs/components/Modals/ProfileHeader/ProfileHeader.js.map +0 -1
- package/lib/commonjs/components/Modals/ProfileHeader/ProfileMenu.js +0 -210
- package/lib/commonjs/components/Modals/ProfileHeader/ProfileMenu.js.map +0 -1
- package/lib/commonjs/helpers/getChatBackground.js +0 -23
- package/lib/commonjs/helpers/getChatBackground.js.map +0 -1
- package/lib/commonjs/helpers/mediaLibraryRuntime.js +0 -31
- package/lib/commonjs/helpers/mediaLibraryRuntime.js.map +0 -1
- package/lib/commonjs/helpers/pickImageAsset.js +0 -68
- package/lib/commonjs/helpers/pickImageAsset.js.map +0 -1
- package/lib/commonjs/helpers/sheetGestures.js +0 -32
- package/lib/commonjs/helpers/sheetGestures.js.map +0 -1
- package/lib/module/components/Modals/ChatProfileModal/ReportChatModal.js +0 -223
- package/lib/module/components/Modals/ChatProfileModal/ReportChatModal.js.map +0 -1
- package/lib/module/components/Modals/ProfileHeader/ProfileHeader.js +0 -548
- package/lib/module/components/Modals/ProfileHeader/ProfileHeader.js.map +0 -1
- package/lib/module/components/Modals/ProfileHeader/ProfileMenu.js +0 -205
- package/lib/module/components/Modals/ProfileHeader/ProfileMenu.js.map +0 -1
- package/lib/module/helpers/getChatBackground.js +0 -18
- package/lib/module/helpers/getChatBackground.js.map +0 -1
- package/lib/module/helpers/mediaLibraryRuntime.js +0 -25
- package/lib/module/helpers/mediaLibraryRuntime.js.map +0 -1
- package/lib/module/helpers/pickImageAsset.js +0 -63
- package/lib/module/helpers/pickImageAsset.js.map +0 -1
- package/lib/module/helpers/sheetGestures.js +0 -26
- package/lib/module/helpers/sheetGestures.js.map +0 -1
- package/lib/typescript/components/Modals/ChatProfileModal/ReportChatModal.d.ts +0 -9
- package/lib/typescript/components/Modals/ChatProfileModal/ReportChatModal.d.ts.map +0 -1
- package/lib/typescript/components/Modals/ProfileHeader/ProfileHeader.d.ts +0 -75
- package/lib/typescript/components/Modals/ProfileHeader/ProfileHeader.d.ts.map +0 -1
- package/lib/typescript/components/Modals/ProfileHeader/ProfileMenu.d.ts +0 -25
- package/lib/typescript/components/Modals/ProfileHeader/ProfileMenu.d.ts.map +0 -1
- package/lib/typescript/helpers/getChatBackground.d.ts +0 -15
- package/lib/typescript/helpers/getChatBackground.d.ts.map +0 -1
- package/lib/typescript/helpers/mediaLibraryRuntime.d.ts +0 -3
- package/lib/typescript/helpers/mediaLibraryRuntime.d.ts.map +0 -1
- package/lib/typescript/helpers/pickImageAsset.d.ts +0 -27
- package/lib/typescript/helpers/pickImageAsset.d.ts.map +0 -1
- package/lib/typescript/helpers/sheetGestures.d.ts +0 -20
- package/lib/typescript/helpers/sheetGestures.d.ts.map +0 -1
- package/src/components/Modals/ChatProfileModal/ReportChatModal.tsx +0 -244
- package/src/components/Modals/ProfileHeader/ProfileHeader.tsx +0 -615
- package/src/components/Modals/ProfileHeader/ProfileMenu.tsx +0 -217
- package/src/helpers/getChatBackground.ts +0 -18
- package/src/helpers/mediaLibraryRuntime.ts +0 -25
- package/src/helpers/pickImageAsset.ts +0 -68
- package/src/helpers/sheetGestures.ts +0 -25
|
@@ -1,16 +1,18 @@
|
|
|
1
|
-
/** @format */
|
|
2
|
-
|
|
3
1
|
import React, { useCallback, useMemo } from 'react';
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
ModalContainerFullScreen,
|
|
5
|
+
Viewider,
|
|
6
|
+
Label,
|
|
7
|
+
LabelData,
|
|
8
|
+
BorderedContainer,
|
|
9
|
+
CenterContainer,
|
|
10
|
+
} from '../styledModalComponents';
|
|
7
11
|
import ModalHeaderComponent from '../ModalHeaderComponent';
|
|
8
|
-
import
|
|
12
|
+
import Button from '../../styled/Button';
|
|
13
|
+
import { useDispatch } from 'react-redux';
|
|
9
14
|
import { setActiveModal } from '../../../roomStore/chatSettingsSlice';
|
|
10
15
|
import { MODAL_TYPES } from '../../../helpers/constants/MODAL_TYPES';
|
|
11
|
-
import { useChatSettingState } from '../../../hooks/useChatSettingState';
|
|
12
|
-
import { chatTextStyle } from '../../../helpers/typography';
|
|
13
|
-
import { useT } from '../../../i18n/useT';
|
|
14
16
|
|
|
15
17
|
interface UserSettingsModalProps {
|
|
16
18
|
handleCloseModal: any;
|
|
@@ -19,84 +21,65 @@ interface UserSettingsModalProps {
|
|
|
19
21
|
const UserSettingsModal: React.FC<UserSettingsModalProps> = ({
|
|
20
22
|
handleCloseModal,
|
|
21
23
|
}) => {
|
|
22
|
-
const t = useT();
|
|
23
|
-
const dispatch = useDispatch();
|
|
24
|
-
const { config } = useChatSettingState();
|
|
25
|
-
|
|
26
24
|
const options = useMemo(
|
|
27
25
|
() => [
|
|
28
|
-
{
|
|
29
|
-
{
|
|
26
|
+
{ value: 'Manage Data', key: MODAL_TYPES.MANAGE_DATA },
|
|
27
|
+
{ value: 'Visiblility', key: MODAL_TYPES.VISIBILITY },
|
|
28
|
+
// { value: 'Profile Shares', key: MODAL_TYPES.PROFILE_SHARES },
|
|
29
|
+
// { value: 'Document Shares', key: MODAL_TYPES.DOCUMENT_SHARES },
|
|
30
|
+
// { value: 'Blocked Users', key: MODAL_TYPES.BLOCKED_USERS },
|
|
31
|
+
// { value: 'Referrals', key: MODAL_TYPES.REFERRALS },
|
|
30
32
|
],
|
|
31
|
-
[
|
|
33
|
+
[]
|
|
32
34
|
);
|
|
33
35
|
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
);
|
|
36
|
+
const dispatch = useDispatch();
|
|
37
|
+
|
|
38
|
+
const handleClick = useCallback((key: string) => {
|
|
39
|
+
dispatch(setActiveModal(key as any));
|
|
40
|
+
}, []);
|
|
40
41
|
|
|
41
42
|
return (
|
|
42
|
-
<ModalContainerFullScreen
|
|
43
|
+
<ModalContainerFullScreen>
|
|
43
44
|
<ModalHeaderComponent
|
|
44
45
|
handleCloseModal={handleCloseModal}
|
|
45
|
-
headerTitle={
|
|
46
|
-
titleStyle={chatTextStyle(config?.typography?.profile?.screenTitle)}
|
|
46
|
+
headerTitle={'Settings'}
|
|
47
47
|
/>
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
48
|
+
<CenterContainer>
|
|
49
|
+
<BorderedContainer
|
|
50
|
+
style={{
|
|
51
|
+
padding: 16,
|
|
52
|
+
display: 'flex',
|
|
53
|
+
flexDirection: 'column',
|
|
54
|
+
gap: 8,
|
|
55
|
+
}}
|
|
56
|
+
>
|
|
57
|
+
{options.map((option: { value: string; key: string }, index) => (
|
|
58
|
+
<>
|
|
59
|
+
<Button
|
|
60
|
+
variant="default"
|
|
61
|
+
style={{
|
|
62
|
+
minHeight: 40,
|
|
63
|
+
display: 'flex',
|
|
64
|
+
flexDirection: 'column',
|
|
65
|
+
gap: 2,
|
|
66
|
+
width: '100%',
|
|
67
|
+
justifyContent: 'center',
|
|
68
|
+
borderRadius: 0,
|
|
69
|
+
alignItems: 'flex-start',
|
|
70
|
+
}}
|
|
71
|
+
onPress={() => handleClick(option.key)}
|
|
72
|
+
>
|
|
73
|
+
<Label style={{ textAlign: 'center' }}>{option.value}</Label>
|
|
74
|
+
{[2, 3, 4].includes(index) && <LabelData>0</LabelData>}
|
|
75
|
+
</Button>
|
|
76
|
+
{index < 5 && <Viewider />}
|
|
77
|
+
</>
|
|
78
|
+
))}
|
|
79
|
+
</BorderedContainer>
|
|
80
|
+
</CenterContainer>
|
|
65
81
|
</ModalContainerFullScreen>
|
|
66
82
|
);
|
|
67
83
|
};
|
|
68
84
|
|
|
69
|
-
const styles = StyleSheet.create({
|
|
70
|
-
screen: {
|
|
71
|
-
backgroundColor: '#E8EDF2',
|
|
72
|
-
},
|
|
73
|
-
body: {
|
|
74
|
-
width: '100%',
|
|
75
|
-
padding: 12,
|
|
76
|
-
gap: 12,
|
|
77
|
-
},
|
|
78
|
-
card: {
|
|
79
|
-
flexDirection: 'row',
|
|
80
|
-
alignItems: 'center',
|
|
81
|
-
justifyContent: 'space-between',
|
|
82
|
-
backgroundColor: '#FFFFFF',
|
|
83
|
-
borderRadius: 20,
|
|
84
|
-
paddingHorizontal: 20,
|
|
85
|
-
paddingVertical: 22,
|
|
86
|
-
shadowColor: '#101828',
|
|
87
|
-
shadowOffset: { width: 0, height: 4 },
|
|
88
|
-
shadowOpacity: 0.06,
|
|
89
|
-
shadowRadius: 12,
|
|
90
|
-
elevation: 3,
|
|
91
|
-
},
|
|
92
|
-
label: {
|
|
93
|
-
fontSize: 17,
|
|
94
|
-
fontWeight: '500',
|
|
95
|
-
color: '#141414',
|
|
96
|
-
},
|
|
97
|
-
chevron: {
|
|
98
|
-
transform: [{ rotate: '-90deg' }],
|
|
99
|
-
},
|
|
100
|
-
});
|
|
101
|
-
|
|
102
85
|
export default UserSettingsModal;
|
|
@@ -86,15 +86,8 @@ export const HeaderContainer = styled.View`
|
|
|
86
86
|
* button and 8px below — properly sized and properly centered. */
|
|
87
87
|
padding: 8px 16px;
|
|
88
88
|
background-color: #fff;
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
border-bottom-left-radius: 20px;
|
|
92
|
-
border-bottom-right-radius: 20px;
|
|
93
|
-
shadow-color: #101828;
|
|
94
|
-
shadow-offset: 0px 4px;
|
|
95
|
-
shadow-opacity: 0.06;
|
|
96
|
-
shadow-radius: 12px;
|
|
97
|
-
elevation: 4;
|
|
89
|
+
border-bottom-width: 1px;
|
|
90
|
+
border-bottom-color: #f0f0f0;
|
|
98
91
|
z-index: 1;
|
|
99
92
|
flex-direction: row;
|
|
100
93
|
justify-content: space-between;
|
|
@@ -90,13 +90,11 @@ const ChatRoomItem: React.FC<ChatRoomItemProps> = ({
|
|
|
90
90
|
|
|
91
91
|
return (
|
|
92
92
|
<ChatItem key={index}>
|
|
93
|
-
<
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
/>
|
|
99
|
-
</View>
|
|
93
|
+
<ProfileImagePlaceholder
|
|
94
|
+
name={displayName}
|
|
95
|
+
icon={appendFileToken(chat?.icon, fileToken)}
|
|
96
|
+
active={false}
|
|
97
|
+
/>
|
|
100
98
|
<View
|
|
101
99
|
style={{
|
|
102
100
|
flexDirection: 'column',
|
|
@@ -106,9 +104,7 @@ const ChatRoomItem: React.FC<ChatRoomItemProps> = ({
|
|
|
106
104
|
paddingVertical: 8,
|
|
107
105
|
paddingRight: 8,
|
|
108
106
|
borderBottomWidth: 1,
|
|
109
|
-
|
|
110
|
-
// than the ground itself, so the row separators vanished.
|
|
111
|
-
borderBottomColor: '#C6CFDA',
|
|
107
|
+
borderBottomColor: '#F0F0F0',
|
|
112
108
|
}}
|
|
113
109
|
>
|
|
114
110
|
<View
|
|
@@ -219,11 +215,8 @@ const ChatRoomItem: React.FC<ChatRoomItemProps> = ({
|
|
|
219
215
|
) : null}
|
|
220
216
|
</View>
|
|
221
217
|
{isDriver && (
|
|
222
|
-
// Darker than the list's own ground (#E8EDF2), otherwise the
|
|
223
|
-
// separator disappears into it — white and the old #0052CD0D
|
|
224
|
-
// hairline both did.
|
|
225
218
|
<View
|
|
226
|
-
style={{ height: 1, backgroundColor: '#
|
|
219
|
+
style={{ height: 1, backgroundColor: '#0052CD0D', marginTop: 8 }}
|
|
227
220
|
/>
|
|
228
221
|
)}
|
|
229
222
|
</View>
|
|
@@ -10,16 +10,14 @@ import { IConfig, MediaFile } from '../../types/types';
|
|
|
10
10
|
import Button from './Button';
|
|
11
11
|
import { SendIcon, AttachIcon, RecordIcon } from '../../assets/icons';
|
|
12
12
|
import { KeyboardAvoidingView, Platform, View, Text, TouchableOpacity, Alert, Linking } from 'react-native';
|
|
13
|
-
import AttachSheet
|
|
13
|
+
import AttachSheet from '../Modals/AttachSheet/AttachSheet';
|
|
14
14
|
import { MediaFilePreview } from './MediaFilePreview';
|
|
15
15
|
import { getIconColor } from '../../helpers/getIconColor';
|
|
16
16
|
import { getElementFont } from '../../helpers/getElementFont';
|
|
17
17
|
import { useT } from '../../i18n/useT';
|
|
18
|
-
import { getMediaLibrary } from '../../helpers/mediaLibraryRuntime';
|
|
19
18
|
import * as ImagePicker from 'expo-image-picker';
|
|
20
19
|
import * as DocumentPicker from 'expo-document-picker';
|
|
21
20
|
import * as ImageManipulator from 'expo-image-manipulator';
|
|
22
|
-
import * as FileSystem from 'expo-file-system/legacy';
|
|
23
21
|
// expo-audio replaces the discontinued expo-av: `useAudioRecorder` owns a
|
|
24
22
|
// single reusable recorder for this input's lifetime (prepare → record →
|
|
25
23
|
// stop → prepare again), and the module-level helpers cover permissions
|
|
@@ -261,59 +259,22 @@ const SendInput: React.FC<SendInputProps> = ({
|
|
|
261
259
|
}
|
|
262
260
|
};
|
|
263
261
|
|
|
264
|
-
// A tap on a thumbnail in the attach sheet's recents strip. The sheet
|
|
265
|
-
// already resolved the asset to a real on-disk uri (iOS `ph://` ids are
|
|
266
|
-
// not uploadable); here we apply the same treatment the full-blown
|
|
267
|
-
// pickers get — HEIC→JPEG for images, and a size probe so the 50 MB cap
|
|
268
|
-
// is enforced before anything hits the network.
|
|
269
|
-
const handleRecentMediaSelection = async (media: PickedMedia) => {
|
|
270
|
-
try {
|
|
271
|
-
let size: number | undefined;
|
|
272
|
-
try {
|
|
273
|
-
const info = await FileSystem.getInfoAsync(media.uri);
|
|
274
|
-
if (info.exists && typeof (info as any).size === 'number') {
|
|
275
|
-
size = (info as any).size;
|
|
276
|
-
}
|
|
277
|
-
} catch {
|
|
278
|
-
// Size is a nice-to-have; the backend still rejects oversized bodies.
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
if (media.isVideo) {
|
|
282
|
-
handleFileSelect([
|
|
283
|
-
{
|
|
284
|
-
uri: media.uri,
|
|
285
|
-
type: media.mimeType || 'video/mp4',
|
|
286
|
-
name: media.name,
|
|
287
|
-
size,
|
|
288
|
-
},
|
|
289
|
-
]);
|
|
290
|
-
return;
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
const normalized = await normalizeImageAsset({
|
|
294
|
-
uri: media.uri,
|
|
295
|
-
mimeType: media.mimeType,
|
|
296
|
-
fileName: media.name,
|
|
297
|
-
} as ImagePicker.ImagePickerAsset);
|
|
298
|
-
handleFileSelect([
|
|
299
|
-
{
|
|
300
|
-
uri: normalized.uri,
|
|
301
|
-
type: normalized.mime,
|
|
302
|
-
name: normalized.name,
|
|
303
|
-
size,
|
|
304
|
-
},
|
|
305
|
-
]);
|
|
306
|
-
} catch (error) {
|
|
307
|
-
console.error('Recent media error:', error);
|
|
308
|
-
}
|
|
309
|
-
};
|
|
310
|
-
|
|
311
262
|
const handleFileSelection = async () => {
|
|
312
263
|
// Drop overlapping invocations — a second getDocumentAsync while the
|
|
313
264
|
// first is still presented throws PickingInProgressException on iOS.
|
|
314
265
|
if (pickingDocRef.current) {return;}
|
|
315
266
|
pickingDocRef.current = true;
|
|
316
267
|
try {
|
|
268
|
+
// Let the attach-sheet's modal finish its NATIVE dismissal before we
|
|
269
|
+
// present the picker. The sheet fires this handler right after its
|
|
270
|
+
// slide-out animation, but the underlying RN Modal view-controller
|
|
271
|
+
// dismissal is async — presenting the document picker over a still-
|
|
272
|
+
// dismissing modal makes iOS tear it down without a cancel callback,
|
|
273
|
+
// which strands expo-document-picker's pickingContext and makes every
|
|
274
|
+
// subsequent open throw "Different document picking in progress".
|
|
275
|
+
if (Platform.OS === 'ios') {
|
|
276
|
+
await new Promise((resolve) => setTimeout(resolve, 350));
|
|
277
|
+
}
|
|
317
278
|
const result = await DocumentPicker.getDocumentAsync({
|
|
318
279
|
type: '*/*',
|
|
319
280
|
multiple: false,
|
|
@@ -336,39 +297,8 @@ const SendInput: React.FC<SendInputProps> = ({
|
|
|
336
297
|
}
|
|
337
298
|
};
|
|
338
299
|
|
|
339
|
-
// Photo-library access is requested HERE, not inside the sheet: iOS
|
|
340
|
-
// cannot present the permission alert while an RN <Modal> owns the
|
|
341
|
-
// screen (the same UIKit limitation that used to swallow the pickers),
|
|
342
|
-
// so asking from inside resolved to a silent "denied" and the recents
|
|
343
|
-
// strip stayed empty forever. Asking on the paperclip tap puts the
|
|
344
|
-
// system alert over the plain chat screen, where it can actually show.
|
|
345
|
-
// Only the first tap ever waits on it — afterwards the status is
|
|
346
|
-
// already determined and `getPermissionsAsync` returns immediately.
|
|
347
|
-
const ensureLibraryPermission = async () => {
|
|
348
|
-
const MediaLibrary = getMediaLibrary();
|
|
349
|
-
if (!MediaLibrary?.getPermissionsAsync) {return;}
|
|
350
|
-
try {
|
|
351
|
-
const perm = await MediaLibrary.getPermissionsAsync();
|
|
352
|
-
if (perm?.granted || perm?.canAskAgain === false) {return;}
|
|
353
|
-
await MediaLibrary.requestPermissionsAsync();
|
|
354
|
-
} catch (err) {
|
|
355
|
-
// Optional peer / unsupported platform: the sheet just shows the
|
|
356
|
-
// camera tile and the full-library route.
|
|
357
|
-
console.warn('Media library permission check failed:', err);
|
|
358
|
-
}
|
|
359
|
-
};
|
|
360
|
-
|
|
361
|
-
// Only the very first tap of a session goes through the permission
|
|
362
|
-
// check; afterwards the sheet opens with zero added latency.
|
|
363
|
-
const libraryPermissionCheckedRef = useRef(false);
|
|
364
|
-
|
|
365
300
|
const handleAttachPress = () => {
|
|
366
|
-
|
|
367
|
-
setShowMediaMenu(true);
|
|
368
|
-
return;
|
|
369
|
-
}
|
|
370
|
-
libraryPermissionCheckedRef.current = true;
|
|
371
|
-
ensureLibraryPermission().finally(() => setShowMediaMenu(true));
|
|
301
|
+
setShowMediaMenu(true);
|
|
372
302
|
};
|
|
373
303
|
|
|
374
304
|
// ─── Voice recording ──────────────────────────────────────────────
|
|
@@ -772,7 +702,6 @@ const SendInput: React.FC<SendInputProps> = ({
|
|
|
772
702
|
onCamera={handleCameraSelection}
|
|
773
703
|
onGallery={handleGallerySelection}
|
|
774
704
|
onDocument={handleFileSelection}
|
|
775
|
-
onPickMedia={handleRecentMediaSelection}
|
|
776
705
|
primaryColor={getIconColor(config)}
|
|
777
706
|
/>
|
|
778
707
|
</InputContainer>
|
|
@@ -28,15 +28,9 @@ export const ChatContainerHeader = styled.View`
|
|
|
28
28
|
background-color: #ffffff;
|
|
29
29
|
align-items: center;
|
|
30
30
|
justify-content: space-between;
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
border-
|
|
34
|
-
border-bottom-right-radius: 20px;
|
|
35
|
-
shadow-color: #101828;
|
|
36
|
-
shadow-offset: 0px 4px;
|
|
37
|
-
shadow-opacity: 0.06;
|
|
38
|
-
shadow-radius: 12px;
|
|
39
|
-
elevation: 4;
|
|
31
|
+
border-bottom-width: 1px;
|
|
32
|
+
border-bottom-color: #e5e7eb;
|
|
33
|
+
border-style: solid;
|
|
40
34
|
z-index: 1000;
|
|
41
35
|
`;
|
|
42
36
|
|
|
@@ -13,21 +13,14 @@ const colors = {
|
|
|
13
13
|
|
|
14
14
|
export const InputContainer = styled.View<{ isText?: boolean }>`
|
|
15
15
|
flex-direction: column;
|
|
16
|
-
padding:
|
|
17
|
-
|
|
18
|
-
* corners — are what shows. An opaque child painted straight over those
|
|
19
|
-
* corners (a parent's border radius does not clip children without
|
|
20
|
-
* overflow:hidden, and that would clip the dock's shadow too). */
|
|
21
|
-
background-color: transparent;
|
|
16
|
+
padding: 8px 16px 4px 16px;
|
|
17
|
+
background-color: ${colors.white};
|
|
22
18
|
z-index: 100;
|
|
23
19
|
width: 100%;
|
|
24
20
|
bottom: 0;
|
|
25
21
|
left: 0;
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
* them on this inner view too drew its shadow onto the dock's white
|
|
29
|
-
* background — the faint seam that made the strip below look like a
|
|
30
|
-
* different colour. */
|
|
22
|
+
border-top-width: 1px;
|
|
23
|
+
border-top-color: #e5e7eb;
|
|
31
24
|
`;
|
|
32
25
|
|
|
33
26
|
export const MediaContainer = styled.View`
|
|
@@ -557,7 +557,9 @@ export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config, is
|
|
|
557
557
|
devPushLog('rn', `watchdog: client ${client.status} → forceReconnect`);
|
|
558
558
|
client.forceReconnect();
|
|
559
559
|
} else {
|
|
560
|
-
|
|
560
|
+
// The periodic health check is the probe's primary owner, so it
|
|
561
|
+
// bypasses the throttle that keeps send-path probes rare.
|
|
562
|
+
client.ensureStreamAlive?.({ force: true, reason: 'watchdog' });
|
|
561
563
|
}
|
|
562
564
|
}, 30000);
|
|
563
565
|
return () => clearInterval(id);
|
|
@@ -622,9 +624,19 @@ export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config, is
|
|
|
622
624
|
// the provider so consumers using the component as a package get
|
|
623
625
|
// correct unread without reaching into the chat store themselves.
|
|
624
626
|
visibleBeforeBackground = visibleRoomJID;
|
|
627
|
+
// Prefer the read boundary the user actually reached. Stamping
|
|
628
|
+
// `Date.now()` while they are scrolled up marks unseen messages as
|
|
629
|
+
// read, and because we flush to the server private store below the
|
|
630
|
+
// loss survives an app restart. Customer-reported #33.
|
|
631
|
+
const bgBoundaryTs = visibleRoomJID
|
|
632
|
+
? rooms?.[visibleRoomJID]?.readBoundaryTs ?? null
|
|
633
|
+
: null;
|
|
625
634
|
if (visibleRoomJID) {
|
|
626
635
|
store.dispatch(
|
|
627
|
-
setLastViewedTimestamp({
|
|
636
|
+
setLastViewedTimestamp({
|
|
637
|
+
chatJID: visibleRoomJID,
|
|
638
|
+
timestamp: bgBoundaryTs ?? Date.now(),
|
|
639
|
+
})
|
|
628
640
|
);
|
|
629
641
|
// Drop the "New messages" divider for the room we're leaving so it
|
|
630
642
|
// doesn't linger when the user comes back (mirrors ChatRoom's
|
|
@@ -636,9 +648,10 @@ export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config, is
|
|
|
636
648
|
}
|
|
637
649
|
// Fire-and-forget — we're going to the background and don't
|
|
638
650
|
// care about the resolution path.
|
|
639
|
-
c.flushLastViewedToPrivateStoreStanza(rooms, {
|
|
640
|
-
|
|
641
|
-
|
|
651
|
+
c.flushLastViewedToPrivateStoreStanza(rooms, {
|
|
652
|
+
visibleRoomJID,
|
|
653
|
+
visibleRoomTs: bgBoundaryTs,
|
|
654
|
+
}).catch(() => {});
|
|
642
655
|
});
|
|
643
656
|
return () => sub.remove();
|
|
644
657
|
}, [client]);
|
|
@@ -669,9 +682,16 @@ export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config, is
|
|
|
669
682
|
store.dispatch(setVisibleRoom({ roomJID: activeRoomJID }));
|
|
670
683
|
}
|
|
671
684
|
} else {
|
|
685
|
+
// Same read-boundary rule as the AppState path above (#33).
|
|
686
|
+
const hideBoundaryTs = activeRoomJID
|
|
687
|
+
? rooms?.[activeRoomJID]?.readBoundaryTs ?? null
|
|
688
|
+
: null;
|
|
672
689
|
if (wasVisible && activeRoomJID) {
|
|
673
690
|
store.dispatch(
|
|
674
|
-
setLastViewedTimestamp({
|
|
691
|
+
setLastViewedTimestamp({
|
|
692
|
+
chatJID: activeRoomJID,
|
|
693
|
+
timestamp: hideBoundaryTs ?? Date.now(),
|
|
694
|
+
})
|
|
675
695
|
);
|
|
676
696
|
// Drop the "New messages" divider so it's gone when the user
|
|
677
697
|
// returns to the chat (mirrors ChatRoom's unmount cleanup).
|
|
@@ -683,7 +703,10 @@ export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config, is
|
|
|
683
703
|
store.dispatch(clearVisibleRoom());
|
|
684
704
|
if (wasVisible && client?.flushLastViewedToPrivateStoreStanza) {
|
|
685
705
|
client
|
|
686
|
-
.flushLastViewedToPrivateStoreStanza(rooms, {
|
|
706
|
+
.flushLastViewedToPrivateStoreStanza(rooms, {
|
|
707
|
+
visibleRoomJID: activeRoomJID,
|
|
708
|
+
visibleRoomTs: hideBoundaryTs,
|
|
709
|
+
})
|
|
687
710
|
.catch(() => {});
|
|
688
711
|
}
|
|
689
712
|
}
|
|
@@ -704,6 +727,15 @@ export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config, is
|
|
|
704
727
|
if (room.messages === lastMessagesRef) {return;}
|
|
705
728
|
lastMessagesRef = room.messages;
|
|
706
729
|
|
|
730
|
+
// "Chat is on screen" does NOT mean "user is looking at the newest
|
|
731
|
+
// message". While they are scrolled up, MessageList publishes a read
|
|
732
|
+
// boundary; advancing the marker to `now` here would clear the very
|
|
733
|
+
// unread messages the scroll-up state exists to preserve — and the
|
|
734
|
+
// 2s flush below would push that loss to the server, making it
|
|
735
|
+
// survive an app restart. Leave the marker alone until they come
|
|
736
|
+
// back to the bottom (boundary back to null). Customer-reported #33.
|
|
737
|
+
if (room.readBoundaryTs != null) {return;}
|
|
738
|
+
|
|
707
739
|
let newest = 0;
|
|
708
740
|
const list = room.messages || [];
|
|
709
741
|
for (const m of list) {
|
|
@@ -762,7 +794,8 @@ export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config, is
|
|
|
762
794
|
devPushLog('rn', `NetInfo: reachable & client ${client.status} → forceReconnect`);
|
|
763
795
|
client.forceReconnect();
|
|
764
796
|
} else if (client.status === 'online') {
|
|
765
|
-
|
|
797
|
+
// Connectivity just came back — worth an immediate check.
|
|
798
|
+
client.ensureStreamAlive?.({ force: true, reason: 'netinfo' });
|
|
766
799
|
}
|
|
767
800
|
});
|
|
768
801
|
return () => unsub();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import XmppClient from '../networking/xmppClient';
|
|
2
2
|
import { store } from '../roomStore';
|
|
3
|
-
import {
|
|
3
|
+
import { applyRoomsPreloadBatch } from '../roomStore/roomsSlice';
|
|
4
4
|
import { IMessage, IRoom } from '../types/types';
|
|
5
5
|
import { checkUniqueUsers } from './checkUniqueUsers';
|
|
6
6
|
|
|
@@ -76,22 +76,47 @@ export const updateMessagesTillLast = async (
|
|
|
76
76
|
Number(message.id) === Number(lastCachedMessagesTimeStamp)
|
|
77
77
|
);
|
|
78
78
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Publish whatever the catch-up actually retrieved.
|
|
82
|
+
//
|
|
83
|
+
// This used to sit INSIDE the loop behind
|
|
84
|
+
// `!isMessageFound && !(counter <= maxFetchAttempts - 1)`,
|
|
85
|
+
// i.e. it only ran when the walk-back gave up. In the common
|
|
86
|
+
// case — the gap is small and the anchor is found on the first
|
|
87
|
+
// fetch — `isMessageFound` flips true immediately and NOTHING
|
|
88
|
+
// was ever dispatched, so the reconnect catch-up silently
|
|
89
|
+
// dropped its own result. The messages still appeared, but only
|
|
90
|
+
// as a side effect of the always-on `onMessageHistory` stanza
|
|
91
|
+
// handler, which parses the same stanza a different way
|
|
92
|
+
// (positional form, no explicit `user` object) and inserts via
|
|
93
|
+
// addRoomMessage. That copy could carry a wrong sender identity
|
|
94
|
+
// and, being treated as an own-message, was excluded from the
|
|
95
|
+
// unread count — the "wrong sender + no unread after reconnect,
|
|
96
|
+
// both correct after restart" symptom, because only a fresh
|
|
97
|
+
// start re-runs the preload scheduler that overwrites it.
|
|
98
|
+
//
|
|
99
|
+
// Dispatching through `applyRoomsPreloadBatch` (rather than the
|
|
100
|
+
// previous `setRoomMessages` array-replace) reuses
|
|
101
|
+
// mergeHistoryIntoCache: it dedupes by id with "fetched wins",
|
|
102
|
+
// preserves locally-pending sends and older cached history, and
|
|
103
|
+
// is already a trigger for the unread middleware — exactly what
|
|
104
|
+
// the startup path does, so reconnect and cold start now agree.
|
|
105
|
+
// Customer-reported #32.
|
|
106
|
+
if (currentJidNewMessages.length > 0) {
|
|
107
|
+
// Fire-and-forget — checkUniqueUsers resolves to an
|
|
108
|
+
// updated RoomMember list, but there's no slice
|
|
109
|
+
// action wired to receive it on RN yet (the web SDK
|
|
110
|
+
// has one; the port left a TODO). Keep the call so
|
|
111
|
+
// the API request goes out (it warms the cache for
|
|
112
|
+
// later renders) but stop short of dispatching.
|
|
113
|
+
await checkUniqueUsers(currentJidNewMessages);
|
|
114
|
+
|
|
115
|
+
store.dispatch(
|
|
116
|
+
applyRoomsPreloadBatch({
|
|
117
|
+
rooms: [{ jid, messages: currentJidNewMessages }],
|
|
118
|
+
})
|
|
119
|
+
);
|
|
95
120
|
}
|
|
96
121
|
} catch (error) {
|
|
97
122
|
console.error(`Error processing room ${jid}:`, error);
|
|
@@ -59,12 +59,20 @@ export const useChatRoomFocus = ({
|
|
|
59
59
|
});
|
|
60
60
|
|
|
61
61
|
const leaveRoom = (jid: string) => {
|
|
62
|
-
const
|
|
62
|
+
const rooms = store.getState().rooms?.rooms;
|
|
63
|
+
// Only mark read as far as the user actually scrolled. Blindly
|
|
64
|
+
// stamping `Date.now()` here clears messages they never reached, and
|
|
65
|
+
// the server flush below makes that permanent across a restart.
|
|
66
|
+
// Customer-reported #33.
|
|
67
|
+
const boundaryTs = rooms?.[jid]?.readBoundaryTs ?? null;
|
|
68
|
+
const timestamp = boundaryTs ?? Date.now();
|
|
63
69
|
dispatch(setLastViewedTimestamp({ chatJID: jid, timestamp }));
|
|
64
70
|
dispatch(clearVisibleRoom());
|
|
65
|
-
const rooms = store.getState().rooms?.rooms;
|
|
66
71
|
(store.getState().chatSettingStore as any)?.client
|
|
67
|
-
?.flushLastViewedToPrivateStoreStanza(rooms, {
|
|
72
|
+
?.flushLastViewedToPrivateStoreStanza(rooms, {
|
|
73
|
+
visibleRoomJID: jid,
|
|
74
|
+
visibleRoomTs: boundaryTs,
|
|
75
|
+
})
|
|
68
76
|
.catch(() => {});
|
|
69
77
|
};
|
|
70
78
|
|
package/src/hooks/useLogout.tsx
CHANGED
|
@@ -63,6 +63,13 @@ const logoutService = {
|
|
|
63
63
|
await Promise.race([
|
|
64
64
|
client.flushLastViewedToPrivateStoreStanza(rooms, {
|
|
65
65
|
visibleRoomJID,
|
|
66
|
+
// `onlyIfNoUnread` deliberately exempts the visible room, so
|
|
67
|
+
// without this the open-but-scrolled-up room would still be
|
|
68
|
+
// stamped "read up to now" on logout and come back read on
|
|
69
|
+
// the next login. Customer-reported #33.
|
|
70
|
+
visibleRoomTs: visibleRoomJID
|
|
71
|
+
? rooms?.[visibleRoomJID]?.readBoundaryTs ?? null
|
|
72
|
+
: null,
|
|
66
73
|
onlyIfNoUnread: true,
|
|
67
74
|
}),
|
|
68
75
|
new Promise((res) => setTimeout(res, 2000)),
|