@ethora/chat-component-rn 26.8.7 → 26.8.8

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 (195) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +25 -3
  3. package/lib/commonjs/components/MainComponents/ChatWrapper.js +5 -3
  4. package/lib/commonjs/components/MainComponents/ChatWrapper.js.map +1 -1
  5. package/lib/commonjs/components/MainComponents/ReduxWrapper.js +8 -0
  6. package/lib/commonjs/components/MainComponents/ReduxWrapper.js.map +1 -1
  7. package/lib/commonjs/components/Menu/HeaderRoomListMenu.js +26 -13
  8. package/lib/commonjs/components/Menu/HeaderRoomListMenu.js.map +1 -1
  9. package/lib/commonjs/components/MenuRoom/MenuRoom.js +5 -3
  10. package/lib/commonjs/components/MenuRoom/MenuRoom.js.map +1 -1
  11. package/lib/commonjs/components/MessageBubble/Message.js +3 -3
  12. package/lib/commonjs/components/MessageBubble/Message.js.map +1 -1
  13. package/lib/commonjs/components/MessageBubble/MessageInteractions.js +5 -3
  14. package/lib/commonjs/components/MessageBubble/MessageInteractions.js.map +1 -1
  15. package/lib/commonjs/components/Modals/ChatProfileModal/ChatProfileModal.js +1 -1
  16. package/lib/commonjs/components/Modals/ChatProfileModal/ChatProfileModal.js.map +1 -1
  17. package/lib/commonjs/components/Modals/ChatProfileModal/ReportChatModal.js +2 -2
  18. package/lib/commonjs/components/Modals/ChatProfileModal/ReportChatModal.js.map +1 -1
  19. package/lib/commonjs/components/Modals/FilePreviewModal/FilePreviewModal.js +7 -5
  20. package/lib/commonjs/components/Modals/FilePreviewModal/FilePreviewModal.js.map +1 -1
  21. package/lib/commonjs/components/Modals/Modal/Modal.js +33 -11
  22. package/lib/commonjs/components/Modals/Modal/Modal.js.map +1 -1
  23. package/lib/commonjs/components/Modals/NewChatModal/NewChatModal.js +8 -8
  24. package/lib/commonjs/components/Modals/NewChatModal/NewChatModal.js.map +1 -1
  25. package/lib/commonjs/components/Modals/SettingsModals/ChangePassword/ChangePasswordModal.js +279 -0
  26. package/lib/commonjs/components/Modals/SettingsModals/ChangePassword/ChangePasswordModal.js.map +1 -0
  27. package/lib/commonjs/components/Modals/SettingsModals/ManageDataModal/ManageDataModal.js +10 -8
  28. package/lib/commonjs/components/Modals/SettingsModals/ManageDataModal/ManageDataModal.js.map +1 -1
  29. package/lib/commonjs/components/Modals/SettingsModals/Visibility/VisibilityModal.js +13 -11
  30. package/lib/commonjs/components/Modals/SettingsModals/Visibility/VisibilityModal.js.map +1 -1
  31. package/lib/commonjs/components/Modals/UserProfileModal/UserProfileModal.js +21 -9
  32. package/lib/commonjs/components/Modals/UserProfileModal/UserProfileModal.js.map +1 -1
  33. package/lib/commonjs/components/Modals/UserSettingsModal/LanguageCard.js +121 -0
  34. package/lib/commonjs/components/Modals/UserSettingsModal/LanguageCard.js.map +1 -0
  35. package/lib/commonjs/components/Modals/UserSettingsModal/UserSettingsModal.js +11 -6
  36. package/lib/commonjs/components/Modals/UserSettingsModal/UserSettingsModal.js.map +1 -1
  37. package/lib/commonjs/components/Thread/ThreadWrapper.js +4 -2
  38. package/lib/commonjs/components/Thread/ThreadWrapper.js.map +1 -1
  39. package/lib/commonjs/e2ee/stanza.js +1 -1
  40. package/lib/commonjs/e2ee/stanza.js.map +1 -1
  41. package/lib/commonjs/helpers/constants/MODAL_COMPONENTS.js +2 -0
  42. package/lib/commonjs/helpers/constants/MODAL_COMPONENTS.js.map +1 -1
  43. package/lib/commonjs/helpers/constants/MODAL_TYPES.js +1 -0
  44. package/lib/commonjs/helpers/constants/MODAL_TYPES.js.map +1 -1
  45. package/lib/commonjs/helpers/preferencesStorage.js.map +1 -1
  46. package/lib/commonjs/hooks/useChatSettingState.js +2 -0
  47. package/lib/commonjs/hooks/useChatSettingState.js.map +1 -1
  48. package/lib/commonjs/hooks/useChatWrapperInit.js +4 -0
  49. package/lib/commonjs/hooks/useChatWrapperInit.js.map +1 -1
  50. package/lib/commonjs/i18n/strings.js +187 -1
  51. package/lib/commonjs/i18n/strings.js.map +1 -1
  52. package/lib/commonjs/i18n/useT.js +8 -4
  53. package/lib/commonjs/i18n/useT.js.map +1 -1
  54. package/lib/commonjs/networking/api-requests/user.api.js +13 -0
  55. package/lib/commonjs/networking/api-requests/user.api.js.map +1 -1
  56. package/lib/commonjs/networking/stanzaHandlers.js +1 -1
  57. package/lib/commonjs/networking/stanzaHandlers.js.map +1 -1
  58. package/lib/commonjs/roomStore/chatSettingsSlice.js +7 -2
  59. package/lib/commonjs/roomStore/chatSettingsSlice.js.map +1 -1
  60. package/lib/commonjs/services/languageSettings.js +177 -0
  61. package/lib/commonjs/services/languageSettings.js.map +1 -0
  62. package/lib/commonjs/version.js +1 -1
  63. package/lib/module/components/MainComponents/ChatWrapper.js +5 -3
  64. package/lib/module/components/MainComponents/ChatWrapper.js.map +1 -1
  65. package/lib/module/components/MainComponents/ReduxWrapper.js +9 -1
  66. package/lib/module/components/MainComponents/ReduxWrapper.js.map +1 -1
  67. package/lib/module/components/Menu/HeaderRoomListMenu.js +26 -13
  68. package/lib/module/components/Menu/HeaderRoomListMenu.js.map +1 -1
  69. package/lib/module/components/MenuRoom/MenuRoom.js +5 -3
  70. package/lib/module/components/MenuRoom/MenuRoom.js.map +1 -1
  71. package/lib/module/components/MessageBubble/Message.js +3 -3
  72. package/lib/module/components/MessageBubble/Message.js.map +1 -1
  73. package/lib/module/components/MessageBubble/MessageInteractions.js +5 -3
  74. package/lib/module/components/MessageBubble/MessageInteractions.js.map +1 -1
  75. package/lib/module/components/Modals/ChatProfileModal/ChatProfileModal.js +1 -1
  76. package/lib/module/components/Modals/ChatProfileModal/ChatProfileModal.js.map +1 -1
  77. package/lib/module/components/Modals/ChatProfileModal/ReportChatModal.js +2 -2
  78. package/lib/module/components/Modals/ChatProfileModal/ReportChatModal.js.map +1 -1
  79. package/lib/module/components/Modals/FilePreviewModal/FilePreviewModal.js +7 -5
  80. package/lib/module/components/Modals/FilePreviewModal/FilePreviewModal.js.map +1 -1
  81. package/lib/module/components/Modals/Modal/Modal.js +33 -11
  82. package/lib/module/components/Modals/Modal/Modal.js.map +1 -1
  83. package/lib/module/components/Modals/NewChatModal/NewChatModal.js +8 -8
  84. package/lib/module/components/Modals/NewChatModal/NewChatModal.js.map +1 -1
  85. package/lib/module/components/Modals/SettingsModals/ChangePassword/ChangePasswordModal.js +274 -0
  86. package/lib/module/components/Modals/SettingsModals/ChangePassword/ChangePasswordModal.js.map +1 -0
  87. package/lib/module/components/Modals/SettingsModals/ManageDataModal/ManageDataModal.js +10 -8
  88. package/lib/module/components/Modals/SettingsModals/ManageDataModal/ManageDataModal.js.map +1 -1
  89. package/lib/module/components/Modals/SettingsModals/Visibility/VisibilityModal.js +13 -11
  90. package/lib/module/components/Modals/SettingsModals/Visibility/VisibilityModal.js.map +1 -1
  91. package/lib/module/components/Modals/UserProfileModal/UserProfileModal.js +22 -10
  92. package/lib/module/components/Modals/UserProfileModal/UserProfileModal.js.map +1 -1
  93. package/lib/module/components/Modals/UserSettingsModal/LanguageCard.js +116 -0
  94. package/lib/module/components/Modals/UserSettingsModal/LanguageCard.js.map +1 -0
  95. package/lib/module/components/Modals/UserSettingsModal/UserSettingsModal.js +10 -5
  96. package/lib/module/components/Modals/UserSettingsModal/UserSettingsModal.js.map +1 -1
  97. package/lib/module/components/Thread/ThreadWrapper.js +4 -2
  98. package/lib/module/components/Thread/ThreadWrapper.js.map +1 -1
  99. package/lib/module/e2ee/stanza.js +1 -1
  100. package/lib/module/e2ee/stanza.js.map +1 -1
  101. package/lib/module/helpers/constants/MODAL_COMPONENTS.js +2 -0
  102. package/lib/module/helpers/constants/MODAL_COMPONENTS.js.map +1 -1
  103. package/lib/module/helpers/constants/MODAL_TYPES.js +1 -0
  104. package/lib/module/helpers/constants/MODAL_TYPES.js.map +1 -1
  105. package/lib/module/helpers/preferencesStorage.js.map +1 -1
  106. package/lib/module/hooks/useChatSettingState.js +2 -0
  107. package/lib/module/hooks/useChatSettingState.js.map +1 -1
  108. package/lib/module/hooks/useChatWrapperInit.js +4 -0
  109. package/lib/module/hooks/useChatWrapperInit.js.map +1 -1
  110. package/lib/module/i18n/strings.js +187 -1
  111. package/lib/module/i18n/strings.js.map +1 -1
  112. package/lib/module/i18n/useT.js +8 -4
  113. package/lib/module/i18n/useT.js.map +1 -1
  114. package/lib/module/networking/api-requests/user.api.js +12 -0
  115. package/lib/module/networking/api-requests/user.api.js.map +1 -1
  116. package/lib/module/networking/stanzaHandlers.js +1 -1
  117. package/lib/module/networking/stanzaHandlers.js.map +1 -1
  118. package/lib/module/roomStore/chatSettingsSlice.js +5 -1
  119. package/lib/module/roomStore/chatSettingsSlice.js.map +1 -1
  120. package/lib/module/services/languageSettings.js +164 -0
  121. package/lib/module/services/languageSettings.js.map +1 -0
  122. package/lib/module/version.js +1 -1
  123. package/lib/typescript/components/MainComponents/ChatWrapper.d.ts.map +1 -1
  124. package/lib/typescript/components/MainComponents/ReduxWrapper.d.ts.map +1 -1
  125. package/lib/typescript/components/Menu/HeaderRoomListMenu.d.ts +7 -1
  126. package/lib/typescript/components/Menu/HeaderRoomListMenu.d.ts.map +1 -1
  127. package/lib/typescript/components/MenuRoom/MenuRoom.d.ts.map +1 -1
  128. package/lib/typescript/components/MessageBubble/MessageInteractions.d.ts.map +1 -1
  129. package/lib/typescript/components/Modals/FilePreviewModal/FilePreviewModal.d.ts.map +1 -1
  130. package/lib/typescript/components/Modals/Modal/Modal.d.ts.map +1 -1
  131. package/lib/typescript/components/Modals/SettingsModals/ChangePassword/ChangePasswordModal.d.ts +15 -0
  132. package/lib/typescript/components/Modals/SettingsModals/ChangePassword/ChangePasswordModal.d.ts.map +1 -0
  133. package/lib/typescript/components/Modals/SettingsModals/ManageDataModal/ManageDataModal.d.ts.map +1 -1
  134. package/lib/typescript/components/Modals/SettingsModals/Visibility/VisibilityModal.d.ts.map +1 -1
  135. package/lib/typescript/components/Modals/UserProfileModal/UserProfileModal.d.ts.map +1 -1
  136. package/lib/typescript/components/Modals/UserSettingsModal/LanguageCard.d.ts +14 -0
  137. package/lib/typescript/components/Modals/UserSettingsModal/LanguageCard.d.ts.map +1 -0
  138. package/lib/typescript/components/Modals/UserSettingsModal/UserSettingsModal.d.ts.map +1 -1
  139. package/lib/typescript/components/Thread/ThreadWrapper.d.ts.map +1 -1
  140. package/lib/typescript/helpers/constants/MODAL_COMPONENTS.d.ts.map +1 -1
  141. package/lib/typescript/helpers/constants/MODAL_TYPES.d.ts +1 -0
  142. package/lib/typescript/helpers/constants/MODAL_TYPES.d.ts.map +1 -1
  143. package/lib/typescript/helpers/preferencesStorage.d.ts +4 -0
  144. package/lib/typescript/helpers/preferencesStorage.d.ts.map +1 -1
  145. package/lib/typescript/hooks/useChatSettingState.d.ts +1 -0
  146. package/lib/typescript/hooks/useChatSettingState.d.ts.map +1 -1
  147. package/lib/typescript/hooks/useChatWrapperInit.d.ts.map +1 -1
  148. package/lib/typescript/i18n/strings.d.ts.map +1 -1
  149. package/lib/typescript/i18n/useT.d.ts.map +1 -1
  150. package/lib/typescript/networking/api-requests/user.api.d.ts +6 -0
  151. package/lib/typescript/networking/api-requests/user.api.d.ts.map +1 -1
  152. package/lib/typescript/networking/stanzaHandlers.d.ts.map +1 -1
  153. package/lib/typescript/roomStore/chatSettingsSlice.d.ts +8 -1
  154. package/lib/typescript/roomStore/chatSettingsSlice.d.ts.map +1 -1
  155. package/lib/typescript/services/languageSettings.d.ts +29 -0
  156. package/lib/typescript/services/languageSettings.d.ts.map +1 -0
  157. package/lib/typescript/types/models/user.model.d.ts +4 -0
  158. package/lib/typescript/types/models/user.model.d.ts.map +1 -1
  159. package/lib/typescript/types/types.d.ts +21 -0
  160. package/lib/typescript/types/types.d.ts.map +1 -1
  161. package/lib/typescript/version.d.ts +1 -1
  162. package/package.json +1 -1
  163. package/src/components/MainComponents/ChatWrapper.tsx +5 -3
  164. package/src/components/MainComponents/ReduxWrapper.tsx +6 -0
  165. package/src/components/Menu/HeaderRoomListMenu.tsx +40 -13
  166. package/src/components/MenuRoom/MenuRoom.tsx +5 -3
  167. package/src/components/MessageBubble/Message.tsx +3 -3
  168. package/src/components/MessageBubble/MessageInteractions.tsx +5 -3
  169. package/src/components/Modals/ChatProfileModal/ChatProfileModal.tsx +1 -1
  170. package/src/components/Modals/ChatProfileModal/ReportChatModal.tsx +2 -2
  171. package/src/components/Modals/FilePreviewModal/FilePreviewModal.tsx +7 -5
  172. package/src/components/Modals/Modal/Modal.tsx +44 -16
  173. package/src/components/Modals/NewChatModal/NewChatModal.tsx +8 -8
  174. package/src/components/Modals/SettingsModals/ChangePassword/ChangePasswordModal.tsx +316 -0
  175. package/src/components/Modals/SettingsModals/ManageDataModal/ManageDataModal.tsx +10 -15
  176. package/src/components/Modals/SettingsModals/Visibility/VisibilityModal.tsx +13 -14
  177. package/src/components/Modals/UserProfileModal/UserProfileModal.tsx +19 -12
  178. package/src/components/Modals/UserSettingsModal/LanguageCard.tsx +144 -0
  179. package/src/components/Modals/UserSettingsModal/UserSettingsModal.tsx +11 -4
  180. package/src/components/Thread/ThreadWrapper.tsx +4 -2
  181. package/src/e2ee/stanza.ts +1 -1
  182. package/src/helpers/constants/MODAL_COMPONENTS.tsx +2 -0
  183. package/src/helpers/constants/MODAL_TYPES.ts +1 -0
  184. package/src/helpers/preferencesStorage.ts +4 -0
  185. package/src/hooks/useChatSettingState.tsx +4 -0
  186. package/src/hooks/useChatWrapperInit.ts +4 -0
  187. package/src/i18n/strings.ts +187 -1
  188. package/src/i18n/useT.ts +6 -4
  189. package/src/networking/api-requests/user.api.ts +9 -0
  190. package/src/networking/stanzaHandlers.ts +1 -0
  191. package/src/roomStore/chatSettingsSlice.ts +13 -0
  192. package/src/services/languageSettings.ts +143 -0
  193. package/src/types/models/user.model.ts +4 -0
  194. package/src/types/types.ts +21 -0
  195. package/src/version.ts +1 -1
@@ -0,0 +1,144 @@
1
+ import React, { useCallback, useMemo } from 'react';
2
+ import { StyleProp, StyleSheet, Text, TouchableOpacity, View, ViewStyle } from 'react-native';
3
+ import { useTheme } from '../../../hooks/useTheme';
4
+ import { useT } from '../../../i18n/useT';
5
+ import { useChatSettingState } from '../../../hooks/useChatSettingState';
6
+ import {
7
+ appLanguageChoices,
8
+ chatLanguageChoices,
9
+ setAppLanguage,
10
+ setChatLanguage,
11
+ type LanguageChoice,
12
+ } from '../../../services/languageSettings';
13
+
14
+ interface LanguageCardProps {
15
+ style?: StyleProp<ViewStyle>;
16
+ testID?: string;
17
+ }
18
+
19
+ /**
20
+ * The user's two languages: the interface, and what messages are translated
21
+ * into. See services/languageSettings for what each one does and where it
22
+ * is kept.
23
+ */
24
+ const LanguageCard: React.FC<LanguageCardProps> = ({ style, testID }) => {
25
+ const theme = useTheme();
26
+ const t = useT();
27
+ const { config, langSource, uiLocale } = useChatSettingState();
28
+
29
+ const appChoices = useMemo(() => appLanguageChoices(config), [config]);
30
+ const chatChoices = useMemo(() => chatLanguageChoices(config), [config]);
31
+ const appCurrent = uiLocale || config?.i18n?.locale || '';
32
+ // Unset follows the interface language - the backend's own rule.
33
+ const chatCurrent = langSource || appCurrent;
34
+
35
+ const pick = useCallback(
36
+ (kind: 'app' | 'chat', id: string) => {
37
+ void (kind === 'app' ? setAppLanguage(id) : setChatLanguage(id));
38
+ },
39
+ []
40
+ );
41
+
42
+ const same = (a: string, b: string) => a.toLowerCase() === b.toLowerCase();
43
+
44
+ const group = (
45
+ kind: 'app' | 'chat',
46
+ label: string,
47
+ hint: string,
48
+ choices: LanguageChoice[],
49
+ current: string
50
+ ) => (
51
+ <View style={styles.group}>
52
+ <Text style={[styles.label, { color: theme.text }]}>{label}</Text>
53
+ <Text style={[styles.hint, { color: theme.textSecondary }]}>{hint}</Text>
54
+ <View style={styles.pills} accessibilityRole="radiogroup">
55
+ {choices.map((choice) => {
56
+ const selected = same(choice.id, current);
57
+ return (
58
+ <TouchableOpacity
59
+ key={choice.id}
60
+ testID={`settings-language-${kind}-${choice.id}`}
61
+ accessibilityRole="radio"
62
+ accessibilityState={{ selected }}
63
+ activeOpacity={0.7}
64
+ onPress={() => pick(kind, choice.id)}
65
+ style={[
66
+ styles.pill,
67
+ {
68
+ borderColor: selected ? theme.primary : theme.border,
69
+ backgroundColor: selected ? theme.primary : theme.surfaceSecondary,
70
+ },
71
+ ]}
72
+ >
73
+ <Text
74
+ style={[
75
+ styles.pillLabel,
76
+ { color: selected ? theme.textOnPrimary : theme.text },
77
+ ]}
78
+ >
79
+ {choice.name}
80
+ </Text>
81
+ </TouchableOpacity>
82
+ );
83
+ })}
84
+ </View>
85
+ </View>
86
+ );
87
+
88
+ return (
89
+ <View style={[style, styles.card]} testID={testID || 'settings-languages'}>
90
+ {group(
91
+ 'app',
92
+ t('settings.language.app'),
93
+ t('settings.language.appHint'),
94
+ appChoices,
95
+ appCurrent
96
+ )}
97
+ {group(
98
+ 'chat',
99
+ t('settings.language.chat'),
100
+ t('settings.language.chatHint'),
101
+ chatChoices,
102
+ chatCurrent
103
+ )}
104
+ </View>
105
+ );
106
+ };
107
+
108
+ export default LanguageCard;
109
+
110
+ const styles = StyleSheet.create({
111
+ // Applied over the host's card style: its surface, this layout.
112
+ card: {
113
+ flexDirection: 'column',
114
+ alignItems: 'stretch',
115
+ gap: 18,
116
+ },
117
+ group: {
118
+ gap: 6,
119
+ },
120
+ label: {
121
+ fontSize: 17,
122
+ fontWeight: '500',
123
+ },
124
+ hint: {
125
+ fontSize: 13,
126
+ lineHeight: 18,
127
+ },
128
+ pills: {
129
+ flexDirection: 'row',
130
+ flexWrap: 'wrap',
131
+ gap: 8,
132
+ marginTop: 6,
133
+ },
134
+ pill: {
135
+ paddingHorizontal: 14,
136
+ paddingVertical: 8,
137
+ borderRadius: 999,
138
+ borderWidth: 1,
139
+ },
140
+ pillLabel: {
141
+ fontSize: 14,
142
+ fontWeight: '600',
143
+ },
144
+ });
@@ -1,7 +1,7 @@
1
1
  /** @format */
2
2
 
3
- import EncryptionCard from '../../MainComponents/EncryptionCard';
4
3
  import React, { useCallback, useMemo } from 'react';
4
+ import LanguageCard from './LanguageCard';
5
5
  import {
6
6
  StyleSheet,
7
7
  Switch,
@@ -64,12 +64,17 @@ const UserSettingsModal: React.FC<UserSettingsModalProps> = ({
64
64
  [t]
65
65
  );
66
66
 
67
+ const showPassword = config?.settings?.changePassword === true;
67
68
  const options = useMemo(
68
69
  () => [
69
70
  { label: t('settings.manageData.title'), key: MODAL_TYPES.MANAGE_DATA },
70
71
  { label: t('settings.visibility.title'), key: MODAL_TYPES.VISIBILITY },
72
+ // Off unless the host turned it on: not every backend has the endpoint.
73
+ ...(showPassword
74
+ ? [{ label: t('settings.password.title'), key: MODAL_TYPES.CHANGE_PASSWORD }]
75
+ : []),
71
76
  ],
72
- [t]
77
+ [t, showPassword]
73
78
  );
74
79
 
75
80
  const handleClick = useCallback(
@@ -160,8 +165,10 @@ const UserSettingsModal: React.FC<UserSettingsModalProps> = ({
160
165
  </View>
161
166
  ) : null}
162
167
 
163
- {config?.e2ee?.enabled === true ? (
164
- <EncryptionCard style={styles.card} testID="settings-e2ee" />
168
+ {/* The interface language and the translation language; off
169
+ unless the host turned it on, as it writes to the profile. */}
170
+ {config?.settings?.languages?.enabled === true ? (
171
+ <LanguageCard style={styles.card} />
165
172
  ) : null}
166
173
 
167
174
  {options.map((option) => (
@@ -29,6 +29,7 @@ import { useSendMessage } from '../../hooks/useSendMessage';
29
29
  import { createMainMessageForThread } from '../../helpers/createMainMessageForThread';
30
30
  import { useChatSettingState } from '../../hooks/useChatSettingState';
31
31
  import { useTheme } from '../../hooks/useTheme';
32
+ import { useT } from '../../i18n/useT';
32
33
  import CustomTypingIndicator from '../styled/StyledInputComponents/CustomTypingIndicator';
33
34
  import { KeyboardInputDock } from '../MainComponents/KeyboardInputDock';
34
35
  import {
@@ -69,6 +70,7 @@ const ThreadWrapper: FC<ThreadWrapperProps> = ({
69
70
  const reduxStore = useStore<RootState>();
70
71
  const { config } = useChatSettingState();
71
72
  const theme = useTheme();
73
+ const t = useT();
72
74
  const insets = useSafeAreaInsets();
73
75
  const { width: windowWidth } = useWindowDimensions();
74
76
  const roomJid = activeMessage.roomJid;
@@ -217,7 +219,7 @@ const ThreadWrapper: FC<ThreadWrapperProps> = ({
217
219
  style={[styles.fill, { backgroundColor: theme.surface }]}
218
220
  >
219
221
  <View style={[styles.fill, { backgroundColor: theme.chatBackground }]}>
220
- <ModalHeaderComponent headerTitle="Thread" handleCloseModal={close} />
222
+ <ModalHeaderComponent headerTitle={t('thread.title')} handleCloseModal={close} />
221
223
  <MessageList
222
224
  loadMoreMessages={loadMoreMessages}
223
225
  CustomMessage={CustomMessageComponent}
@@ -267,7 +269,7 @@ const ThreadWrapper: FC<ThreadWrapperProps> = ({
267
269
  numberOfLines={1}
268
270
  style={[styles.alsoText, { color: theme.textSecondary }]}
269
271
  >
270
- Also send to{' '}
272
+ {t('thread.alsoSendTo')}{' '}
271
273
  <Text style={{ color: theme.primary, fontWeight: '600' }}>
272
274
  {roomDisplayName}
273
275
  </Text>
@@ -48,7 +48,7 @@ function placeholder(error: E2eeError): Element {
48
48
  return new Element('body', {}).t(
49
49
  translateKey(
50
50
  placeholderKey(error),
51
- settings?.config?.i18n?.locale || settings?.langSource,
51
+ settings?.uiLocale || settings?.config?.i18n?.locale || settings?.langSource,
52
52
  settings?.config?.i18n?.strings
53
53
  )
54
54
  );
@@ -14,6 +14,7 @@ import ManageDataModal from '../../components/Modals/SettingsModals/ManageDataMo
14
14
  import ProfileSharesModal from '../../components/Modals/SettingsModals/ProfileShares/ProfileShares';
15
15
  import ReferralsModal from '../../components/Modals/SettingsModals/Referrals/Referrals';
16
16
  import VisibilityModal from '../../components/Modals/SettingsModals/Visibility/VisibilityModal';
17
+ import ChangePasswordModal from '../../components/Modals/SettingsModals/ChangePassword/ChangePasswordModal';
17
18
  import UserProfileModal from '../../components/Modals/UserProfileModal/UserProfileModal';
18
19
  import UserSettingsModal from '../../components/Modals/UserSettingsModal/UserSettingsModal';
19
20
 
@@ -27,6 +28,7 @@ export const MODAL_COMPONENTS: Record<
27
28
  [MODAL_TYPES.CHAT_PROFILE]: ChatProfileModal,
28
29
  [MODAL_TYPES.MANAGE_DATA]: ManageDataModal,
29
30
  [MODAL_TYPES.VISIBILITY]: VisibilityModal,
31
+ [MODAL_TYPES.CHANGE_PASSWORD]: ChangePasswordModal,
30
32
  [MODAL_TYPES.REFERRALS]: ReferralsModal,
31
33
  [MODAL_TYPES.DOCUMENT_SHARES]: DocumentSharesModal,
32
34
  [MODAL_TYPES.PROFILE_SHARES]: ProfileSharesModal,
@@ -15,6 +15,7 @@ export const MODAL_TYPES = {
15
15
  CHAT_PROFILE: 'chatprofile',
16
16
  MANAGE_DATA: 'managedata',
17
17
  VISIBILITY: 'visibility',
18
+ CHANGE_PASSWORD: 'change_password',
18
19
 
19
20
  PROFILE_SHARES: 'profile_shares',
20
21
  DOCUMENT_SHARES: 'document_shares',
@@ -9,6 +9,10 @@ const KEY = '@ethora/preferences';
9
9
  export interface StoredPreferences {
10
10
  theme?: ThemePreference;
11
11
  pushEnabled?: boolean;
12
+ /** Interface language picked in Settings (BCP-47). */
13
+ uiLocale?: string;
14
+ /** Language messages are translated into, picked in Settings (BCP-47). */
15
+ chatLanguage?: string;
12
16
  }
13
17
 
14
18
  export const loadPreferences = async (): Promise<StoredPreferences> => {
@@ -9,6 +9,9 @@ export const useChatSettingState = () => {
9
9
  const activeModal = useSelector(
10
10
  (state: RootState) => state.chatSettingStore.activeModal
11
11
  );
12
+ const uiLocale = useSelector(
13
+ (state: RootState) => state.chatSettingStore.uiLocale
14
+ );
12
15
  const config = useSelector(
13
16
  (state: RootState) => state.chatSettingStore.config
14
17
  );
@@ -29,6 +32,7 @@ export const useChatSettingState = () => {
29
32
  );
30
33
 
31
34
  return {
35
+ uiLocale,
32
36
  user,
33
37
  activeFile,
34
38
  activeModal,
@@ -12,6 +12,7 @@ import { initRoomsPresence } from '../helpers/initRoomsPresence';
12
12
  import { updateMessagesTillLast } from '../helpers/updateMessagesTillLast';
13
13
  import { refreshAuthTokensQuietly } from '../networking/authRefresh';
14
14
  import { setLangSource, setConfig } from '../roomStore/chatSettingsSlice';
15
+ import { applyProfileLanguages } from '../services/languageSettings';
15
16
  import { setIsLoading } from '../roomStore/roomsSlice';
16
17
  import { useRoomState } from './useRoomState';
17
18
  import { useChatSettingState } from './useChatSettingState';
@@ -120,6 +121,9 @@ const useChatWrapperInit = ({
120
121
  }
121
122
 
122
123
  dispatch(setConfig(config));
124
+ // The profile's languages are the account's truth, over what the
125
+ // device remembered.
126
+ applyProfileLanguages(user as any, config);
123
127
  try {
124
128
  if (!user.xmppUsername) {
125
129
  setShowModal(true);