@ethora/chat-component-rn 26.6.13 → 26.7.2

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 (152) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +22 -0
  3. package/lib/commonjs/assets/icons.js +2 -2
  4. package/lib/commonjs/assets/icons.js.map +1 -1
  5. package/lib/commonjs/components/AuthForms/Login.js +2 -3
  6. package/lib/commonjs/components/AuthForms/Login.js.map +1 -1
  7. package/lib/commonjs/components/MainComponents/ProfileImagePlaceholder.js +9 -8
  8. package/lib/commonjs/components/MainComponents/ProfileImagePlaceholder.js.map +1 -1
  9. package/lib/commonjs/components/Menu/HeaderRoomListMenu.js +110 -37
  10. package/lib/commonjs/components/Menu/HeaderRoomListMenu.js.map +1 -1
  11. package/lib/commonjs/components/Modals/AttachSheet/AttachSheet.js +16 -14
  12. package/lib/commonjs/components/Modals/AttachSheet/AttachSheet.js.map +1 -1
  13. package/lib/commonjs/components/Modals/NewChatModal/ModalContent.js +2 -1
  14. package/lib/commonjs/components/Modals/NewChatModal/ModalContent.js.map +1 -1
  15. package/lib/commonjs/components/Modals/NewChatModal/UpdNewChatModal.js +8 -0
  16. package/lib/commonjs/components/Modals/NewChatModal/UpdNewChatModal.js.map +1 -1
  17. package/lib/commonjs/components/Modals/UserProfileModal/EditUserModal.js +7 -21
  18. package/lib/commonjs/components/Modals/UserProfileModal/EditUserModal.js.map +1 -1
  19. package/lib/commonjs/components/styled/SendInput.js +0 -10
  20. package/lib/commonjs/components/styled/SendInput.js.map +1 -1
  21. package/lib/commonjs/context/xmppProvider.js +2 -3
  22. package/lib/commonjs/context/xmppProvider.js.map +1 -1
  23. package/lib/commonjs/helpers/ensureScopedChatCache.js +2 -2
  24. package/lib/commonjs/helpers/ensureScopedChatCache.js.map +1 -1
  25. package/lib/commonjs/helpers/persistCrypto.js +122 -0
  26. package/lib/commonjs/helpers/persistCrypto.js.map +1 -0
  27. package/lib/commonjs/helpers/pickImageAsset.js +68 -0
  28. package/lib/commonjs/helpers/pickImageAsset.js.map +1 -0
  29. package/lib/commonjs/helpers/resolveInitBeforeLoadUser.js +5 -6
  30. package/lib/commonjs/helpers/resolveInitBeforeLoadUser.js.map +1 -1
  31. package/lib/commonjs/helpers/secureKeyValue.js +83 -0
  32. package/lib/commonjs/helpers/secureKeyValue.js.map +1 -0
  33. package/lib/commonjs/helpers/secureStoreRuntime.js +59 -0
  34. package/lib/commonjs/helpers/secureStoreRuntime.js.map +1 -0
  35. package/lib/commonjs/helpers/secureUserStorage.js +75 -0
  36. package/lib/commonjs/helpers/secureUserStorage.js.map +1 -0
  37. package/lib/commonjs/hooks/useLogout.js +15 -7
  38. package/lib/commonjs/hooks/useLogout.js.map +1 -1
  39. package/lib/commonjs/main.js +6 -0
  40. package/lib/commonjs/main.js.map +1 -1
  41. package/lib/commonjs/networking/authRefresh.js +4 -5
  42. package/lib/commonjs/networking/authRefresh.js.map +1 -1
  43. package/lib/commonjs/roomStore/chatSettingsSlice.js +3 -4
  44. package/lib/commonjs/roomStore/chatSettingsSlice.js.map +1 -1
  45. package/lib/commonjs/roomStore/persistence.js +29 -15
  46. package/lib/commonjs/roomStore/persistence.js.map +1 -1
  47. package/lib/commonjs/roomStore/roomsSlice.js +2 -0
  48. package/lib/commonjs/roomStore/roomsSlice.js.map +1 -1
  49. package/lib/module/assets/icons.js +1 -1
  50. package/lib/module/assets/icons.js.map +1 -1
  51. package/lib/module/components/AuthForms/Login.js +2 -3
  52. package/lib/module/components/AuthForms/Login.js.map +1 -1
  53. package/lib/module/components/MainComponents/ProfileImagePlaceholder.js +9 -8
  54. package/lib/module/components/MainComponents/ProfileImagePlaceholder.js.map +1 -1
  55. package/lib/module/components/Menu/HeaderRoomListMenu.js +110 -38
  56. package/lib/module/components/Menu/HeaderRoomListMenu.js.map +1 -1
  57. package/lib/module/components/Modals/AttachSheet/AttachSheet.js +16 -14
  58. package/lib/module/components/Modals/AttachSheet/AttachSheet.js.map +1 -1
  59. package/lib/module/components/Modals/NewChatModal/ModalContent.js +2 -1
  60. package/lib/module/components/Modals/NewChatModal/ModalContent.js.map +1 -1
  61. package/lib/module/components/Modals/NewChatModal/UpdNewChatModal.js +8 -0
  62. package/lib/module/components/Modals/NewChatModal/UpdNewChatModal.js.map +1 -1
  63. package/lib/module/components/Modals/UserProfileModal/EditUserModal.js +9 -23
  64. package/lib/module/components/Modals/UserProfileModal/EditUserModal.js.map +1 -1
  65. package/lib/module/components/styled/SendInput.js +1 -11
  66. package/lib/module/components/styled/SendInput.js.map +1 -1
  67. package/lib/module/context/xmppProvider.js +2 -3
  68. package/lib/module/context/xmppProvider.js.map +1 -1
  69. package/lib/module/helpers/ensureScopedChatCache.js +2 -2
  70. package/lib/module/helpers/ensureScopedChatCache.js.map +1 -1
  71. package/lib/module/helpers/persistCrypto.js +115 -0
  72. package/lib/module/helpers/persistCrypto.js.map +1 -0
  73. package/lib/module/helpers/pickImageAsset.js +63 -0
  74. package/lib/module/helpers/pickImageAsset.js.map +1 -0
  75. package/lib/module/helpers/resolveInitBeforeLoadUser.js +5 -6
  76. package/lib/module/helpers/resolveInitBeforeLoadUser.js.map +1 -1
  77. package/lib/module/helpers/secureKeyValue.js +75 -0
  78. package/lib/module/helpers/secureKeyValue.js.map +1 -0
  79. package/lib/module/helpers/secureStoreRuntime.js +52 -0
  80. package/lib/module/helpers/secureStoreRuntime.js.map +1 -0
  81. package/lib/module/helpers/secureUserStorage.js +72 -0
  82. package/lib/module/helpers/secureUserStorage.js.map +1 -0
  83. package/lib/module/hooks/useLogout.js +15 -7
  84. package/lib/module/hooks/useLogout.js.map +1 -1
  85. package/lib/module/main.js +1 -1
  86. package/lib/module/main.js.map +1 -1
  87. package/lib/module/networking/authRefresh.js +4 -5
  88. package/lib/module/networking/authRefresh.js.map +1 -1
  89. package/lib/module/roomStore/chatSettingsSlice.js +3 -4
  90. package/lib/module/roomStore/chatSettingsSlice.js.map +1 -1
  91. package/lib/module/roomStore/persistence.js +30 -15
  92. package/lib/module/roomStore/persistence.js.map +1 -1
  93. package/lib/module/roomStore/roomsSlice.js +2 -0
  94. package/lib/module/roomStore/roomsSlice.js.map +1 -1
  95. package/lib/typescript/assets/icons.d.ts +4 -0
  96. package/lib/typescript/assets/icons.d.ts.map +1 -1
  97. package/lib/typescript/components/AuthForms/Login.d.ts.map +1 -1
  98. package/lib/typescript/components/MainComponents/ProfileImagePlaceholder.d.ts.map +1 -1
  99. package/lib/typescript/components/Menu/HeaderRoomListMenu.d.ts +3 -0
  100. package/lib/typescript/components/Menu/HeaderRoomListMenu.d.ts.map +1 -1
  101. package/lib/typescript/components/Modals/AttachSheet/AttachSheet.d.ts.map +1 -1
  102. package/lib/typescript/components/Modals/NewChatModal/ModalContent.d.ts +4 -2
  103. package/lib/typescript/components/Modals/NewChatModal/ModalContent.d.ts.map +1 -1
  104. package/lib/typescript/components/Modals/NewChatModal/UpdNewChatModal.d.ts.map +1 -1
  105. package/lib/typescript/components/Modals/UserProfileModal/EditUserModal.d.ts.map +1 -1
  106. package/lib/typescript/components/styled/SendInput.d.ts.map +1 -1
  107. package/lib/typescript/context/xmppProvider.d.ts.map +1 -1
  108. package/lib/typescript/helpers/persistCrypto.d.ts +13 -0
  109. package/lib/typescript/helpers/persistCrypto.d.ts.map +1 -0
  110. package/lib/typescript/helpers/pickImageAsset.d.ts +27 -0
  111. package/lib/typescript/helpers/pickImageAsset.d.ts.map +1 -0
  112. package/lib/typescript/helpers/resolveInitBeforeLoadUser.d.ts.map +1 -1
  113. package/lib/typescript/helpers/secureKeyValue.d.ts +13 -0
  114. package/lib/typescript/helpers/secureKeyValue.d.ts.map +1 -0
  115. package/lib/typescript/helpers/secureStoreRuntime.d.ts +29 -0
  116. package/lib/typescript/helpers/secureStoreRuntime.d.ts.map +1 -0
  117. package/lib/typescript/helpers/secureUserStorage.d.ts +23 -0
  118. package/lib/typescript/helpers/secureUserStorage.d.ts.map +1 -0
  119. package/lib/typescript/hooks/useLogout.d.ts.map +1 -1
  120. package/lib/typescript/main.d.ts +1 -1
  121. package/lib/typescript/main.d.ts.map +1 -1
  122. package/lib/typescript/networking/authRefresh.d.ts.map +1 -1
  123. package/lib/typescript/roomStore/chatSettingsSlice.d.ts.map +1 -1
  124. package/lib/typescript/roomStore/persistence.d.ts.map +1 -1
  125. package/lib/typescript/roomStore/roomsSlice.d.ts.map +1 -1
  126. package/lib/typescript/types/types.d.ts +12 -0
  127. package/lib/typescript/types/types.d.ts.map +1 -1
  128. package/package.json +8 -1
  129. package/src/assets/icons.tsx +19 -0
  130. package/src/components/AuthForms/Login.tsx +2 -3
  131. package/src/components/MainComponents/ProfileImagePlaceholder.tsx +16 -9
  132. package/src/components/Menu/HeaderRoomListMenu.tsx +105 -11
  133. package/src/components/Modals/AttachSheet/AttachSheet.tsx +16 -14
  134. package/src/components/Modals/NewChatModal/ModalContent.tsx +6 -3
  135. package/src/components/Modals/NewChatModal/UpdNewChatModal.tsx +12 -1
  136. package/src/components/Modals/UserProfileModal/EditUserModal.tsx +9 -25
  137. package/src/components/styled/SendInput.tsx +0 -10
  138. package/src/context/xmppProvider.tsx +2 -3
  139. package/src/helpers/ensureScopedChatCache.ts +2 -2
  140. package/src/helpers/persistCrypto.ts +127 -0
  141. package/src/helpers/pickImageAsset.ts +68 -0
  142. package/src/helpers/resolveInitBeforeLoadUser.ts +5 -10
  143. package/src/helpers/secureKeyValue.ts +80 -0
  144. package/src/helpers/secureStoreRuntime.ts +62 -0
  145. package/src/helpers/secureUserStorage.ts +80 -0
  146. package/src/hooks/useLogout.tsx +15 -9
  147. package/src/main.ts +1 -1
  148. package/src/networking/authRefresh.ts +4 -9
  149. package/src/roomStore/chatSettingsSlice.ts +3 -6
  150. package/src/roomStore/persistence.ts +39 -19
  151. package/src/roomStore/roomsSlice.ts +2 -0
  152. package/src/types/types.ts +14 -0
@@ -1,6 +1,7 @@
1
1
  import AsyncStorage from '@react-native-async-storage/async-storage';
2
2
  import { Middleware } from '@reduxjs/toolkit';
3
3
  import { IMessage, IRoom, User } from '../types/types';
4
+ import { encryptForPersist, decryptFromPersist } from '../helpers/persistCrypto';
4
5
 
5
6
  // -------------------------------------------------------------------
6
7
  // Lightweight RN persistence layer. Mirrors what redux-persist gives
@@ -11,7 +12,11 @@ import { IMessage, IRoom, User } from '../types/types';
11
12
  // - cap each room's messages to the most recent MESSAGE_LIMIT (100)
12
13
  // - debounced writes (200ms) on relevant action types
13
14
  //
14
- // Not encrypted. We rely on AsyncStorage's per-app sandbox.
15
+ // AES-256-CBC at rest (see `helpers/persistCrypto.ts`): the JSON blob
16
+ // under each key below is encrypted before it reaches AsyncStorage, with
17
+ // the symmetric key held in the platform Keychain/Keystore. `user` here
18
+ // is already secret-free (see `sanitizeUser`) — the encryption is for
19
+ // the message bodies in `rooms`, which aren't.
15
20
  // -------------------------------------------------------------------
16
21
 
17
22
  const KEY_CHAT = '@ethora/persist:chatSettingStore';
@@ -199,21 +204,27 @@ export const persistenceMiddleware: Middleware = (storeAPI) => (next) => (
199
204
 
200
205
  if (writeTimer) {clearTimeout(writeTimer);}
201
206
  writeTimer = setTimeout(() => {
202
- try {
203
- const state = storeAPI.getState();
204
- const chatPayload: PersistedChatState = {
205
- user: sanitizeUser(state.chatSettingStore?.user) as User,
206
- };
207
- const roomsPayload: PersistedRoomsState = {
208
- rooms: sanitizeRooms(state.rooms?.rooms || {}),
209
- };
210
- AsyncStorage.multiSet([
211
- [KEY_CHAT, JSON.stringify(chatPayload)],
212
- [KEY_ROOMS, JSON.stringify(roomsPayload)],
213
- ]).catch((e) => console.warn('persist write failed', e));
214
- } catch (e) {
215
- console.warn('persist serialize failed', e);
216
- }
207
+ (async () => {
208
+ try {
209
+ const state = storeAPI.getState();
210
+ const chatPayload: PersistedChatState = {
211
+ user: sanitizeUser(state.chatSettingStore?.user) as User,
212
+ };
213
+ const roomsPayload: PersistedRoomsState = {
214
+ rooms: sanitizeRooms(state.rooms?.rooms || {}),
215
+ };
216
+ const [chatCipher, roomsCipher] = await Promise.all([
217
+ encryptForPersist(JSON.stringify(chatPayload)),
218
+ encryptForPersist(JSON.stringify(roomsPayload)),
219
+ ]);
220
+ await AsyncStorage.multiSet([
221
+ [KEY_CHAT, chatCipher],
222
+ [KEY_ROOMS, roomsCipher],
223
+ ]);
224
+ } catch (e) {
225
+ console.warn('persist write failed', e);
226
+ }
227
+ })();
217
228
  }, 200);
218
229
 
219
230
  return result;
@@ -233,9 +244,18 @@ export async function readPersistedState(): Promise<{
233
244
  KEY_CHAT,
234
245
  KEY_ROOMS,
235
246
  ]);
236
- const chat = chatRaw[1] ? (JSON.parse(chatRaw[1]) as PersistedChatState) : null;
237
- const rooms = roomsRaw[1]
238
- ? (JSON.parse(roomsRaw[1]) as PersistedRoomsState)
247
+ const [chatPlain, roomsPlain] = await Promise.all([
248
+ chatRaw[1] ? decryptFromPersist(chatRaw[1]) : Promise.resolve(null),
249
+ roomsRaw[1] ? decryptFromPersist(roomsRaw[1]) : Promise.resolve(null),
250
+ ]);
251
+ // `decryptFromPersist` returns null both for "nothing stored" and
252
+ // for "stored value isn't a valid envelope for the current key" —
253
+ // notably a plaintext blob left over from a pre-encryption install.
254
+ // Either way there is nothing safe to parse, so the caller treats it
255
+ // as a cold start and re-hydrates from the server.
256
+ const chat = chatPlain ? (JSON.parse(chatPlain) as PersistedChatState) : null;
257
+ const rooms = roomsPlain
258
+ ? (JSON.parse(roomsPlain) as PersistedRoomsState)
239
259
  : null;
240
260
  return { chat, rooms };
241
261
  } catch (e) {
@@ -317,6 +317,8 @@ const reducers = {
317
317
  : [];
318
318
  state.rooms[roomData.jid] = {
319
319
  ...roomData,
320
+ icon: roomData.icon !== undefined ? roomData.icon : existing?.icon,
321
+ roomBg: roomData.roomBg !== undefined ? roomData.roomBg : existing?.roomBg,
320
322
  messages:
321
323
  existingMessages.length > 0 ? existingMessages : incomingMessages,
322
324
  lastViewedTimestamp: lastViewed,
@@ -454,6 +454,20 @@ export interface IConfig {
454
454
  loginFunction: () => Promise<User | null>;
455
455
  };
456
456
  defaultLogin?: boolean;
457
+ logout?: {
458
+ enabled: boolean;
459
+ label?: string;
460
+ confirm?:
461
+ | boolean
462
+ | {
463
+ title?: string;
464
+ message?: string;
465
+ confirmText?: string;
466
+ cancelText?: string;
467
+ };
468
+ onBeforeLogout?: () => Promise<boolean | void> | boolean | void;
469
+ onAfterLogout?: () => Promise<void> | void;
470
+ };
457
471
  refreshTokens?: {
458
472
  enabled: boolean;
459
473
  /**