@ethora/chat-component-rn 26.7.10 → 26.8.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.
- package/lib/commonjs/components/Header/HeaderRoomList.js +3 -1
- package/lib/commonjs/components/Header/HeaderRoomList.js.map +1 -1
- package/lib/commonjs/components/MainComponents/ChatWrapper.js +25 -0
- package/lib/commonjs/components/MainComponents/ChatWrapper.js.map +1 -1
- package/lib/commonjs/components/MainComponents/ReduxWrapper.js +24 -3
- package/lib/commonjs/components/MainComponents/ReduxWrapper.js.map +1 -1
- package/lib/commonjs/components/MessageBubble/MessageTranslate.js +16 -7
- package/lib/commonjs/components/MessageBubble/MessageTranslate.js.map +1 -1
- package/lib/commonjs/components/Modals/AttachSheet/AttachSheet.js +7 -3
- package/lib/commonjs/components/Modals/AttachSheet/AttachSheet.js.map +1 -1
- package/lib/commonjs/components/Modals/ChatProfileModal/ChatProfileModal.js +12 -10
- package/lib/commonjs/components/Modals/ChatProfileModal/ChatProfileModal.js.map +1 -1
- package/lib/commonjs/components/Modals/ChatProfileModal/DeleteChatModal.js +9 -7
- package/lib/commonjs/components/Modals/ChatProfileModal/DeleteChatModal.js.map +1 -1
- package/lib/commonjs/components/Modals/NewChatModal/NewChatModal.js +3 -3
- package/lib/commonjs/components/Modals/NewChatModal/NewChatModal.js.map +1 -1
- package/lib/commonjs/components/Modals/ProfileHeader/ProfileHeader.js +8 -1
- package/lib/commonjs/components/Modals/ProfileHeader/ProfileHeader.js.map +1 -1
- package/lib/commonjs/components/RoomComponents/ChatRoomItem.js +32 -2
- package/lib/commonjs/components/RoomComponents/ChatRoomItem.js.map +1 -1
- package/lib/commonjs/components/styled/DateLabel.js +10 -3
- package/lib/commonjs/components/styled/DateLabel.js.map +1 -1
- package/lib/commonjs/components/styled/NewMessageLabel.js +3 -1
- package/lib/commonjs/components/styled/NewMessageLabel.js.map +1 -1
- package/lib/commonjs/components/styled/SendInput.js +6 -6
- package/lib/commonjs/components/styled/SendInput.js.map +1 -1
- package/lib/commonjs/context/xmppProvider.js +7 -0
- package/lib/commonjs/context/xmppProvider.js.map +1 -1
- package/lib/commonjs/helpers/getDataFromXml.js +24 -1
- package/lib/commonjs/helpers/getDataFromXml.js.map +1 -1
- package/lib/commonjs/helpers/insertMessageWithDelimiter.js +13 -0
- package/lib/commonjs/helpers/insertMessageWithDelimiter.js.map +1 -1
- package/lib/commonjs/helpers/isUnresolvedSenderId.js +6 -1
- package/lib/commonjs/helpers/isUnresolvedSenderId.js.map +1 -1
- package/lib/commonjs/helpers/resolveLangSource.js +38 -0
- package/lib/commonjs/helpers/resolveLangSource.js.map +1 -0
- package/lib/commonjs/helpers/xmppUsername.js +39 -0
- package/lib/commonjs/helpers/xmppUsername.js.map +1 -0
- package/lib/commonjs/hooks/useChatWrapperInit.js +4 -2
- package/lib/commonjs/hooks/useChatWrapperInit.js.map +1 -1
- package/lib/commonjs/i18n/strings.js +120 -0
- package/lib/commonjs/i18n/strings.js.map +1 -1
- package/lib/commonjs/i18n/useT.js +1 -1
- package/lib/commonjs/networking/stanzaHandlers.js +41 -70
- package/lib/commonjs/networking/stanzaHandlers.js.map +1 -1
- package/lib/commonjs/roomStore/persistence.js +17 -1
- package/lib/commonjs/roomStore/persistence.js.map +1 -1
- package/lib/commonjs/version.js +3 -1
- package/lib/commonjs/version.js.map +1 -1
- package/lib/module/components/Header/HeaderRoomList.js +3 -1
- package/lib/module/components/Header/HeaderRoomList.js.map +1 -1
- package/lib/module/components/MainComponents/ChatWrapper.js +26 -1
- package/lib/module/components/MainComponents/ChatWrapper.js.map +1 -1
- package/lib/module/components/MainComponents/ReduxWrapper.js +26 -5
- package/lib/module/components/MainComponents/ReduxWrapper.js.map +1 -1
- package/lib/module/components/MessageBubble/MessageTranslate.js +16 -7
- package/lib/module/components/MessageBubble/MessageTranslate.js.map +1 -1
- package/lib/module/components/Modals/AttachSheet/AttachSheet.js +7 -3
- package/lib/module/components/Modals/AttachSheet/AttachSheet.js.map +1 -1
- package/lib/module/components/Modals/ChatProfileModal/ChatProfileModal.js +12 -10
- package/lib/module/components/Modals/ChatProfileModal/ChatProfileModal.js.map +1 -1
- package/lib/module/components/Modals/ChatProfileModal/DeleteChatModal.js +9 -7
- package/lib/module/components/Modals/ChatProfileModal/DeleteChatModal.js.map +1 -1
- package/lib/module/components/Modals/NewChatModal/NewChatModal.js +3 -3
- package/lib/module/components/Modals/NewChatModal/NewChatModal.js.map +1 -1
- package/lib/module/components/Modals/ProfileHeader/ProfileHeader.js +8 -1
- package/lib/module/components/Modals/ProfileHeader/ProfileHeader.js.map +1 -1
- package/lib/module/components/RoomComponents/ChatRoomItem.js +33 -3
- package/lib/module/components/RoomComponents/ChatRoomItem.js.map +1 -1
- package/lib/module/components/styled/DateLabel.js +10 -3
- package/lib/module/components/styled/DateLabel.js.map +1 -1
- package/lib/module/components/styled/NewMessageLabel.js +3 -1
- package/lib/module/components/styled/NewMessageLabel.js.map +1 -1
- package/lib/module/components/styled/SendInput.js +6 -6
- package/lib/module/components/styled/SendInput.js.map +1 -1
- package/lib/module/context/xmppProvider.js +7 -0
- package/lib/module/context/xmppProvider.js.map +1 -1
- package/lib/module/helpers/getDataFromXml.js +23 -1
- package/lib/module/helpers/getDataFromXml.js.map +1 -1
- package/lib/module/helpers/insertMessageWithDelimiter.js +13 -0
- package/lib/module/helpers/insertMessageWithDelimiter.js.map +1 -1
- package/lib/module/helpers/isUnresolvedSenderId.js +6 -1
- package/lib/module/helpers/isUnresolvedSenderId.js.map +1 -1
- package/lib/module/helpers/resolveLangSource.js +32 -0
- package/lib/module/helpers/resolveLangSource.js.map +1 -0
- package/lib/module/helpers/xmppUsername.js +35 -0
- package/lib/module/helpers/xmppUsername.js.map +1 -0
- package/lib/module/hooks/useChatWrapperInit.js +4 -2
- package/lib/module/hooks/useChatWrapperInit.js.map +1 -1
- package/lib/module/i18n/strings.js +120 -0
- package/lib/module/i18n/strings.js.map +1 -1
- package/lib/module/i18n/useT.js +1 -1
- package/lib/module/networking/stanzaHandlers.js +42 -71
- package/lib/module/networking/stanzaHandlers.js.map +1 -1
- package/lib/module/roomStore/persistence.js +17 -1
- package/lib/module/roomStore/persistence.js.map +1 -1
- package/lib/module/version.js +3 -1
- package/lib/module/version.js.map +1 -1
- package/lib/typescript/components/Header/HeaderRoomList.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/ChatWrapper.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/ReduxWrapper.d.ts.map +1 -1
- package/lib/typescript/components/MessageBubble/MessageTranslate.d.ts.map +1 -1
- package/lib/typescript/components/Modals/AttachSheet/AttachSheet.d.ts.map +1 -1
- package/lib/typescript/components/Modals/ChatProfileModal/DeleteChatModal.d.ts.map +1 -1
- package/lib/typescript/components/Modals/NewChatModal/NewChatModal.d.ts.map +1 -1
- package/lib/typescript/components/Modals/ProfileHeader/ProfileHeader.d.ts.map +1 -1
- package/lib/typescript/components/RoomComponents/ChatRoomItem.d.ts.map +1 -1
- package/lib/typescript/components/styled/DateLabel.d.ts.map +1 -1
- package/lib/typescript/components/styled/NewMessageLabel.d.ts.map +1 -1
- package/lib/typescript/components/styled/SendInput.d.ts.map +1 -1
- package/lib/typescript/context/xmppProvider.d.ts.map +1 -1
- package/lib/typescript/helpers/getDataFromXml.d.ts.map +1 -1
- package/lib/typescript/helpers/insertMessageWithDelimiter.d.ts.map +1 -1
- package/lib/typescript/helpers/isUnresolvedSenderId.d.ts.map +1 -1
- package/lib/typescript/helpers/resolveLangSource.d.ts +30 -0
- package/lib/typescript/helpers/resolveLangSource.d.ts.map +1 -0
- package/lib/typescript/helpers/xmppUsername.d.ts +13 -0
- package/lib/typescript/helpers/xmppUsername.d.ts.map +1 -0
- package/lib/typescript/hooks/useChatWrapperInit.d.ts.map +1 -1
- package/lib/typescript/i18n/strings.d.ts.map +1 -1
- package/lib/typescript/i18n/useT.d.ts +1 -1
- package/lib/typescript/networking/stanzaHandlers.d.ts.map +1 -1
- package/lib/typescript/roomStore/persistence.d.ts.map +1 -1
- package/lib/typescript/version.d.ts +1 -1
- package/lib/typescript/version.d.ts.map +1 -1
- package/package.json +2 -1
- package/src/components/Header/HeaderRoomList.tsx +5 -1
- package/src/components/MainComponents/ChatWrapper.tsx +33 -0
- package/src/components/MainComponents/ReduxWrapper.tsx +18 -1
- package/src/components/MessageBubble/MessageTranslate.tsx +17 -12
- package/src/components/Modals/AttachSheet/AttachSheet.tsx +7 -3
- package/src/components/Modals/ChatProfileModal/ChatProfileModal.tsx +11 -11
- package/src/components/Modals/ChatProfileModal/DeleteChatModal.tsx +9 -7
- package/src/components/Modals/NewChatModal/NewChatModal.tsx +7 -4
- package/src/components/Modals/ProfileHeader/ProfileHeader.tsx +11 -2
- package/src/components/RoomComponents/ChatRoomItem.tsx +47 -3
- package/src/components/styled/DateLabel.tsx +10 -3
- package/src/components/styled/NewMessageLabel.tsx +3 -1
- package/src/components/styled/SendInput.tsx +6 -8
- package/src/context/xmppProvider.tsx +7 -0
- package/src/helpers/getDataFromXml.ts +25 -1
- package/src/helpers/insertMessageWithDelimiter.ts +13 -0
- package/src/helpers/isUnresolvedSenderId.ts +9 -1
- package/src/helpers/resolveLangSource.ts +40 -0
- package/src/helpers/xmppUsername.ts +38 -0
- package/src/hooks/useChatWrapperInit.ts +6 -2
- package/src/i18n/strings.ts +120 -0
- package/src/i18n/useT.ts +1 -1
- package/src/networking/stanzaHandlers.ts +42 -67
- package/src/roomStore/persistence.ts +16 -0
- package/src/version.ts +3 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SendInput.d.ts","sourceRoot":"","sources":["../../../../src/components/styled/SendInput.tsx"],"names":[],"mappings":"AAAA,cAAc;AAEd,OAAO,KAAmD,MAAM,OAAO,CAAC;AAMxE,OAAO,EAAE,OAAO,EAAa,MAAM,mBAAmB,CAAC;AAkEvD,UAAU,cAAc;IACtB,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACzC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;CAC5D;AAED,QAAA,MAAM,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,cAAc,
|
|
1
|
+
{"version":3,"file":"SendInput.d.ts","sourceRoot":"","sources":["../../../../src/components/styled/SendInput.tsx"],"names":[],"mappings":"AAAA,cAAc;AAEd,OAAO,KAAmD,MAAM,OAAO,CAAC;AAMxE,OAAO,EAAE,OAAO,EAAa,MAAM,mBAAmB,CAAC;AAkEvD,UAAU,cAAc;IACtB,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACzC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;CAC5D;AAED,QAAA,MAAM,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,cAAc,CA+qBvC,CAAC;AAEF,eAAe,SAAS,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"xmppProvider.d.ts","sourceRoot":"","sources":["../../../src/context/xmppProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EACZ,SAAS,EAQV,MAAM,OAAO,CAAC;AAIf,OAAO,UAEN,MAAM,0BAA0B,CAAC;AAElC,OAAO,EACL,OAAO,EACP,uBAAuB,EAEvB,qBAAqB,EACtB,MAAM,gBAAgB,CAAC;AAsCxB,UAAU,QAAQ;IAChB,OAAO,EAAE,UAAU,GAAG,MAAM,CAAC;CAC9B;AAED,UAAU,eAAe;IACvB,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;IAC1B,uBAAuB,EAAE,uBAAuB,CAAC;IACjD,QAAQ,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC;IAC9B,SAAS,EAAE,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,KAAK,IAAI,CAAC;IAC/C,gBAAgB,EAAE,CAChB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,YAAY,CAAC,EAAE,qBAAqB,KACjC,OAAO,CAAC,UAAU,CAAC,CAAC;CAC1B;AAID,UAAU,iBAAiB;IACzB,QAAQ,EAAE,SAAS,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IAIjB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAcD,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,
|
|
1
|
+
{"version":3,"file":"xmppProvider.d.ts","sourceRoot":"","sources":["../../../src/context/xmppProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EACZ,SAAS,EAQV,MAAM,OAAO,CAAC;AAIf,OAAO,UAEN,MAAM,0BAA0B,CAAC;AAElC,OAAO,EACL,OAAO,EACP,uBAAuB,EAEvB,qBAAqB,EACtB,MAAM,gBAAgB,CAAC;AAsCxB,UAAU,QAAQ;IAChB,OAAO,EAAE,UAAU,GAAG,MAAM,CAAC;CAC9B;AAED,UAAU,eAAe;IACvB,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;IAC1B,uBAAuB,EAAE,uBAAuB,CAAC;IACjD,QAAQ,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC;IAC9B,SAAS,EAAE,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,KAAK,IAAI,CAAC;IAC/C,gBAAgB,EAAE,CAChB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,YAAY,CAAC,EAAE,qBAAqB,KACjC,OAAO,CAAC,UAAU,CAAC,CAAC;CAC1B;AAID,UAAU,iBAAiB;IACzB,QAAQ,EAAE,SAAS,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IAIjB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAcD,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CA+0BpD,CAAC;AAEF,eAAO,MAAM,aAAa,uBAkBzB,CAAC;AAEF,iFAAiF;AACjF,wBAAgB,cAAc,SAE7B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getDataFromXml.d.ts","sourceRoot":"","sources":["../../../src/helpers/getDataFromXml.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AAC9B,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"getDataFromXml.d.ts","sourceRoot":"","sources":["../../../src/helpers/getDataFromXml.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AAC9B,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAoDtD,UAAU,OAAO;IACf,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,KAAK,CAAC;IACZ,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY,CAAC,EAAE,GAAG,CAAC;IACnB,UAAU,CAAC,EAAE,aAAa,CAAC;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE;QAAE,CAAC,CAAC,EAAE,MAAM,GAAG,GAAG,CAAA;KAAE,CAAC;CAC5B;AACD,eAAO,MAAM,cAAc,GAAU,QAAQ,OAAO,KAAG,OAAO,CAAC,OAAO,GAAG,SAAS,CAyEjF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"insertMessageWithDelimiter.d.ts","sourceRoot":"","sources":["../../../src/helpers/insertMessageWithDelimiter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"insertMessageWithDelimiter.d.ts","sourceRoot":"","sources":["../../../src/helpers/insertMessageWithDelimiter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AA6D1C,wBAAgB,0BAA0B,CACxC,YAAY,EAAE,OAAO,CAAC,QAAQ,CAAC,EAAE,EACjC,OAAO,EAAE,QAAQ,EACjB,mBAAmB,EAAE,MAAM,GAAG;IAAE,QAAQ,EAAE,MAAM,MAAM,CAAA;CAAE,GAAG,IAAI,QAyGhE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"isUnresolvedSenderId.d.ts","sourceRoot":"","sources":["../../../src/helpers/isUnresolvedSenderId.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"isUnresolvedSenderId.d.ts","sourceRoot":"","sources":["../../../src/helpers/isUnresolvedSenderId.ts"],"names":[],"mappings":"AA0BA,eAAO,MAAM,oBAAoB,GAAI,OAAO,MAAM,KAAG,OAMpD,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { IConfig, Iso639_1Codes } from '../types/types';
|
|
2
|
+
/**
|
|
3
|
+
* Legacy single-locale config (`translates.translations`) seeds langSource
|
|
4
|
+
* only when the host ACTUALLY set it.
|
|
5
|
+
*
|
|
6
|
+
* The condition used to be inverted (`!translates.translations`), so merely
|
|
7
|
+
* enabling translation fired `setLangSource(undefined)` on every XMPP init
|
|
8
|
+
* and wiped whatever the reader had picked from the globe — the language
|
|
9
|
+
* reset itself on every reconnect. Web fixed this; RN had not.
|
|
10
|
+
*/
|
|
11
|
+
export declare const resolveLegacyTranslatesLangSource: (translatesConfig?: IConfig["translates"]) => Iso639_1Codes | undefined;
|
|
12
|
+
/**
|
|
13
|
+
* A host drives the reader's language from OUTSIDE the component by setting
|
|
14
|
+
* `config.translates.readerLocale` (their own language switcher, or the
|
|
15
|
+
* testbed's Setup tab). Nothing was syncing it into `langSource`, so pinning
|
|
16
|
+
* it only redirected the incoming-translation lookup: the UI captions and
|
|
17
|
+
* the `<translate source>` on outgoing messages both kept following the
|
|
18
|
+
* unset `langSource`.
|
|
19
|
+
*
|
|
20
|
+
* Unlike web this keeps the FULL locale rather than the base language. RN's
|
|
21
|
+
* LANGUAGE_OPTIONS are region-tagged (`es-US`, `fr-CA`) because the region
|
|
22
|
+
* is forwarded to the translation service, and the in-chat picker stores
|
|
23
|
+
* that full form — so the external path has to store the same thing or the
|
|
24
|
+
* two would disagree. Caption lookups strip to the base themselves.
|
|
25
|
+
*
|
|
26
|
+
* Resolves only when actually set, so a host that leaves it unset never
|
|
27
|
+
* clobbers what the reader chose for themselves.
|
|
28
|
+
*/
|
|
29
|
+
export declare const resolveExternalReaderLocaleLangSource: (readerLocale?: string) => Iso639_1Codes | undefined;
|
|
30
|
+
//# sourceMappingURL=resolveLangSource.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolveLangSource.d.ts","sourceRoot":"","sources":["../../../src/helpers/resolveLangSource.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAExD;;;;;;;;GAQG;AACH,eAAO,MAAM,iCAAiC,GAC5C,mBAAmB,OAAO,CAAC,YAAY,CAAC,KACvC,aAAa,GAAG,SAGJ,CAAC;AAEhB;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,qCAAqC,GAChD,eAAe,MAAM,KACpB,aAAa,GAAG,SACuC,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Collapse a duplicated `<appId>_` prefix down to one.
|
|
3
|
+
*
|
|
4
|
+
* Ported from the web SDK (src/helpers/xmppUsername.ts). Some senders stamp
|
|
5
|
+
* an already-qualified username and it gets qualified a second time, which
|
|
6
|
+
* yields `<appId>_<appId>_<userId>` — a key `usersSet` will never match.
|
|
7
|
+
*
|
|
8
|
+
* RN reads the appId off the logged-in user's own xmppUsername
|
|
9
|
+
* (`<appId>_<userId>`) since the chat store has no standalone `appId` field
|
|
10
|
+
* the way web's does.
|
|
11
|
+
*/
|
|
12
|
+
export declare const normalizeXmppUsername: (value: string | undefined | null) => string;
|
|
13
|
+
//# sourceMappingURL=xmppUsername.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"xmppUsername.d.ts","sourceRoot":"","sources":["../../../src/helpers/xmppUsername.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AACH,eAAO,MAAM,qBAAqB,GAChC,OAAO,MAAM,GAAG,SAAS,GAAG,IAAI,KAC/B,MAsBF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useChatWrapperInit.d.ts","sourceRoot":"","sources":["../../../src/hooks/useChatWrapperInit.ts"],"names":[],"mappings":"AAAA,cAAc;AAId,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"useChatWrapperInit.d.ts","sourceRoot":"","sources":["../../../src/hooks/useChatWrapperInit.ts"],"names":[],"mappings":"AAAA,cAAc;AAId,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAEzC,OAAO,UAAU,MAAM,0BAA0B,CAAC;AAgBlD,UAAU,uBAAuB;IAC/B,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACnC,eAAe,EAAE,OAAO,CAAC;IACzB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,UAAU,wBAAwB;IAChC,MAAM,EAAE,OAAO,CAAC;IAChB,UAAU,EAAE,OAAO,GAAG,SAAS,CAAC;IAChC,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IACzD,YAAY,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IAC5D,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC,CAAC;IACnE,gBAAgB,EAAE,OAAO,CAAC;CAC3B;AAED,QAAA,MAAM,kBAAkB,GAAI,uCAIzB,uBAAuB,KAAG,wBAwP5B,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"strings.d.ts","sourceRoot":"","sources":["../../../src/i18n/strings.ts"],"names":[],"mappings":"AAaA,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"strings.d.ts","sourceRoot":"","sources":["../../../src/i18n/strings.ts"],"names":[],"mappings":"AAaA,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAo9CnD,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAOzD,CAAC;AAEF,eAAO,MAAM,mBAAmB,OAAO,CAAC;AAExC,gFAAgF;AAChF,eAAO,MAAM,cAAc,GAAI,SAAS,MAAM,GAAG,IAAI,KAAG,MAIf,CAAC;AAE1C;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,GAC7B,SAAS,MAAM,GAAG,IAAI,EACtB,YAAY,aAAa,GAAG,IAAI,KAC/B,aAQF,CAAC;AAEF,6DAA6D;AAC7D,eAAO,MAAM,WAAW,GACtB,UAAU,MAAM,EAChB,OAAO,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,KACrC,MAKF,CAAC;AAEF,uDAAuD;AACvD,eAAO,MAAM,YAAY,GACvB,KAAK,MAAM,EACX,SAAS,MAAM,GAAG,IAAI,EACtB,YAAY,aAAa,GAAG,IAAI,EAChC,OAAO,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,KACrC,MAGF,CAAC"}
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* When the host doesn't set `config.i18n.locale` explicitly, this falls
|
|
14
14
|
* back to `langSource` - the same reader-language state the in-chat globe
|
|
15
15
|
* picker (LanguageSelectorButton) and `config.translates.readerLocale`
|
|
16
|
-
* drive (see
|
|
16
|
+
* drive (see ChatWrapper's resolveExternalReaderLocaleLangSource effect).
|
|
17
17
|
* So picking a language in the chat changes both message translations AND
|
|
18
18
|
* static captions together, as one language switch, unless the host is
|
|
19
19
|
* explicitly managing UI locale separately via `config.i18n.locale`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stanzaHandlers.d.ts","sourceRoot":"","sources":["../../../src/networking/stanzaHandlers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"stanzaHandlers.d.ts","sourceRoot":"","sources":["../../../src/networking/stanzaHandlers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AA4B9B,QAAA,MAAM,iBAAiB,GAAU,QAAQ,OAAO,oDA2H/C,CAAC;AAEF,QAAA,MAAM,eAAe,GAAU,QAAQ,OAAO,kBAiB7C,CAAC;AAEF,QAAA,MAAM,aAAa,GAAU,QAAQ,OAAO,kBAiB3C,CAAC;AAEF,QAAA,MAAM,gBAAgB,GAAU,QAAQ,GAAG,kBAiH1C,CAAC;AAEF,QAAA,MAAM,eAAe,GAAU,QAAQ,OAAO,EAAE,aAAa,MAAM,kBA8ClE,CAAC;AAEF,QAAA,MAAM,gBAAgB,GAAI,QAAQ,OAAO,GAAG,GAAG,SAU9C,CAAC;AAEF,QAAA,MAAM,YAAY,GAAU,QAAQ,OAAO,EAAE,QAAQ,GAAG,kBAoBvD,CAAC;AAEF,QAAA,MAAM,YAAY,GAAI,QAAQ,OAAO,SAcpC,CAAC;AAEF,QAAA,MAAM,aAAa,GAAI,QAAQ,OAAO,SAGrC,CAAC;AAEF,QAAA,MAAM,uBAAuB,GAAI,QAAQ,OAAO,EAAE,OAAO,GAAG,SAG3D,CAAC;AAEF,QAAA,MAAM,gBAAgB,GAAI,QAAQ,OAAO,EAAE,MAAM,GAAG,SAGnD,CAAC;AAEF,QAAA,MAAM,cAAc,GAAI,QAAQ,OAAO,EAAE,MAAM,GAAG,SAsDjD,CAAC;AAKF,QAAA,MAAM,cAAc,GAAI,SAAS,OAAO,EAAE,QAAQ,GAAG,SAAO,CAAC;AAC7D,QAAA,MAAM,iBAAiB,GAAI,SAAS,OAAO,SAAO,CAAC;AACnD,QAAA,MAAM,iBAAiB,GAAI,SAAS,OAAO,SAAO,CAAC;AACnD,QAAA,MAAM,YAAY,GAAI,SAAS,OAAO,SAAO,CAAC;AAE9C,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,uBAAuB,EACvB,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,YAAY,EACZ,aAAa,EACb,eAAe,EACf,aAAa,EACb,YAAY,EACZ,cAAc,EACd,iBAAiB,EACjB,iBAAiB,EACjB,YAAY,GACb,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"persistence.d.ts","sourceRoot":"","sources":["../../../src/roomStore/persistence.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAEvD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AA8B5D,eAAO,MAAM,aAAa,MAAM,CAAC;AAMjC,eAAO,MAAM,6BAA6B,MAAM,CAAC;AAEjD,UAAU,kBAAkB;IAC1B,IAAI,EAAE,IAAI,CAAC;CACZ;AAED,UAAU,mBAAmB;IAC3B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;CAE9B;AAED,UAAU,kBAAkB;IAC1B,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;CAKtD;
|
|
1
|
+
{"version":3,"file":"persistence.d.ts","sourceRoot":"","sources":["../../../src/roomStore/persistence.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAEvD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AA8B5D,eAAO,MAAM,aAAa,MAAM,CAAC;AAMjC,eAAO,MAAM,6BAA6B,MAAM,CAAC;AAEjD,UAAU,kBAAkB;IAC1B,IAAI,EAAE,IAAI,CAAC;CACZ;AAED,UAAU,mBAAmB;IAC3B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;CAE9B;AAED,UAAU,kBAAkB;IAC1B,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;CAKtD;AA4PD,wBAAgB,+BAA+B,CAC7C,OAAO,EAAE,QAAQ,EACjB,OAAO,EAAE,MAAM,GACd,oBAAoB,GAAG,IAAI,CAkC7B;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,IAAI,GAAG,SAAS,EAC/C,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,GAAG,IAAI,GAAG,SAAS,GACrE,oBAAoB,EAAE,CAaxB;AAID;;;GAGG;AACH,eAAO,MAAM,qBAAqB,EAAE,UAkDnC,CAAC;AAEF;;;;GAIG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC;IAClD,IAAI,EAAE,kBAAkB,GAAG,IAAI,CAAC;IAChC,KAAK,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAClC,IAAI,EAAE,kBAAkB,GAAG,IAAI,CAAC;CACjC,CAAC,CA6BD;AAED,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAMzD;AAED,eAAO,MAAM,YAAY;;;;CAAoC,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const ETHORA_CHAT_COMPONENT_VERSION = "
|
|
1
|
+
export declare const ETHORA_CHAT_COMPONENT_VERSION = "26.8.2";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,6BAA6B,WAAW,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ethora/chat-component-rn",
|
|
3
|
-
"version": "26.
|
|
3
|
+
"version": "26.8.2",
|
|
4
4
|
"description": "Drop-in XMPP chat component for React Native / Expo. <Chat config={...}/> and you're done.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"module": "lib/module/main.js",
|
|
@@ -135,6 +135,7 @@
|
|
|
135
135
|
"fix-prebuild-deps": "node scripts/fix-prebuild-deps.js",
|
|
136
136
|
"lint": "eslint .",
|
|
137
137
|
"test": "jest",
|
|
138
|
+
"version": "node scripts/sync-version.mjs",
|
|
138
139
|
"build": "bob build",
|
|
139
140
|
"clean": "rm -rf lib",
|
|
140
141
|
"prepack": "npm run clean && npm run build",
|
|
@@ -7,6 +7,7 @@ import { ProfileImagePlaceholder } from '../MainComponents/ProfileImagePlacehold
|
|
|
7
7
|
import { useChatSettingState } from '../../hooks/useChatSettingState';
|
|
8
8
|
import { BurgerMenuIcon } from '../../assets/icons';
|
|
9
9
|
import Button from '../styled/Button';
|
|
10
|
+
import { useT } from '../../i18n/useT';
|
|
10
11
|
|
|
11
12
|
interface HeaderRoomListProps {
|
|
12
13
|
setDrawerOpen: () => void;
|
|
@@ -14,6 +15,7 @@ interface HeaderRoomListProps {
|
|
|
14
15
|
|
|
15
16
|
export const HeaderRoomList: FC<HeaderRoomListProps> = ({ setDrawerOpen }) => {
|
|
16
17
|
const { config, user, selectedUser } = useChatSettingState();
|
|
18
|
+
const t = useT();
|
|
17
19
|
const insets = useSafeAreaInsets();
|
|
18
20
|
const topInset = config?.headerLayout?.safeAreaTop ? insets.top : 0;
|
|
19
21
|
|
|
@@ -60,7 +62,9 @@ export const HeaderRoomList: FC<HeaderRoomListProps> = ({ setDrawerOpen }) => {
|
|
|
60
62
|
{config?.headerLogo ? (
|
|
61
63
|
HeaderLogo
|
|
62
64
|
) : (
|
|
63
|
-
<Text style={{ fontWeight: 500, fontSize: 18 }}>
|
|
65
|
+
<Text style={{ fontWeight: 500, fontSize: 18 }}>
|
|
66
|
+
{t('roomList.title')}
|
|
67
|
+
</Text>
|
|
64
68
|
)}
|
|
65
69
|
</View>
|
|
66
70
|
<View style={styles.rightContainer}>
|
|
@@ -5,8 +5,13 @@ import {
|
|
|
5
5
|
setActiveModal,
|
|
6
6
|
setConfig,
|
|
7
7
|
setDeleteModal,
|
|
8
|
+
setLangSource,
|
|
8
9
|
setStoreClient,
|
|
9
10
|
} from '../../roomStore/chatSettingsSlice';
|
|
11
|
+
import {
|
|
12
|
+
resolveExternalReaderLocaleLangSource,
|
|
13
|
+
resolveLegacyTranslatesLangSource,
|
|
14
|
+
} from '../../helpers/resolveLangSource';
|
|
10
15
|
import {ChatWrapperBox} from '../styled/ChatWrapperBox';
|
|
11
16
|
import {Overlay, StyledModal} from '../styled/MediaModal';
|
|
12
17
|
import ConnectionBanner from './ConnectionBanner';
|
|
@@ -116,6 +121,26 @@ const ChatWrapper: FC<ChatWrapperProps> = ({
|
|
|
116
121
|
dispatch(setDeleteModal({isDeleteModal: false}));
|
|
117
122
|
};
|
|
118
123
|
|
|
124
|
+
// A host drives the reader's language from OUTSIDE the component through
|
|
125
|
+
// `config.translates.readerLocale` (their own switcher, or the testbed's
|
|
126
|
+
// Setup tab). Nothing was syncing it into `langSource`, so pinning it only
|
|
127
|
+
// redirected the incoming-translation lookup while the UI captions and the
|
|
128
|
+
// `<translate source>` on outgoing messages kept following the unset
|
|
129
|
+
// langSource — which is why picking a language appeared to do nothing.
|
|
130
|
+
//
|
|
131
|
+
// Its own effect, not part of init: it has to re-fire whenever the host
|
|
132
|
+
// changes the value mid-session. And it dispatches only when the value is
|
|
133
|
+
// actually set, so a host that leaves it unset never clobbers what the
|
|
134
|
+
// reader picked from the globe.
|
|
135
|
+
useEffect(() => {
|
|
136
|
+
const resolved = resolveExternalReaderLocaleLangSource(
|
|
137
|
+
config?.translates?.readerLocale
|
|
138
|
+
);
|
|
139
|
+
if (resolved) {
|
|
140
|
+
dispatch(setLangSource(resolved));
|
|
141
|
+
}
|
|
142
|
+
}, [config?.translates?.readerLocale, dispatch]);
|
|
143
|
+
|
|
119
144
|
useEffect(() => {
|
|
120
145
|
return () => {
|
|
121
146
|
if (client && user.xmppPassword === '') {
|
|
@@ -205,6 +230,14 @@ const ChatWrapper: FC<ChatWrapperProps> = ({
|
|
|
205
230
|
// Only sync config to redux if we have one — passing `undefined`
|
|
206
231
|
// wipes whatever XmppProvider already set up.
|
|
207
232
|
if (config) {dispatch(setConfig(config));}
|
|
233
|
+
// Seeds only when the host actually set the legacy single-locale
|
|
234
|
+
// field, never on mere `enabled` — see resolveLangSource.
|
|
235
|
+
const legacyLangSource = resolveLegacyTranslatesLangSource(
|
|
236
|
+
config?.translates
|
|
237
|
+
);
|
|
238
|
+
if (legacyLangSource) {
|
|
239
|
+
dispatch(setLangSource(legacyLangSource));
|
|
240
|
+
}
|
|
208
241
|
try {
|
|
209
242
|
const hasUser =
|
|
210
243
|
!!user?.defaultWallet?.walletAddress &&
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import React, {useMemo} from 'react';
|
|
2
|
-
import {Provider} from 'react-redux';
|
|
2
|
+
import {Provider, useDispatch} from 'react-redux';
|
|
3
3
|
import {KeyboardProvider} from 'react-native-keyboard-controller';
|
|
4
4
|
import {SafeAreaProvider} from 'react-native-safe-area-context';
|
|
5
5
|
import {store} from '../../roomStore';
|
|
6
|
+
import {setConfig} from '../../roomStore/chatSettingsSlice';
|
|
6
7
|
import {ConfigUser, IConfig, MessageProps} from '../../types/types';
|
|
7
8
|
import {XmppProvider} from '../../context/xmppProvider';
|
|
8
9
|
import {MessageNotificationProvider} from '../../context/MessageNotificationContext';
|
|
@@ -28,6 +29,21 @@ interface ChatWrapperProps {
|
|
|
28
29
|
isVisible?: boolean;
|
|
29
30
|
}
|
|
30
31
|
|
|
32
|
+
// Mirrors the web SDK's ConfigEnabler (ReduxWrapper.tsx): keeps redux's
|
|
33
|
+
// copy of the config in step with the prop. Without it setConfig is only
|
|
34
|
+
// dispatched during XMPP init, so a host changing config mid-session (the
|
|
35
|
+
// testbed's Setup toggles, a host flipping translates.readerLocale) kept
|
|
36
|
+
// serving a STALE config to everything that reads it from the store —
|
|
37
|
+
// which is why picking a reader language changed nothing.
|
|
38
|
+
const ConfigEnabler: React.FC<{config?: IConfig}> = ({config}) => {
|
|
39
|
+
const dispatch = useDispatch();
|
|
40
|
+
React.useEffect(() => {
|
|
41
|
+
if (!config) {return;}
|
|
42
|
+
dispatch(setConfig(config));
|
|
43
|
+
}, [config, dispatch]);
|
|
44
|
+
return null;
|
|
45
|
+
};
|
|
46
|
+
|
|
31
47
|
export const ReduxWrapper: React.FC<ChatWrapperProps> = React.memo(
|
|
32
48
|
({...props}) => {
|
|
33
49
|
const memoizedConfig = useMemo(() => {
|
|
@@ -57,6 +73,7 @@ export const ReduxWrapper: React.FC<ChatWrapperProps> = React.memo(
|
|
|
57
73
|
|
|
58
74
|
return (
|
|
59
75
|
<Provider store={store}>
|
|
76
|
+
<ConfigEnabler config={memoizedConfig} />
|
|
60
77
|
<SafeAreaProvider>
|
|
61
78
|
{ownKeyboardHandling ? (
|
|
62
79
|
<KeyboardProvider>{tree}</KeyboardProvider>
|
|
@@ -68,7 +68,6 @@ const MessageTranslate: FC<MessageTranslateProps> = ({
|
|
|
68
68
|
const attached = useMessageTranslation(message, targetLocale, true);
|
|
69
69
|
|
|
70
70
|
const [revealed, setRevealed] = useState(false);
|
|
71
|
-
const [showOriginal, setShowOriginal] = useState(false);
|
|
72
71
|
const [hostPhase, setHostPhase] = useState<HostPhase>('idle');
|
|
73
72
|
const [hostText, setHostText] = useState<string | null>(null);
|
|
74
73
|
const linkColor = config?.colors?.primary || '#0052CD';
|
|
@@ -129,20 +128,22 @@ const MessageTranslate: FC<MessageTranslateProps> = ({
|
|
|
129
128
|
</TouchableOpacity>
|
|
130
129
|
);
|
|
131
130
|
|
|
132
|
-
|
|
131
|
+
// "Show original" COLLAPSES the block — it does not swap a second copy of
|
|
132
|
+
// the original in. The bubble body directly above this link is already the
|
|
133
|
+
// original text (manual mode never translates it inline; that's auto
|
|
134
|
+
// mode's job, see Message.tsx's showInlineTranslation). Rendering
|
|
135
|
+
// `originalText` here too printed the same sentence twice, once in the
|
|
136
|
+
// body and once under the divider. Hiding the revealed block leaves
|
|
137
|
+
// exactly one original on screen, which is what the label promises.
|
|
138
|
+
const renderRevealed = (translatedText: string, onHide: () => void) => (
|
|
133
139
|
<View>
|
|
134
140
|
<CustomDivider
|
|
135
141
|
configColor={
|
|
136
142
|
isUser ? config?.colors?.secondary : config?.colors?.primary
|
|
137
143
|
}
|
|
138
144
|
/>
|
|
139
|
-
<CustomMessageText colorUser="">
|
|
140
|
-
|
|
141
|
-
</CustomMessageText>
|
|
142
|
-
{renderLink(
|
|
143
|
-
showOriginal ? t('action.translate') : t('action.showOriginal'),
|
|
144
|
-
() => setShowOriginal((v) => !v)
|
|
145
|
-
)}
|
|
145
|
+
<CustomMessageText colorUser="">{translatedText}</CustomMessageText>
|
|
146
|
+
{renderLink(t('action.showOriginal'), onHide)}
|
|
146
147
|
</View>
|
|
147
148
|
);
|
|
148
149
|
|
|
@@ -159,16 +160,20 @@ const MessageTranslate: FC<MessageTranslateProps> = ({
|
|
|
159
160
|
return renderLink(t('translation.failed'), runHostTranslate);
|
|
160
161
|
}
|
|
161
162
|
if (hostPhase === 'done' && hostText) {
|
|
162
|
-
|
|
163
|
+
// Keep hostText: re-tapping "Translate" re-reveals what we already
|
|
164
|
+
// have instead of paying for the host's translator a second time.
|
|
165
|
+
return renderRevealed(hostText, () => setHostPhase('idle'));
|
|
163
166
|
}
|
|
164
|
-
return renderLink(t('action.translate'),
|
|
167
|
+
return renderLink(t('action.translate'), () =>
|
|
168
|
+
hostText ? setHostPhase('done') : runHostTranslate()
|
|
169
|
+
);
|
|
165
170
|
}
|
|
166
171
|
|
|
167
172
|
// Stanza-attached: nothing to await, nothing to fail.
|
|
168
173
|
if (!revealed) {
|
|
169
174
|
return renderLink(t('action.translate'), () => setRevealed(true));
|
|
170
175
|
}
|
|
171
|
-
return renderRevealed(attached.displayText);
|
|
176
|
+
return renderRevealed(attached.displayText, () => setRevealed(false));
|
|
172
177
|
};
|
|
173
178
|
|
|
174
179
|
const styles = StyleSheet.create({
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
import { CameraIcon, DocumentIcon } from '../../../assets/icons';
|
|
19
19
|
import { useChatSettingState } from '../../../hooks/useChatSettingState';
|
|
20
20
|
import { chatTextStyle } from '../../../helpers/typography';
|
|
21
|
+
import { useT } from '../../../i18n/useT';
|
|
21
22
|
import { getMediaLibrary } from '../../../helpers/mediaLibraryRuntime';
|
|
22
23
|
import {
|
|
23
24
|
shouldClaimVerticalDrag,
|
|
@@ -103,6 +104,7 @@ const AttachSheet: React.FC<AttachSheetProps> = ({
|
|
|
103
104
|
}) => {
|
|
104
105
|
const { config } = useChatSettingState();
|
|
105
106
|
const ts = config?.typography?.attachSheet;
|
|
107
|
+
const t = useT();
|
|
106
108
|
const pendingRef = useRef<(() => void) | null>(null);
|
|
107
109
|
const runPending = () => {
|
|
108
110
|
const fn = pendingRef.current;
|
|
@@ -304,7 +306,7 @@ const AttachSheet: React.FC<AttachSheetProps> = ({
|
|
|
304
306
|
}[] = [
|
|
305
307
|
{
|
|
306
308
|
id: 'Document',
|
|
307
|
-
label: '
|
|
309
|
+
label: t('attach.uploadFile'),
|
|
308
310
|
Icon: DocumentIcon,
|
|
309
311
|
handler: onDocument,
|
|
310
312
|
},
|
|
@@ -350,7 +352,7 @@ const AttachSheet: React.FC<AttachSheetProps> = ({
|
|
|
350
352
|
{/* Photos & Videos ------------------------------------------------ */}
|
|
351
353
|
<View style={styles.sectionHeader}>
|
|
352
354
|
<Text style={[styles.sectionTitle, chatTextStyle(ts?.title)]}>
|
|
353
|
-
|
|
355
|
+
{t('attach.photosAndVideos')}
|
|
354
356
|
</Text>
|
|
355
357
|
<TouchableOpacity
|
|
356
358
|
testID="attach-view-library"
|
|
@@ -365,7 +367,7 @@ const AttachSheet: React.FC<AttachSheetProps> = ({
|
|
|
365
367
|
chatTextStyle(ts?.viewLibrary),
|
|
366
368
|
]}
|
|
367
369
|
>
|
|
368
|
-
|
|
370
|
+
{t('attach.viewLibrary')}
|
|
369
371
|
</Text>
|
|
370
372
|
</TouchableOpacity>
|
|
371
373
|
</View>
|
|
@@ -379,6 +381,8 @@ const AttachSheet: React.FC<AttachSheetProps> = ({
|
|
|
379
381
|
{/* Camera tile — always first, works without library access. */}
|
|
380
382
|
<TouchableOpacity
|
|
381
383
|
testID="attach-row-Camera"
|
|
384
|
+
accessibilityRole="button"
|
|
385
|
+
accessibilityLabel={t('attach.takePhoto')}
|
|
382
386
|
activeOpacity={0.7}
|
|
383
387
|
style={styles.cameraTile}
|
|
384
388
|
onPress={trigger(onCamera)}
|
|
@@ -145,8 +145,8 @@ const ChatProfileModal: React.FC<ChatProfileModalProps> = ({
|
|
|
145
145
|
const perm = await ImagePicker.requestMediaLibraryPermissionsAsync();
|
|
146
146
|
if (!perm.granted) {
|
|
147
147
|
Alert.alert(
|
|
148
|
-
'
|
|
149
|
-
'
|
|
148
|
+
t('permission.requiredTitle'),
|
|
149
|
+
t('permission.photoLibrary'),
|
|
150
150
|
[
|
|
151
151
|
{
|
|
152
152
|
text: t('action.cancel'),
|
|
@@ -154,7 +154,7 @@ const ChatProfileModal: React.FC<ChatProfileModalProps> = ({
|
|
|
154
154
|
style: 'cancel',
|
|
155
155
|
},
|
|
156
156
|
{
|
|
157
|
-
text: '
|
|
157
|
+
text: t('action.openSettings'),
|
|
158
158
|
onPress: () => Linking.openSettings(),
|
|
159
159
|
},
|
|
160
160
|
]
|
|
@@ -193,8 +193,8 @@ const ChatProfileModal: React.FC<ChatProfileModalProps> = ({
|
|
|
193
193
|
|
|
194
194
|
showToast({
|
|
195
195
|
id: Date.now().toString(),
|
|
196
|
-
title: '
|
|
197
|
-
message: '
|
|
196
|
+
title: t('toast.successTitle'),
|
|
197
|
+
message: t('toast.roomImageUpdated'),
|
|
198
198
|
type: 'success',
|
|
199
199
|
});
|
|
200
200
|
}
|
|
@@ -207,8 +207,8 @@ const ChatProfileModal: React.FC<ChatProfileModalProps> = ({
|
|
|
207
207
|
console.error('File upload failed or location is missing:', error);
|
|
208
208
|
showToast({
|
|
209
209
|
id: Date.now().toString(),
|
|
210
|
-
title: '
|
|
211
|
-
message: '
|
|
210
|
+
title: t('toast.error'),
|
|
211
|
+
message: t('toast.failedToUploadImage'),
|
|
212
212
|
type: 'error',
|
|
213
213
|
});
|
|
214
214
|
} finally {
|
|
@@ -244,16 +244,16 @@ const ChatProfileModal: React.FC<ChatProfileModalProps> = ({
|
|
|
244
244
|
|
|
245
245
|
showToast({
|
|
246
246
|
id: Date.now().toString(),
|
|
247
|
-
title: '
|
|
248
|
-
message:
|
|
247
|
+
title: t('toast.successTitle'),
|
|
248
|
+
message: t('toast.userRemovedFromRoom', { userId }),
|
|
249
249
|
type: 'success',
|
|
250
250
|
});
|
|
251
251
|
} catch (error) {
|
|
252
252
|
console.error('Failed to delete user:', error);
|
|
253
253
|
showToast({
|
|
254
254
|
id: Date.now().toString(),
|
|
255
|
-
title: '
|
|
256
|
-
message: '
|
|
255
|
+
title: t('toast.error'),
|
|
256
|
+
message: t('toast.failedToDeleteUser'),
|
|
257
257
|
type: 'error',
|
|
258
258
|
});
|
|
259
259
|
}
|
|
@@ -13,6 +13,7 @@ import { deleteRoom as deleteRoomApi } from '../../../networking/api-requests/ro
|
|
|
13
13
|
import { deleteRoom as deleteRoomAction } from '../../../roomStore/roomsSlice';
|
|
14
14
|
import { Text } from 'react-native';
|
|
15
15
|
import { useToast } from '../../../context/ToastContext';
|
|
16
|
+
import { useT } from '../../../i18n/useT';
|
|
16
17
|
|
|
17
18
|
interface DeleteChatModalProps {
|
|
18
19
|
isModalOpen: boolean;
|
|
@@ -25,6 +26,7 @@ const DeleteChatModal: React.FC<DeleteChatModalProps> = ({
|
|
|
25
26
|
}) => {
|
|
26
27
|
const dispatch = useDispatch();
|
|
27
28
|
const { showToast } = useToast();
|
|
29
|
+
const t = useT();
|
|
28
30
|
const activeRoom = useSelector((state: RootState) => getActiveRoom(state));
|
|
29
31
|
|
|
30
32
|
const handleOpenModal = () => setIsModalOpen(true);
|
|
@@ -37,16 +39,16 @@ const DeleteChatModal: React.FC<DeleteChatModalProps> = ({
|
|
|
37
39
|
handleCloseModal();
|
|
38
40
|
showToast({
|
|
39
41
|
id: Date.now().toString(),
|
|
40
|
-
title: '
|
|
41
|
-
message: '
|
|
42
|
+
title: t('toast.successTitle'),
|
|
43
|
+
message: t('toast.chatDeletedSuccess'),
|
|
42
44
|
type: 'success',
|
|
43
45
|
});
|
|
44
46
|
} catch (error) {
|
|
45
47
|
console.error('Failed to delete chat:', error);
|
|
46
48
|
showToast({
|
|
47
49
|
id: Date.now().toString(),
|
|
48
|
-
title: '
|
|
49
|
-
message: '
|
|
50
|
+
title: t('toast.error'),
|
|
51
|
+
message: t('toast.failedToDeleteChat'),
|
|
50
52
|
type: 'error',
|
|
51
53
|
});
|
|
52
54
|
}
|
|
@@ -59,19 +61,19 @@ const DeleteChatModal: React.FC<DeleteChatModalProps> = ({
|
|
|
59
61
|
<CloseButton onPress={handleCloseModal}>
|
|
60
62
|
<Text style={{ fontSize: 24 }}>×</Text>
|
|
61
63
|
</CloseButton>
|
|
62
|
-
<ModalTitle>
|
|
64
|
+
<ModalTitle>{t('modal.deleteChat.title')}</ModalTitle>
|
|
63
65
|
|
|
64
66
|
<GroupContainer>
|
|
65
67
|
<Button
|
|
66
68
|
onPress={handleCloseModal}
|
|
67
|
-
text={'
|
|
69
|
+
text={t('action.cancel')}
|
|
68
70
|
style={{ width: '100%' }}
|
|
69
71
|
unstyled
|
|
70
72
|
variant="filled"
|
|
71
73
|
/>
|
|
72
74
|
<Button
|
|
73
75
|
onPress={handleDeleteChat}
|
|
74
|
-
text={'
|
|
76
|
+
text={t('action.delete')}
|
|
75
77
|
style={{
|
|
76
78
|
width: '100%',
|
|
77
79
|
borderWidth: 1,
|
|
@@ -118,11 +118,14 @@ const NewChatModal: React.FC<NewChatModalProps> = ({
|
|
|
118
118
|
|
|
119
119
|
if (status !== 'granted') {
|
|
120
120
|
Alert.alert(
|
|
121
|
-
'
|
|
122
|
-
'
|
|
121
|
+
t('permission.requiredTitle'),
|
|
122
|
+
t('permission.photoLibrary'),
|
|
123
123
|
[
|
|
124
|
-
{ text: '
|
|
125
|
-
{
|
|
124
|
+
{ text: t('action.cancel'), style: 'cancel' },
|
|
125
|
+
{
|
|
126
|
+
text: t('action.openSettings'),
|
|
127
|
+
onPress: () => Linking.openSettings(),
|
|
128
|
+
},
|
|
126
129
|
]
|
|
127
130
|
);
|
|
128
131
|
return;
|
|
@@ -326,7 +326,12 @@ export const ProfileHero: React.FC<
|
|
|
326
326
|
>
|
|
327
327
|
{action.icon(iconColor)}
|
|
328
328
|
</View>
|
|
329
|
-
<Text
|
|
329
|
+
<Text
|
|
330
|
+
style={[styles.actionLabel, { color: contentColor }]}
|
|
331
|
+
numberOfLines={1}
|
|
332
|
+
adjustsFontSizeToFit
|
|
333
|
+
minimumFontScale={0.8}
|
|
334
|
+
>
|
|
330
335
|
{action.label}
|
|
331
336
|
</Text>
|
|
332
337
|
</TouchableOpacity>
|
|
@@ -534,9 +539,13 @@ const styles = StyleSheet.create({
|
|
|
534
539
|
marginTop: 20,
|
|
535
540
|
gap: 16,
|
|
536
541
|
},
|
|
542
|
+
// minWidth, not a fixed width: translated labels ("Rechercher",
|
|
543
|
+
// "Denunciar") don't fit 64pt and used to wrap mid-word. English labels
|
|
544
|
+
// are shorter than 64pt, so their layout is unchanged.
|
|
537
545
|
action: {
|
|
538
546
|
alignItems: 'center',
|
|
539
|
-
|
|
547
|
+
minWidth: 64,
|
|
548
|
+
maxWidth: 96,
|
|
540
549
|
},
|
|
541
550
|
actionCircle: {
|
|
542
551
|
width: 56,
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import React, { useMemo } from 'react';
|
|
1
|
+
import React, { useCallback, useMemo } from 'react';
|
|
2
|
+
import { useSelector } from 'react-redux';
|
|
3
|
+
import { RootState } from '../../roomStore';
|
|
4
|
+
import { IMessage } from '../../types/types';
|
|
2
5
|
import { useFileToken } from '../../hooks/useFileToken';
|
|
3
6
|
import { appendFileToken } from '../../helpers/secureFileUrl';
|
|
4
7
|
import { IConfig, IRoom } from '../../types/types';
|
|
@@ -32,17 +35,58 @@ const ChatRoomItem: React.FC<ChatRoomItemProps> = ({
|
|
|
32
35
|
const fileToken = useFileToken();
|
|
33
36
|
const displayName = String(chat?.title || chat?.name || '').trim();
|
|
34
37
|
|
|
38
|
+
// usersSet is the canonical name store — the same one Message.tsx
|
|
39
|
+
// resolves sender names through. The preview must go through it too
|
|
40
|
+
// (mirrors web's ChatRoomItem.withAuthorFallback): a message restored
|
|
41
|
+
// from the persist cache carries only a compacted user, so reading
|
|
42
|
+
// `user.name` alone left this line showing a raw JID after a refresh.
|
|
43
|
+
const usersSet = useSelector((state: RootState) => state.rooms.usersSet) as
|
|
44
|
+
| Record<string, any>
|
|
45
|
+
| undefined;
|
|
46
|
+
|
|
47
|
+
const withAuthorFallback = useCallback(
|
|
48
|
+
(message?: IMessage): IMessage | undefined => {
|
|
49
|
+
if (!message) {return message;}
|
|
50
|
+
const rawUserId = String(message?.user?.id || '');
|
|
51
|
+
const localId = rawUserId.split('@')[0];
|
|
52
|
+
const entry = usersSet?.[localId] ?? usersSet?.[rawUserId];
|
|
53
|
+
const fromUsersSet = entry
|
|
54
|
+
? `${entry.firstName ?? ''} ${entry.lastName ?? ''}`.trim()
|
|
55
|
+
: '';
|
|
56
|
+
|
|
57
|
+
// usersSet first, exactly like Message.tsx: it's the live store, so
|
|
58
|
+
// a renamed user updates here too. The message's own `name` is the
|
|
59
|
+
// fallback that carries broadcast/system senders ("Ethora"), which
|
|
60
|
+
// never appear in usersSet.
|
|
61
|
+
const safeName =
|
|
62
|
+
fromUsersSet ||
|
|
63
|
+
String(message?.user?.name || '').trim() ||
|
|
64
|
+
localId ||
|
|
65
|
+
rawUserId ||
|
|
66
|
+
'Unknown';
|
|
67
|
+
|
|
68
|
+
return {
|
|
69
|
+
...message,
|
|
70
|
+
user: {
|
|
71
|
+
...message.user,
|
|
72
|
+
name: safeName,
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
},
|
|
76
|
+
[usersSet]
|
|
77
|
+
);
|
|
78
|
+
|
|
35
79
|
const lastMessage = useMemo(() => {
|
|
36
80
|
if (!chat?.messages || chat.messages.length === 0) {return undefined;}
|
|
37
81
|
|
|
38
82
|
for (let i = chat.messages.length - 1; i >= 0; i--) {
|
|
39
83
|
const msg = chat.messages[i];
|
|
40
84
|
if (!msg.deleted && !msg.isDeleted) {
|
|
41
|
-
return msg;
|
|
85
|
+
return withAuthorFallback(msg);
|
|
42
86
|
}
|
|
43
87
|
}
|
|
44
88
|
return undefined;
|
|
45
|
-
}, [chat?.messages]);
|
|
89
|
+
}, [chat?.messages, withAuthorFallback]);
|
|
46
90
|
|
|
47
91
|
// Mirrors web's formatter: tolerates undefined/garbage inputs (returns
|
|
48
92
|
// undefined instead of "NaN:NaN"), and uses HH:MM today / MM/DD this
|