@ethora/chat-component-rn 26.8.7 → 26.8.9

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 (243) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +27 -4
  3. package/lib/commonjs/components/Header/HeaderRoomList.js +34 -6
  4. package/lib/commonjs/components/Header/HeaderRoomList.js.map +1 -1
  5. package/lib/commonjs/components/MainComponents/ChatHeader.js +15 -1
  6. package/lib/commonjs/components/MainComponents/ChatHeader.js.map +1 -1
  7. package/lib/commonjs/components/MainComponents/ChatWrapper.js +5 -3
  8. package/lib/commonjs/components/MainComponents/ChatWrapper.js.map +1 -1
  9. package/lib/commonjs/components/MainComponents/ReduxWrapper.js +8 -0
  10. package/lib/commonjs/components/MainComponents/ReduxWrapper.js.map +1 -1
  11. package/lib/commonjs/components/MainComponents/RoomList.js +63 -11
  12. package/lib/commonjs/components/MainComponents/RoomList.js.map +1 -1
  13. package/lib/commonjs/components/Menu/HeaderRoomListMenu.js +26 -13
  14. package/lib/commonjs/components/Menu/HeaderRoomListMenu.js.map +1 -1
  15. package/lib/commonjs/components/MenuRoom/MenuRoom.js +5 -3
  16. package/lib/commonjs/components/MenuRoom/MenuRoom.js.map +1 -1
  17. package/lib/commonjs/components/MessageBubble/Message.js +3 -3
  18. package/lib/commonjs/components/MessageBubble/Message.js.map +1 -1
  19. package/lib/commonjs/components/MessageBubble/MessageInteractions.js +5 -3
  20. package/lib/commonjs/components/MessageBubble/MessageInteractions.js.map +1 -1
  21. package/lib/commonjs/components/Modals/ChatProfileModal/ChatProfileModal.js +1 -1
  22. package/lib/commonjs/components/Modals/ChatProfileModal/ChatProfileModal.js.map +1 -1
  23. package/lib/commonjs/components/Modals/ChatProfileModal/ReportChatModal.js +5 -4
  24. package/lib/commonjs/components/Modals/ChatProfileModal/ReportChatModal.js.map +1 -1
  25. package/lib/commonjs/components/Modals/FilePreviewModal/FilePreviewModal.js +7 -5
  26. package/lib/commonjs/components/Modals/FilePreviewModal/FilePreviewModal.js.map +1 -1
  27. package/lib/commonjs/components/Modals/Modal/Modal.js +33 -11
  28. package/lib/commonjs/components/Modals/Modal/Modal.js.map +1 -1
  29. package/lib/commonjs/components/Modals/NewChatModal/NewChatModal.js +8 -8
  30. package/lib/commonjs/components/Modals/NewChatModal/NewChatModal.js.map +1 -1
  31. package/lib/commonjs/components/Modals/SettingsModals/ChangePassword/ChangePasswordModal.js +279 -0
  32. package/lib/commonjs/components/Modals/SettingsModals/ChangePassword/ChangePasswordModal.js.map +1 -0
  33. package/lib/commonjs/components/Modals/SettingsModals/ManageDataModal/ManageDataModal.js +10 -8
  34. package/lib/commonjs/components/Modals/SettingsModals/ManageDataModal/ManageDataModal.js.map +1 -1
  35. package/lib/commonjs/components/Modals/SettingsModals/Visibility/VisibilityModal.js +13 -11
  36. package/lib/commonjs/components/Modals/SettingsModals/Visibility/VisibilityModal.js.map +1 -1
  37. package/lib/commonjs/components/Modals/UserProfileModal/UserProfileModal.js +22 -38
  38. package/lib/commonjs/components/Modals/UserProfileModal/UserProfileModal.js.map +1 -1
  39. package/lib/commonjs/components/Modals/UserSettingsModal/LanguageCard.js +121 -0
  40. package/lib/commonjs/components/Modals/UserSettingsModal/LanguageCard.js.map +1 -0
  41. package/lib/commonjs/components/Modals/UserSettingsModal/UserSettingsModal.js +11 -6
  42. package/lib/commonjs/components/Modals/UserSettingsModal/UserSettingsModal.js.map +1 -1
  43. package/lib/commonjs/components/RoomComponents/SwipeableRoomRow.js +133 -0
  44. package/lib/commonjs/components/RoomComponents/SwipeableRoomRow.js.map +1 -0
  45. package/lib/commonjs/components/Thread/ThreadWrapper.js +4 -2
  46. package/lib/commonjs/components/Thread/ThreadWrapper.js.map +1 -1
  47. package/lib/commonjs/context/xmppProvider.js +15 -3
  48. package/lib/commonjs/context/xmppProvider.js.map +1 -1
  49. package/lib/commonjs/e2ee/stanza.js +1 -1
  50. package/lib/commonjs/e2ee/stanza.js.map +1 -1
  51. package/lib/commonjs/helpers/constants/MODAL_COMPONENTS.js +2 -0
  52. package/lib/commonjs/helpers/constants/MODAL_COMPONENTS.js.map +1 -1
  53. package/lib/commonjs/helpers/constants/MODAL_TYPES.js +1 -0
  54. package/lib/commonjs/helpers/constants/MODAL_TYPES.js.map +1 -1
  55. package/lib/commonjs/helpers/preferencesStorage.js.map +1 -1
  56. package/lib/commonjs/hooks/useChatSettingState.js +4 -0
  57. package/lib/commonjs/hooks/useChatSettingState.js.map +1 -1
  58. package/lib/commonjs/hooks/useChatWrapperInit.js +4 -0
  59. package/lib/commonjs/hooks/useChatWrapperInit.js.map +1 -1
  60. package/lib/commonjs/hooks/useConnectionLabel.js +29 -0
  61. package/lib/commonjs/hooks/useConnectionLabel.js.map +1 -0
  62. package/lib/commonjs/i18n/strings.js +199 -1
  63. package/lib/commonjs/i18n/strings.js.map +1 -1
  64. package/lib/commonjs/i18n/useT.js +8 -4
  65. package/lib/commonjs/i18n/useT.js.map +1 -1
  66. package/lib/commonjs/networking/api-requests/user.api.js +13 -0
  67. package/lib/commonjs/networking/api-requests/user.api.js.map +1 -1
  68. package/lib/commonjs/networking/stanzaHandlers.js +1 -1
  69. package/lib/commonjs/networking/stanzaHandlers.js.map +1 -1
  70. package/lib/commonjs/networking/xmppClient.js +29 -1
  71. package/lib/commonjs/networking/xmppClient.js.map +1 -1
  72. package/lib/commonjs/roomStore/chatSettingsSlice.js +12 -2
  73. package/lib/commonjs/roomStore/chatSettingsSlice.js.map +1 -1
  74. package/lib/commonjs/services/languageSettings.js +177 -0
  75. package/lib/commonjs/services/languageSettings.js.map +1 -0
  76. package/lib/commonjs/version.js +1 -1
  77. package/lib/module/components/Header/HeaderRoomList.js +34 -6
  78. package/lib/module/components/Header/HeaderRoomList.js.map +1 -1
  79. package/lib/module/components/MainComponents/ChatHeader.js +15 -1
  80. package/lib/module/components/MainComponents/ChatHeader.js.map +1 -1
  81. package/lib/module/components/MainComponents/ChatWrapper.js +5 -3
  82. package/lib/module/components/MainComponents/ChatWrapper.js.map +1 -1
  83. package/lib/module/components/MainComponents/ReduxWrapper.js +9 -1
  84. package/lib/module/components/MainComponents/ReduxWrapper.js.map +1 -1
  85. package/lib/module/components/MainComponents/RoomList.js +64 -12
  86. package/lib/module/components/MainComponents/RoomList.js.map +1 -1
  87. package/lib/module/components/Menu/HeaderRoomListMenu.js +26 -13
  88. package/lib/module/components/Menu/HeaderRoomListMenu.js.map +1 -1
  89. package/lib/module/components/MenuRoom/MenuRoom.js +5 -3
  90. package/lib/module/components/MenuRoom/MenuRoom.js.map +1 -1
  91. package/lib/module/components/MessageBubble/Message.js +3 -3
  92. package/lib/module/components/MessageBubble/Message.js.map +1 -1
  93. package/lib/module/components/MessageBubble/MessageInteractions.js +5 -3
  94. package/lib/module/components/MessageBubble/MessageInteractions.js.map +1 -1
  95. package/lib/module/components/Modals/ChatProfileModal/ChatProfileModal.js +1 -1
  96. package/lib/module/components/Modals/ChatProfileModal/ChatProfileModal.js.map +1 -1
  97. package/lib/module/components/Modals/ChatProfileModal/ReportChatModal.js +5 -4
  98. package/lib/module/components/Modals/ChatProfileModal/ReportChatModal.js.map +1 -1
  99. package/lib/module/components/Modals/FilePreviewModal/FilePreviewModal.js +7 -5
  100. package/lib/module/components/Modals/FilePreviewModal/FilePreviewModal.js.map +1 -1
  101. package/lib/module/components/Modals/Modal/Modal.js +33 -11
  102. package/lib/module/components/Modals/Modal/Modal.js.map +1 -1
  103. package/lib/module/components/Modals/NewChatModal/NewChatModal.js +8 -8
  104. package/lib/module/components/Modals/NewChatModal/NewChatModal.js.map +1 -1
  105. package/lib/module/components/Modals/SettingsModals/ChangePassword/ChangePasswordModal.js +274 -0
  106. package/lib/module/components/Modals/SettingsModals/ChangePassword/ChangePasswordModal.js.map +1 -0
  107. package/lib/module/components/Modals/SettingsModals/ManageDataModal/ManageDataModal.js +10 -8
  108. package/lib/module/components/Modals/SettingsModals/ManageDataModal/ManageDataModal.js.map +1 -1
  109. package/lib/module/components/Modals/SettingsModals/Visibility/VisibilityModal.js +13 -11
  110. package/lib/module/components/Modals/SettingsModals/Visibility/VisibilityModal.js.map +1 -1
  111. package/lib/module/components/Modals/UserProfileModal/UserProfileModal.js +24 -40
  112. package/lib/module/components/Modals/UserProfileModal/UserProfileModal.js.map +1 -1
  113. package/lib/module/components/Modals/UserSettingsModal/LanguageCard.js +116 -0
  114. package/lib/module/components/Modals/UserSettingsModal/LanguageCard.js.map +1 -0
  115. package/lib/module/components/Modals/UserSettingsModal/UserSettingsModal.js +10 -5
  116. package/lib/module/components/Modals/UserSettingsModal/UserSettingsModal.js.map +1 -1
  117. package/lib/module/components/RoomComponents/SwipeableRoomRow.js +126 -0
  118. package/lib/module/components/RoomComponents/SwipeableRoomRow.js.map +1 -0
  119. package/lib/module/components/Thread/ThreadWrapper.js +4 -2
  120. package/lib/module/components/Thread/ThreadWrapper.js.map +1 -1
  121. package/lib/module/context/xmppProvider.js +16 -4
  122. package/lib/module/context/xmppProvider.js.map +1 -1
  123. package/lib/module/e2ee/stanza.js +1 -1
  124. package/lib/module/e2ee/stanza.js.map +1 -1
  125. package/lib/module/helpers/constants/MODAL_COMPONENTS.js +2 -0
  126. package/lib/module/helpers/constants/MODAL_COMPONENTS.js.map +1 -1
  127. package/lib/module/helpers/constants/MODAL_TYPES.js +1 -0
  128. package/lib/module/helpers/constants/MODAL_TYPES.js.map +1 -1
  129. package/lib/module/helpers/preferencesStorage.js.map +1 -1
  130. package/lib/module/hooks/useChatSettingState.js +4 -0
  131. package/lib/module/hooks/useChatSettingState.js.map +1 -1
  132. package/lib/module/hooks/useChatWrapperInit.js +4 -0
  133. package/lib/module/hooks/useChatWrapperInit.js.map +1 -1
  134. package/lib/module/hooks/useConnectionLabel.js +25 -0
  135. package/lib/module/hooks/useConnectionLabel.js.map +1 -0
  136. package/lib/module/i18n/strings.js +199 -1
  137. package/lib/module/i18n/strings.js.map +1 -1
  138. package/lib/module/i18n/useT.js +8 -4
  139. package/lib/module/i18n/useT.js.map +1 -1
  140. package/lib/module/networking/api-requests/user.api.js +12 -0
  141. package/lib/module/networking/api-requests/user.api.js.map +1 -1
  142. package/lib/module/networking/stanzaHandlers.js +1 -1
  143. package/lib/module/networking/stanzaHandlers.js.map +1 -1
  144. package/lib/module/networking/xmppClient.js +29 -1
  145. package/lib/module/networking/xmppClient.js.map +1 -1
  146. package/lib/module/roomStore/chatSettingsSlice.js +9 -1
  147. package/lib/module/roomStore/chatSettingsSlice.js.map +1 -1
  148. package/lib/module/services/languageSettings.js +164 -0
  149. package/lib/module/services/languageSettings.js.map +1 -0
  150. package/lib/module/version.js +1 -1
  151. package/lib/typescript/components/Header/HeaderRoomList.d.ts +1 -0
  152. package/lib/typescript/components/Header/HeaderRoomList.d.ts.map +1 -1
  153. package/lib/typescript/components/MainComponents/ChatHeader.d.ts.map +1 -1
  154. package/lib/typescript/components/MainComponents/ChatWrapper.d.ts.map +1 -1
  155. package/lib/typescript/components/MainComponents/ReduxWrapper.d.ts.map +1 -1
  156. package/lib/typescript/components/MainComponents/RoomList.d.ts.map +1 -1
  157. package/lib/typescript/components/Menu/HeaderRoomListMenu.d.ts +7 -1
  158. package/lib/typescript/components/Menu/HeaderRoomListMenu.d.ts.map +1 -1
  159. package/lib/typescript/components/MenuRoom/MenuRoom.d.ts.map +1 -1
  160. package/lib/typescript/components/MessageBubble/MessageInteractions.d.ts.map +1 -1
  161. package/lib/typescript/components/Modals/ChatProfileModal/ReportChatModal.d.ts +2 -0
  162. package/lib/typescript/components/Modals/ChatProfileModal/ReportChatModal.d.ts.map +1 -1
  163. package/lib/typescript/components/Modals/FilePreviewModal/FilePreviewModal.d.ts.map +1 -1
  164. package/lib/typescript/components/Modals/Modal/Modal.d.ts.map +1 -1
  165. package/lib/typescript/components/Modals/SettingsModals/ChangePassword/ChangePasswordModal.d.ts +15 -0
  166. package/lib/typescript/components/Modals/SettingsModals/ChangePassword/ChangePasswordModal.d.ts.map +1 -0
  167. package/lib/typescript/components/Modals/SettingsModals/ManageDataModal/ManageDataModal.d.ts.map +1 -1
  168. package/lib/typescript/components/Modals/SettingsModals/Visibility/VisibilityModal.d.ts.map +1 -1
  169. package/lib/typescript/components/Modals/UserProfileModal/UserProfileModal.d.ts.map +1 -1
  170. package/lib/typescript/components/Modals/UserSettingsModal/LanguageCard.d.ts +14 -0
  171. package/lib/typescript/components/Modals/UserSettingsModal/LanguageCard.d.ts.map +1 -0
  172. package/lib/typescript/components/Modals/UserSettingsModal/UserSettingsModal.d.ts.map +1 -1
  173. package/lib/typescript/components/RoomComponents/SwipeableRoomRow.d.ts +19 -0
  174. package/lib/typescript/components/RoomComponents/SwipeableRoomRow.d.ts.map +1 -0
  175. package/lib/typescript/components/Thread/ThreadWrapper.d.ts.map +1 -1
  176. package/lib/typescript/context/xmppProvider.d.ts.map +1 -1
  177. package/lib/typescript/helpers/constants/MODAL_COMPONENTS.d.ts.map +1 -1
  178. package/lib/typescript/helpers/constants/MODAL_TYPES.d.ts +1 -0
  179. package/lib/typescript/helpers/constants/MODAL_TYPES.d.ts.map +1 -1
  180. package/lib/typescript/helpers/preferencesStorage.d.ts +4 -0
  181. package/lib/typescript/helpers/preferencesStorage.d.ts.map +1 -1
  182. package/lib/typescript/hooks/useChatSettingState.d.ts +2 -0
  183. package/lib/typescript/hooks/useChatSettingState.d.ts.map +1 -1
  184. package/lib/typescript/hooks/useChatWrapperInit.d.ts.map +1 -1
  185. package/lib/typescript/hooks/useConnectionLabel.d.ts +8 -0
  186. package/lib/typescript/hooks/useConnectionLabel.d.ts.map +1 -0
  187. package/lib/typescript/i18n/strings.d.ts.map +1 -1
  188. package/lib/typescript/i18n/useT.d.ts.map +1 -1
  189. package/lib/typescript/networking/api-requests/user.api.d.ts +6 -0
  190. package/lib/typescript/networking/api-requests/user.api.d.ts.map +1 -1
  191. package/lib/typescript/networking/stanzaHandlers.d.ts.map +1 -1
  192. package/lib/typescript/networking/xmppClient.d.ts +11 -1
  193. package/lib/typescript/networking/xmppClient.d.ts.map +1 -1
  194. package/lib/typescript/roomStore/chatSettingsSlice.d.ts +18 -1
  195. package/lib/typescript/roomStore/chatSettingsSlice.d.ts.map +1 -1
  196. package/lib/typescript/services/languageSettings.d.ts +29 -0
  197. package/lib/typescript/services/languageSettings.d.ts.map +1 -0
  198. package/lib/typescript/types/models/user.model.d.ts +4 -0
  199. package/lib/typescript/types/models/user.model.d.ts.map +1 -1
  200. package/lib/typescript/types/types.d.ts +23 -0
  201. package/lib/typescript/types/types.d.ts.map +1 -1
  202. package/lib/typescript/version.d.ts +1 -1
  203. package/package.json +1 -1
  204. package/src/components/Header/HeaderRoomList.tsx +31 -6
  205. package/src/components/MainComponents/ChatHeader.tsx +16 -1
  206. package/src/components/MainComponents/ChatWrapper.tsx +5 -3
  207. package/src/components/MainComponents/ReduxWrapper.tsx +6 -0
  208. package/src/components/MainComponents/RoomList.tsx +78 -12
  209. package/src/components/Menu/HeaderRoomListMenu.tsx +40 -13
  210. package/src/components/MenuRoom/MenuRoom.tsx +5 -3
  211. package/src/components/MessageBubble/Message.tsx +3 -3
  212. package/src/components/MessageBubble/MessageInteractions.tsx +5 -3
  213. package/src/components/Modals/ChatProfileModal/ChatProfileModal.tsx +1 -1
  214. package/src/components/Modals/ChatProfileModal/ReportChatModal.tsx +6 -3
  215. package/src/components/Modals/FilePreviewModal/FilePreviewModal.tsx +7 -5
  216. package/src/components/Modals/Modal/Modal.tsx +44 -16
  217. package/src/components/Modals/NewChatModal/NewChatModal.tsx +8 -8
  218. package/src/components/Modals/SettingsModals/ChangePassword/ChangePasswordModal.tsx +316 -0
  219. package/src/components/Modals/SettingsModals/ManageDataModal/ManageDataModal.tsx +10 -15
  220. package/src/components/Modals/SettingsModals/Visibility/VisibilityModal.tsx +13 -14
  221. package/src/components/Modals/UserProfileModal/UserProfileModal.tsx +19 -40
  222. package/src/components/Modals/UserSettingsModal/LanguageCard.tsx +144 -0
  223. package/src/components/Modals/UserSettingsModal/UserSettingsModal.tsx +11 -4
  224. package/src/components/RoomComponents/SwipeableRoomRow.tsx +133 -0
  225. package/src/components/Thread/ThreadWrapper.tsx +4 -2
  226. package/src/context/xmppProvider.tsx +21 -4
  227. package/src/e2ee/stanza.ts +1 -1
  228. package/src/helpers/constants/MODAL_COMPONENTS.tsx +2 -0
  229. package/src/helpers/constants/MODAL_TYPES.ts +1 -0
  230. package/src/helpers/preferencesStorage.ts +4 -0
  231. package/src/hooks/useChatSettingState.tsx +8 -0
  232. package/src/hooks/useChatWrapperInit.ts +4 -0
  233. package/src/hooks/useConnectionLabel.ts +16 -0
  234. package/src/i18n/strings.ts +199 -1
  235. package/src/i18n/useT.ts +6 -4
  236. package/src/networking/api-requests/user.api.ts +9 -0
  237. package/src/networking/stanzaHandlers.ts +1 -0
  238. package/src/networking/xmppClient.ts +33 -1
  239. package/src/roomStore/chatSettingsSlice.ts +30 -0
  240. package/src/services/languageSettings.ts +143 -0
  241. package/src/types/models/user.model.ts +4 -0
  242. package/src/types/types.ts +23 -0
  243. package/src/version.ts +1 -1
@@ -0,0 +1,143 @@
1
+ // The user's two languages, as the backend keeps them on the profile:
2
+ //
3
+ // appLanguage - the interface: the chat's captions (`uiLocale`).
4
+ // chatLanguage - what incoming messages are translated into, and the
5
+ // language declared on the user's own messages (`langSource`).
6
+ //
7
+ // Both are per account, not per device: a choice made here is written to the
8
+ // profile with `PUT /v1/users` - one field per request, as the web app does,
9
+ // so writing one never rewrites the other - and the profile's values are
10
+ // applied when a session starts. The last choice is also kept on the device,
11
+ // so the interface comes up in the right language before the profile loads.
12
+ //
13
+ // Translation itself happens on the server, per the reader's chatLanguage:
14
+ // that is why the choice has to reach the profile for a translation to ever
15
+ // arrive on a message.
16
+
17
+ import { store } from '../roomStore';
18
+ import { setLangSource, setUiLocale, updateUser } from '../roomStore/chatSettingsSlice';
19
+ import { savePreferences } from '../helpers/preferencesStorage';
20
+ import { updateMe } from '../networking/api-requests/user.api';
21
+ import { LANGUAGE_OPTIONS } from '../helpers/constants/LANGUAGE_OPTIONS';
22
+ import type { IConfig } from '../types/types';
23
+
24
+ export interface LanguageChoice {
25
+ /** BCP-47 tag, e.g. "fr-CA". */
26
+ id: string;
27
+ /** The language's own name for itself. */
28
+ name: string;
29
+ }
30
+
31
+ const AUTONYMS: Record<string, string> = {
32
+ en: 'English',
33
+ es: 'Español',
34
+ fr: 'Français',
35
+ pt: 'Português',
36
+ ht: 'Kreyòl ayisyen',
37
+ zh: '中文',
38
+ de: 'Deutsch',
39
+ it: 'Italiano',
40
+ uk: 'Українська',
41
+ ru: 'Русский',
42
+ pl: 'Polski',
43
+ tr: 'Türkçe',
44
+ ar: 'العربية',
45
+ hi: 'हिन्दी',
46
+ ja: '日本語',
47
+ ko: '한국어',
48
+ nl: 'Nederlands',
49
+ sv: 'Svenska',
50
+ };
51
+
52
+ /** "en-ca" -> "en-CA"; anything that is not a language tag -> undefined. */
53
+ export const canonicalLocale = (value: unknown): string | undefined => {
54
+ const raw = String(value ?? '').trim();
55
+ const match = /^([A-Za-z]{2,3})(?:[-_]([A-Za-z0-9]{2,8}))?$/.exec(raw);
56
+ if (!match) {return undefined;}
57
+ const [, language, region] = match;
58
+ const base = language!.toLowerCase();
59
+ if (!region) {return base;}
60
+ return `${base}-${region.length === 2 ? region.toUpperCase() : region}`;
61
+ };
62
+
63
+ export const languageLabel = (id: string): string => {
64
+ const exact = LANGUAGE_OPTIONS.find((o) => o.id.toLowerCase() === id.toLowerCase());
65
+ if (exact) {return exact.name;}
66
+ return AUTONYMS[id.split('-')[0]!.toLowerCase()] || id;
67
+ };
68
+
69
+ const toChoices = (ids: string[] | undefined): LanguageChoice[] | undefined => {
70
+ const list = (ids || []).map(canonicalLocale).filter((id): id is string => !!id);
71
+ return list.length ? list.map((id) => ({ id, name: languageLabel(id) })) : undefined;
72
+ };
73
+
74
+ export const languagesEnabled = (config?: IConfig | null): boolean =>
75
+ config?.settings?.languages?.enabled === true;
76
+
77
+ /** What the interface can be shown in. */
78
+ export const appLanguageChoices = (config?: IConfig | null): LanguageChoice[] =>
79
+ toChoices(config?.settings?.languages?.appLanguages) ??
80
+ LANGUAGE_OPTIONS.map((o) => ({ id: o.id, name: o.name }));
81
+
82
+ /** What messages can be translated into. */
83
+ export const chatLanguageChoices = (config?: IConfig | null): LanguageChoice[] =>
84
+ toChoices(config?.settings?.languages?.chatLanguages) ??
85
+ LANGUAGE_OPTIONS.map((o) => ({ id: o.id, name: o.name }));
86
+
87
+ async function writeToProfile(field: 'appLanguage' | 'chatLanguage', value: string) {
88
+ try {
89
+ await updateMe({ [field]: value });
90
+ // The field alone: replacing the whole user with the backend's profile
91
+ // would drop what only this side holds (tokens, the XMPP password).
92
+ store.dispatch(updateUser({ updates: { [field]: value } }));
93
+ return true;
94
+ } catch (error) {
95
+ // The local choice stands: a flaky network degrades to a device-only
96
+ // setting rather than silently reverting what the user just picked.
97
+ console.warn(`[languages] could not save ${field}`, error);
98
+ return false;
99
+ }
100
+ }
101
+
102
+ /** The interface language. Applied at once; written to the profile behind. */
103
+ export async function setAppLanguage(id: string): Promise<boolean> {
104
+ const locale = canonicalLocale(id);
105
+ if (!locale) {return false;}
106
+ store.dispatch(setUiLocale(locale));
107
+ void savePreferences({ uiLocale: locale });
108
+ if (!languagesEnabled(store.getState().chatSettingStore.config)) {return true;}
109
+ return writeToProfile('appLanguage', locale);
110
+ }
111
+
112
+ /** The language messages are translated into. */
113
+ export async function setChatLanguage(id: string): Promise<boolean> {
114
+ const locale = canonicalLocale(id);
115
+ if (!locale) {return false;}
116
+ store.dispatch(setLangSource(locale as any));
117
+ void savePreferences({ chatLanguage: locale });
118
+ if (!languagesEnabled(store.getState().chatSettingStore.config)) {return true;}
119
+ return writeToProfile('chatLanguage', locale);
120
+ }
121
+
122
+ /**
123
+ * The profile's languages, applied when a session starts. The profile is the
124
+ * account's truth; what the device remembered only bridged the gap until
125
+ * now. A profile that has never chosen leaves the device's value alone.
126
+ */
127
+ export function applyProfileLanguages(
128
+ user: { appLanguage?: string | null; chatLanguage?: string | null } | null | undefined,
129
+ config?: IConfig | null
130
+ ): void {
131
+ if (!user || !languagesEnabled(config)) {return;}
132
+ const app = canonicalLocale(user.appLanguage);
133
+ if (app && app !== store.getState().chatSettingStore.uiLocale) {
134
+ store.dispatch(setUiLocale(app));
135
+ void savePreferences({ uiLocale: app });
136
+ }
137
+ // Unset means "follow the app language" - the backend's own rule.
138
+ const chat = canonicalLocale(user.chatLanguage) || app;
139
+ if (chat && chat !== store.getState().chatSettingStore.langSource) {
140
+ store.dispatch(setLangSource(chat as any));
141
+ void savePreferences({ chatLanguage: chat });
142
+ }
143
+ }
@@ -54,6 +54,10 @@ export interface User {
54
54
  isAssetsOpen?: boolean;
55
55
  isAgreeWithTerms?: boolean;
56
56
  isSuperAdmin?: boolean;
57
+ /** Interface language on the profile (BCP-47). */
58
+ appLanguage?: string | null;
59
+ /** Language messages are translated into (BCP-47); unset = follow appLanguage. */
60
+ chatLanguage?: string | null;
57
61
  }
58
62
 
59
63
  export interface ConfigUser {
@@ -652,6 +652,8 @@ export interface IConfig {
652
652
  };
653
653
  disableProfilesInteractions?: boolean;
654
654
  disableUserCount?: boolean;
655
+ /** No Report / Leave behind a room-list row swiped to the left. */
656
+ disableRoomSwipeActions?: boolean;
655
657
  disableSentLogic?: boolean;
656
658
  disableTypingIndicator?: boolean;
657
659
  // Hide the full-screen "Connection error" overlay (the dark modal with
@@ -811,6 +813,27 @@ export interface IConfig {
811
813
  hideAppearance?: boolean;
812
814
  /** Hide the push-notifications toggle. */
813
815
  hidePushToggle?: boolean;
816
+ /**
817
+ * A "Language" card with two pickers, off by default: the interface
818
+ * language (the backend's `user.appLanguage`) and the language messages
819
+ * are translated into (`user.chatLanguage`). A choice is applied at
820
+ * once, kept on the device, and written to the profile with
821
+ * `PUT /v1/users`, one field per request; the profile's values are
822
+ * applied when a session starts. Translation itself is the server's,
823
+ * per the reader's chat language - so `translates.enabled` is what
824
+ * shows the result. Options default to the built-in list (en-CA, es-US,
825
+ * fr-CA); pass BCP-47 tags to offer others.
826
+ */
827
+ languages?: {
828
+ enabled: boolean;
829
+ appLanguages?: string[];
830
+ chatLanguages?: string[];
831
+ };
832
+ /**
833
+ * A "Change password" screen, off by default: the current password and
834
+ * the new one, sent to `PUT /v2/users/me/password`.
835
+ */
836
+ changePassword?: boolean;
814
837
  };
815
838
 
816
839
  // ----- event hooks -----
package/src/version.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  // Generated by scripts/sync-version.mjs on `npm version`.
2
2
  // Edit package.json's version instead of this file.
3
- export const ETHORA_CHAT_COMPONENT_VERSION = '26.8.7';
3
+ export const ETHORA_CHAT_COMPONENT_VERSION = '26.8.9';