@developer_tribe/react-native-comnyx 0.3.10 → 0.3.12
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/App.js +6 -2
- package/lib/commonjs/App.js.map +1 -1
- package/lib/commonjs/components/AppText.js +11 -1
- package/lib/commonjs/components/AppText.js.map +1 -1
- package/lib/commonjs/components/ChatList.js +67 -55
- package/lib/commonjs/components/ChatList.js.map +1 -1
- package/lib/commonjs/components/CustomerForm.js +13 -13
- package/lib/commonjs/components/CustomerForm.js.map +1 -1
- package/lib/commonjs/components/MessageItem.js +2 -1
- package/lib/commonjs/components/MessageItem.js.map +1 -1
- package/lib/commonjs/constants/translations.js +15 -15
- package/lib/commonjs/constants/translations.js.map +1 -1
- package/lib/commonjs/hooks/useTheme.js +12 -0
- package/lib/commonjs/hooks/useTheme.js.map +1 -0
- package/lib/commonjs/store.js +6 -0
- package/lib/commonjs/store.js.map +1 -1
- package/lib/commonjs/types/GlobalTheme.js +6 -0
- package/lib/commonjs/types/GlobalTheme.js.map +1 -0
- package/lib/module/App.js +6 -2
- package/lib/module/App.js.map +1 -1
- package/lib/module/components/AppText.js +11 -1
- package/lib/module/components/AppText.js.map +1 -1
- package/lib/module/components/ChatList.js +67 -55
- package/lib/module/components/ChatList.js.map +1 -1
- package/lib/module/components/CustomerForm.js +13 -13
- package/lib/module/components/CustomerForm.js.map +1 -1
- package/lib/module/components/MessageItem.js +2 -1
- package/lib/module/components/MessageItem.js.map +1 -1
- package/lib/module/constants/translations.js +15 -15
- package/lib/module/constants/translations.js.map +1 -1
- package/lib/module/hooks/useTheme.js +8 -0
- package/lib/module/hooks/useTheme.js.map +1 -0
- package/lib/module/store.js +6 -0
- package/lib/module/store.js.map +1 -1
- package/lib/module/types/GlobalTheme.js +4 -0
- package/lib/module/types/GlobalTheme.js.map +1 -0
- package/lib/typescript/commonjs/src/App.d.ts +2 -1
- package/lib/typescript/commonjs/src/App.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/components/AppText.d.ts +5 -1
- package/lib/typescript/commonjs/src/components/AppText.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/components/ChatList.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/constants/translations.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/hooks/useTheme.d.ts +3 -0
- package/lib/typescript/commonjs/src/hooks/useTheme.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/store.d.ts +2 -0
- package/lib/typescript/commonjs/src/store.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/types/GlobalTheme.d.ts +6 -0
- package/lib/typescript/commonjs/src/types/GlobalTheme.d.ts.map +1 -0
- package/lib/typescript/module/src/App.d.ts +2 -1
- package/lib/typescript/module/src/App.d.ts.map +1 -1
- package/lib/typescript/module/src/components/AppText.d.ts +5 -1
- package/lib/typescript/module/src/components/AppText.d.ts.map +1 -1
- package/lib/typescript/module/src/components/ChatList.d.ts.map +1 -1
- package/lib/typescript/module/src/constants/translations.d.ts.map +1 -1
- package/lib/typescript/module/src/hooks/useTheme.d.ts +3 -0
- package/lib/typescript/module/src/hooks/useTheme.d.ts.map +1 -0
- package/lib/typescript/module/src/store.d.ts +2 -0
- package/lib/typescript/module/src/store.d.ts.map +1 -1
- package/lib/typescript/module/src/types/GlobalTheme.d.ts +6 -0
- package/lib/typescript/module/src/types/GlobalTheme.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/App.tsx +6 -1
- package/src/components/AppText.tsx +39 -1
- package/src/components/ChatList.tsx +90 -70
- package/src/components/CustomerForm.tsx +14 -14
- package/src/components/MessageItem.tsx +1 -0
- package/src/constants/translations.ts +15 -24
- package/src/hooks/useTheme.ts +7 -0
- package/src/store.ts +6 -0
- package/src/types/GlobalTheme.tsx +7 -0
|
@@ -4,7 +4,8 @@ interface ComnyxProps {
|
|
|
4
4
|
theme?: 'light' | 'dark';
|
|
5
5
|
fake?: boolean;
|
|
6
6
|
onBack: () => void;
|
|
7
|
+
themes?: any;
|
|
7
8
|
}
|
|
8
|
-
export declare function Comnyx({ language, theme, fake, onBack, }: ComnyxProps): import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
export declare function Comnyx({ language, theme, fake, onBack, themes, }: ComnyxProps): import("react/jsx-runtime").JSX.Element;
|
|
9
10
|
export {};
|
|
10
11
|
//# sourceMappingURL=App.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../../../src/App.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAMrD,UAAU,WAAW;IACnB,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IACzB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../../../src/App.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAMrD,UAAU,WAAW;IACnB,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IACzB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,MAAM,CAAC,EAAE,GAAG,CAAC;CACd;AAED,wBAAgB,MAAM,CAAC,EACrB,QAAe,EACf,KAAc,EACd,IAAY,EACZ,MAAM,EACN,MAAM,GACP,EAAE,WAAW,2CAmCb"}
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
2
|
import type { TextProps } from 'react-native';
|
|
3
3
|
import type { LocalizationKeys } from '../types/LocalizationKeys';
|
|
4
|
+
export type FamilyWeight = Record<Weight, string | undefined>;
|
|
5
|
+
export type Weight = 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900';
|
|
4
6
|
interface AppTextProps extends Omit<TextProps, 'children'> {
|
|
5
7
|
localization?: keyof LocalizationKeys;
|
|
6
8
|
children?: React.ReactNode;
|
|
9
|
+
family?: Partial<FamilyWeight>;
|
|
10
|
+
weight?: Weight;
|
|
7
11
|
}
|
|
8
|
-
export declare function AppText({ style, localization, children, ...props }: AppTextProps): import("react/jsx-runtime").JSX.Element | null;
|
|
12
|
+
export declare function AppText({ style, localization, children, family, weight, ...props }: AppTextProps): import("react/jsx-runtime").JSX.Element | null;
|
|
9
13
|
export {};
|
|
10
14
|
//# sourceMappingURL=AppText.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AppText.d.ts","sourceRoot":"","sources":["../../../../../src/components/AppText.tsx"],"names":[],"mappings":";AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAI9C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"AppText.d.ts","sourceRoot":"","sources":["../../../../../src/components/AppText.tsx"],"names":[],"mappings":";AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAI9C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAGlE,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;AAE9D,MAAM,MAAM,MAAM,GACd,QAAQ,GACR,MAAM,GACN,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,CAAC;AAEV,UAAU,YAAa,SAAQ,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC;IACxD,YAAY,CAAC,EAAE,MAAM,gBAAgB,CAAC;IACtC,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,MAAM,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,OAAO,CAAC,EACtB,KAAK,EACL,YAAY,EACZ,QAAQ,EACR,MAAM,EACN,MAAc,EACd,GAAG,KAAK,EACT,EAAE,YAAY,kDA2Cd"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatList.d.ts","sourceRoot":"","sources":["../../../../../src/components/ChatList.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ChatList.d.ts","sourceRoot":"","sources":["../../../../../src/components/ChatList.tsx"],"names":[],"mappings":"AAwCA,wBAAgB,QAAQ,CAAC,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;CAAE,2CAwnB3D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"translations.d.ts","sourceRoot":"","sources":["../../../../../src/constants/translations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,YAAY,EAAE,gBAAgB,
|
|
1
|
+
{"version":3,"file":"translations.d.ts","sourceRoot":"","sources":["../../../../../src/constants/translations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,YAAY,EAAE,gBAAgB,CAwd1D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useTheme.d.ts","sourceRoot":"","sources":["../../../../../src/hooks/useTheme.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAExD,wBAAgB,cAAc,IAAI,QAAQ,CAAC,WAAW,CAAC,CAGtD"}
|
|
@@ -11,6 +11,7 @@ interface AppStoreState {
|
|
|
11
11
|
language: LanguageCode;
|
|
12
12
|
theme: 'light' | 'dark';
|
|
13
13
|
fake: boolean;
|
|
14
|
+
themes: any;
|
|
14
15
|
firstMessage: AppConversationMessage | null;
|
|
15
16
|
setData: (cb: (prevData: AppConversationMessage[] | null) => AppConversationMessage[] | null) => void;
|
|
16
17
|
setFirstMessage: (message: AppConversationMessage | null) => void;
|
|
@@ -21,6 +22,7 @@ interface AppStoreState {
|
|
|
21
22
|
setLanguage: (language: LanguageCode) => void;
|
|
22
23
|
setTheme: (theme: 'light' | 'dark') => void;
|
|
23
24
|
setFake: (fake: boolean) => void;
|
|
25
|
+
setThemes: (themes: any) => void;
|
|
24
26
|
updateBaseDimensions: (config: {
|
|
25
27
|
baseHeight: number;
|
|
26
28
|
baseWidth: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../../src/store.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAErD,UAAU,aAAa;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC1B,IAAI,EAAE,sBAAsB,EAAE,GAAG,IAAI,CAAC;IACtC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,YAAY,CAAC;IACvB,KAAK,EAAE,OAAO,GAAG,MAAM,CAAC;IACxB,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,sBAAsB,GAAG,IAAI,CAAC;IAC5C,OAAO,EAAE,CACP,EAAE,EAAE,CACF,QAAQ,EAAE,sBAAsB,EAAE,GAAG,IAAI,KACtC,sBAAsB,EAAE,GAAG,IAAI,KACjC,IAAI,CAAC;IACV,eAAe,EAAE,CAAC,OAAO,EAAE,sBAAsB,GAAG,IAAI,KAAK,IAAI,CAAC;IAClE,IAAI,EAAE,CAAC,EAAE,UAAU,EAAE,EAAE;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACvD,QAAQ,EAAE,CAAC,sBAAsB,EAAE,QAAQ,KAAK,IAAI,CAAC;IACrD,WAAW,EAAE,CAAC,QAAQ,EAAE,YAAY,KAAK,IAAI,CAAC;IAC9C,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,KAAK,IAAI,CAAC;IAC5C,OAAO,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACjC,oBAAoB,EAAE,CAAC,MAAM,EAAE;QAC7B,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;KACnB,KAAK,IAAI,CAAC;CACZ;
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../../src/store.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAErD,UAAU,aAAa;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC1B,IAAI,EAAE,sBAAsB,EAAE,GAAG,IAAI,CAAC;IACtC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,YAAY,CAAC;IACvB,KAAK,EAAE,OAAO,GAAG,MAAM,CAAC;IACxB,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,GAAG,CAAC;IACZ,YAAY,EAAE,sBAAsB,GAAG,IAAI,CAAC;IAC5C,OAAO,EAAE,CACP,EAAE,EAAE,CACF,QAAQ,EAAE,sBAAsB,EAAE,GAAG,IAAI,KACtC,sBAAsB,EAAE,GAAG,IAAI,KACjC,IAAI,CAAC;IACV,eAAe,EAAE,CAAC,OAAO,EAAE,sBAAsB,GAAG,IAAI,KAAK,IAAI,CAAC;IAClE,IAAI,EAAE,CAAC,EAAE,UAAU,EAAE,EAAE;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACvD,QAAQ,EAAE,CAAC,sBAAsB,EAAE,QAAQ,KAAK,IAAI,CAAC;IACrD,WAAW,EAAE,CAAC,QAAQ,EAAE,YAAY,KAAK,IAAI,CAAC;IAC9C,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,KAAK,IAAI,CAAC;IAC5C,OAAO,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACjC,SAAS,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;IACjC,oBAAoB,EAAE,CAAC,MAAM,EAAE;QAC7B,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;KACnB,KAAK,IAAI,CAAC;CACZ;AA4CD,eAAO,MAAM,WAAW;;;;;;;;;;EAmBvB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GlobalTheme.d.ts","sourceRoot":"","sources":["../../../../../src/types/GlobalTheme.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAE1D,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;CAClD,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG,iBAAiB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@developer_tribe/react-native-comnyx",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.12",
|
|
4
4
|
"description": "React Native chat component with integrated support panel, enabling real-time customer communication and efficient agent workflow management.",
|
|
5
5
|
"source": "./src/index.tsx",
|
|
6
6
|
"main": "./lib/commonjs/index.js",
|
package/src/App.tsx
CHANGED
|
@@ -13,6 +13,7 @@ interface ComnyxProps {
|
|
|
13
13
|
theme?: 'light' | 'dark';
|
|
14
14
|
fake?: boolean;
|
|
15
15
|
onBack: () => void;
|
|
16
|
+
themes?: any;
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
export function Comnyx({
|
|
@@ -20,6 +21,7 @@ export function Comnyx({
|
|
|
20
21
|
theme = 'dark',
|
|
21
22
|
fake = false,
|
|
22
23
|
onBack,
|
|
24
|
+
themes,
|
|
23
25
|
}: ComnyxProps) {
|
|
24
26
|
const { initialized, customer } = useAppStore((s) => ({
|
|
25
27
|
initialized: s.initialized,
|
|
@@ -31,7 +33,10 @@ export function Comnyx({
|
|
|
31
33
|
useAppStore.getState().setLanguage(language);
|
|
32
34
|
useAppStore.getState().setTheme(theme);
|
|
33
35
|
useAppStore.getState().setFake(fake);
|
|
34
|
-
|
|
36
|
+
if (themes) {
|
|
37
|
+
useAppStore.getState().setThemes(themes);
|
|
38
|
+
}
|
|
39
|
+
}, [language, theme, fake, themes]);
|
|
35
40
|
|
|
36
41
|
if (!initialized) {
|
|
37
42
|
return (
|
|
@@ -4,19 +4,41 @@ import { LocalizationList } from '../constants/translations';
|
|
|
4
4
|
import { useAppStore } from '../store';
|
|
5
5
|
import { useThemeColors } from '../hooks/useThemeColors';
|
|
6
6
|
import type { LocalizationKeys } from '../types/LocalizationKeys';
|
|
7
|
+
import { useGlobalTheme } from '../hooks/useTheme';
|
|
8
|
+
|
|
9
|
+
export type FamilyWeight = Record<Weight, string | undefined>;
|
|
10
|
+
|
|
11
|
+
export type Weight =
|
|
12
|
+
| 'normal'
|
|
13
|
+
| 'bold'
|
|
14
|
+
| '100'
|
|
15
|
+
| '200'
|
|
16
|
+
| '300'
|
|
17
|
+
| '400'
|
|
18
|
+
| '500'
|
|
19
|
+
| '600'
|
|
20
|
+
| '700'
|
|
21
|
+
| '800'
|
|
22
|
+
| '900';
|
|
7
23
|
|
|
8
24
|
interface AppTextProps extends Omit<TextProps, 'children'> {
|
|
9
25
|
localization?: keyof LocalizationKeys;
|
|
10
26
|
children?: React.ReactNode;
|
|
27
|
+
family?: Partial<FamilyWeight>;
|
|
28
|
+
weight?: Weight;
|
|
11
29
|
}
|
|
12
30
|
|
|
13
31
|
export function AppText({
|
|
14
32
|
style,
|
|
15
33
|
localization,
|
|
16
34
|
children,
|
|
35
|
+
family,
|
|
36
|
+
weight = '400',
|
|
17
37
|
...props
|
|
18
38
|
}: AppTextProps) {
|
|
19
39
|
const themeColors = useThemeColors();
|
|
40
|
+
const theme = useGlobalTheme();
|
|
41
|
+
|
|
20
42
|
const { language } = useAppStore((s) => ({
|
|
21
43
|
language: s.language,
|
|
22
44
|
}));
|
|
@@ -35,8 +57,24 @@ export function AppText({
|
|
|
35
57
|
return null;
|
|
36
58
|
}
|
|
37
59
|
|
|
60
|
+
if (!family && theme.family && language) {
|
|
61
|
+
family = theme.family(language);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const fontFamily = family?.[weight ?? '400'];
|
|
65
|
+
|
|
38
66
|
return (
|
|
39
|
-
<Text
|
|
67
|
+
<Text
|
|
68
|
+
style={[
|
|
69
|
+
{
|
|
70
|
+
color: themeColors.text,
|
|
71
|
+
fontFamily,
|
|
72
|
+
fontWeight: fontFamily ? undefined : weight || '400',
|
|
73
|
+
},
|
|
74
|
+
style,
|
|
75
|
+
]}
|
|
76
|
+
{...props}
|
|
77
|
+
>
|
|
40
78
|
{content}
|
|
41
79
|
</Text>
|
|
42
80
|
);
|
|
@@ -22,7 +22,6 @@ import CustomPopup from './CustomAlert';
|
|
|
22
22
|
import type { LocalizationKeys } from '../types/LocalizationKeys';
|
|
23
23
|
import { ScaledSheet } from './ScaledSheet';
|
|
24
24
|
import { formatDate } from '../utils/formatDate';
|
|
25
|
-
import { viewabilityConfig } from '../viewabilityConfig';
|
|
26
25
|
import { activeOpacity } from '../constants/activeOpacity';
|
|
27
26
|
|
|
28
27
|
const headphonesIcon = require('../assets/headphones-01.png');
|
|
@@ -64,6 +63,9 @@ export function ChatList({ onBack }: { onBack?: () => void }) {
|
|
|
64
63
|
const [popupVisible, setPopupVisible] = useState(false);
|
|
65
64
|
const [selectedMessage, setSelectedMessage] = useState<string>('');
|
|
66
65
|
const [currentSection, setCurrentSection] = useState<string>('');
|
|
66
|
+
const lastSectionChangeTime = useRef<number>(0);
|
|
67
|
+
const pendingSectionRef = useRef<string | null>(null);
|
|
68
|
+
const MIN_SECTION_CHANGE_INTERVAL = 150;
|
|
67
69
|
|
|
68
70
|
const sections = useMemo(() => {
|
|
69
71
|
if (!data || data.length === 0) return [];
|
|
@@ -297,32 +299,41 @@ export function ChatList({ onBack }: { onBack?: () => void }) {
|
|
|
297
299
|
[]
|
|
298
300
|
);
|
|
299
301
|
|
|
300
|
-
const
|
|
301
|
-
(
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
302
|
+
const updateSectionSafely = useCallback(
|
|
303
|
+
(newSection: string) => {
|
|
304
|
+
const now = Date.now();
|
|
305
|
+
const timeSinceLastChange = now - lastSectionChangeTime.current;
|
|
306
|
+
|
|
307
|
+
// If this is a different section than current and pending
|
|
308
|
+
if (
|
|
309
|
+
newSection !== currentSection &&
|
|
310
|
+
newSection !== pendingSectionRef.current
|
|
311
|
+
) {
|
|
312
|
+
// If we recently changed the section, queue this change
|
|
313
|
+
if (timeSinceLastChange < MIN_SECTION_CHANGE_INTERVAL) {
|
|
314
|
+
// Store the pending section
|
|
315
|
+
pendingSectionRef.current = newSection;
|
|
316
|
+
|
|
317
|
+
// Schedule an update after the minimum interval has passed
|
|
318
|
+
setTimeout(() => {
|
|
319
|
+
// Only update if pending section hasn't changed again
|
|
320
|
+
if (pendingSectionRef.current === newSection) {
|
|
321
|
+
setCurrentSection(newSection);
|
|
322
|
+
lastSectionChangeTime.current = Date.now();
|
|
323
|
+
pendingSectionRef.current = null;
|
|
310
324
|
}
|
|
311
|
-
}
|
|
325
|
+
}, MIN_SECTION_CHANGE_INTERVAL - timeSinceLastChange);
|
|
326
|
+
} else {
|
|
327
|
+
// Enough time has passed, update immediately
|
|
328
|
+
setCurrentSection(newSection);
|
|
329
|
+
lastSectionChangeTime.current = now;
|
|
330
|
+
pendingSectionRef.current = null;
|
|
312
331
|
}
|
|
313
332
|
}
|
|
314
333
|
},
|
|
315
334
|
[currentSection]
|
|
316
335
|
);
|
|
317
336
|
|
|
318
|
-
const viewabilityConfigCallbackPairs = useRef([
|
|
319
|
-
{
|
|
320
|
-
viewabilityConfig,
|
|
321
|
-
onViewableItemsChanged: handleViewabilityChange,
|
|
322
|
-
},
|
|
323
|
-
]);
|
|
324
|
-
|
|
325
|
-
// We'll use onScroll instead of onMomentumScrollEnd for more responsive updates
|
|
326
337
|
const handleScroll = useCallback(
|
|
327
338
|
(event: any) => {
|
|
328
339
|
const currentScrollY = event.nativeEvent.contentOffset.y;
|
|
@@ -331,60 +342,65 @@ export function ChatList({ onBack }: { onBack?: () => void }) {
|
|
|
331
342
|
|
|
332
343
|
setIsScrollingUp(currentScrollY > 300);
|
|
333
344
|
|
|
334
|
-
//
|
|
335
|
-
if (sections && sections.length > 0
|
|
336
|
-
|
|
337
|
-
let
|
|
338
|
-
let maxVisibility = 0;
|
|
345
|
+
// Determine the section at the bottom of the window based on scroll position
|
|
346
|
+
if (sections && sections.length > 0) {
|
|
347
|
+
let accumulatedHeight = 0;
|
|
348
|
+
let lastVisibleSection = null;
|
|
339
349
|
|
|
340
|
-
//
|
|
350
|
+
// Check all sections
|
|
341
351
|
for (let i = 0; i < sections.length; i++) {
|
|
342
352
|
const section = sections[i];
|
|
343
353
|
if (!section || !section.data) continue;
|
|
344
354
|
|
|
345
|
-
|
|
346
|
-
const
|
|
347
|
-
|
|
348
|
-
//
|
|
349
|
-
const
|
|
350
|
-
const
|
|
351
|
-
|
|
352
|
-
//
|
|
353
|
-
const visibleTop =
|
|
354
|
-
const visibleBottom =
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
if (
|
|
362
|
-
|
|
363
|
-
visibleSectionIndex = i;
|
|
355
|
+
// Calculate section height
|
|
356
|
+
const sectionHeight = section.data.length * (MESSAGE_MIN_HEIGHT + 10);
|
|
357
|
+
|
|
358
|
+
// Section positions
|
|
359
|
+
const sectionStart = accumulatedHeight;
|
|
360
|
+
const sectionEnd = sectionStart + sectionHeight;
|
|
361
|
+
|
|
362
|
+
// Visible area
|
|
363
|
+
const visibleTop = currentScrollY;
|
|
364
|
+
const visibleBottom = visibleTop + scrollViewHeight;
|
|
365
|
+
|
|
366
|
+
// Find the section visible at the bottom of the screen
|
|
367
|
+
const isSectionVisibleAtBottom =
|
|
368
|
+
(visibleBottom >= sectionStart && visibleBottom <= sectionEnd) ||
|
|
369
|
+
(sectionStart <= visibleTop && sectionEnd >= visibleBottom);
|
|
370
|
+
|
|
371
|
+
if (isSectionVisibleAtBottom) {
|
|
372
|
+
lastVisibleSection = section;
|
|
364
373
|
}
|
|
374
|
+
|
|
375
|
+
accumulatedHeight += sectionHeight;
|
|
365
376
|
}
|
|
366
377
|
|
|
367
|
-
//
|
|
368
|
-
if (
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
378
|
+
// Display the found section using our safe updater
|
|
379
|
+
if (
|
|
380
|
+
lastVisibleSection?.title &&
|
|
381
|
+
lastVisibleSection.title !== currentSection
|
|
382
|
+
) {
|
|
383
|
+
updateSectionSafely(lastVisibleSection.title);
|
|
384
|
+
} else if (
|
|
385
|
+
!lastVisibleSection &&
|
|
386
|
+
currentScrollY <= 10 &&
|
|
387
|
+
sections[0]?.title
|
|
388
|
+
) {
|
|
389
|
+
updateSectionSafely(sections[0].title);
|
|
379
390
|
}
|
|
380
391
|
}
|
|
381
392
|
|
|
382
|
-
// Check if we need to load more data
|
|
383
393
|
if (currentScrollY >= contentHeight - scrollViewHeight - 200) {
|
|
384
394
|
nextPage();
|
|
385
395
|
}
|
|
386
396
|
},
|
|
387
|
-
[
|
|
397
|
+
[
|
|
398
|
+
nextPage,
|
|
399
|
+
sections,
|
|
400
|
+
currentSection,
|
|
401
|
+
MESSAGE_MIN_HEIGHT,
|
|
402
|
+
updateSectionSafely,
|
|
403
|
+
]
|
|
388
404
|
);
|
|
389
405
|
|
|
390
406
|
const scrollToBottom = useCallback(
|
|
@@ -483,6 +499,13 @@ export function ChatList({ onBack }: { onBack?: () => void }) {
|
|
|
483
499
|
};
|
|
484
500
|
}, []);
|
|
485
501
|
|
|
502
|
+
// Clear pending updates on unmount
|
|
503
|
+
useEffect(() => {
|
|
504
|
+
return () => {
|
|
505
|
+
pendingSectionRef.current = null;
|
|
506
|
+
};
|
|
507
|
+
}, []);
|
|
508
|
+
|
|
486
509
|
if (nexPageFailed) {
|
|
487
510
|
return (
|
|
488
511
|
<View
|
|
@@ -570,7 +593,7 @@ export function ChatList({ onBack }: { onBack?: () => void }) {
|
|
|
570
593
|
<View style={styles.listContainer}>
|
|
571
594
|
<AppText
|
|
572
595
|
style={[
|
|
573
|
-
styles.
|
|
596
|
+
styles.dateText,
|
|
574
597
|
{ color: themeColors.slate, backgroundColor: themeColors.ghost },
|
|
575
598
|
]}
|
|
576
599
|
>
|
|
@@ -596,8 +619,8 @@ export function ChatList({ onBack }: { onBack?: () => void }) {
|
|
|
596
619
|
keyExtractor={(item: AppConversationMessage) =>
|
|
597
620
|
item.id + '-' + item.created_at
|
|
598
621
|
}
|
|
599
|
-
removeClippedSubviews={
|
|
600
|
-
maxToRenderPerBatch={
|
|
622
|
+
removeClippedSubviews={false}
|
|
623
|
+
maxToRenderPerBatch={20}
|
|
601
624
|
windowSize={21}
|
|
602
625
|
initialNumToRender={MESSAGES_PER_PAGE}
|
|
603
626
|
getItemLayout={(_: any, index: number) => ({
|
|
@@ -606,10 +629,7 @@ export function ChatList({ onBack }: { onBack?: () => void }) {
|
|
|
606
629
|
index,
|
|
607
630
|
})}
|
|
608
631
|
onScroll={handleScroll}
|
|
609
|
-
scrollEventThrottle={
|
|
610
|
-
viewabilityConfigCallbackPairs={
|
|
611
|
-
viewabilityConfigCallbackPairs.current
|
|
612
|
-
}
|
|
632
|
+
scrollEventThrottle={1}
|
|
613
633
|
stickySectionHeadersEnabled={false}
|
|
614
634
|
/>
|
|
615
635
|
</View>
|
|
@@ -762,12 +782,12 @@ const styles = ScaledSheet.create({
|
|
|
762
782
|
alignSelf: 'center',
|
|
763
783
|
marginVertical: '8@vs',
|
|
764
784
|
},
|
|
765
|
-
|
|
785
|
+
dateText: {
|
|
766
786
|
fontSize: '14@vs',
|
|
767
787
|
fontWeight: '500',
|
|
768
|
-
borderRadius: '
|
|
769
|
-
paddingHorizontal: '
|
|
770
|
-
paddingVertical: '
|
|
788
|
+
borderRadius: '12@s',
|
|
789
|
+
paddingHorizontal: '8@s',
|
|
790
|
+
paddingVertical: '2@s',
|
|
771
791
|
position: 'absolute',
|
|
772
792
|
top: '10@vs',
|
|
773
793
|
zIndex: 10,
|
|
@@ -106,7 +106,7 @@ export function CustomerForm({ onBack }: { onBack: () => void }) {
|
|
|
106
106
|
<TouchableOpacity
|
|
107
107
|
style={[styles.container, { backgroundColor: themeColors.background }]}
|
|
108
108
|
onPress={Keyboard.dismiss}
|
|
109
|
-
activeOpacity={
|
|
109
|
+
activeOpacity={1}
|
|
110
110
|
>
|
|
111
111
|
<ScrollView
|
|
112
112
|
contentContainerStyle={styles.scrollContainer}
|
|
@@ -284,21 +284,21 @@ export function CustomerForm({ onBack }: { onBack: () => void }) {
|
|
|
284
284
|
name="phone"
|
|
285
285
|
/>
|
|
286
286
|
</View>
|
|
287
|
-
<TouchableOpacity
|
|
288
|
-
activeOpacity={activeOpacity}
|
|
289
|
-
style={[
|
|
290
|
-
styles.button,
|
|
291
|
-
{ backgroundColor: themeColors.dark_background },
|
|
292
|
-
]}
|
|
293
|
-
onPress={handleSubmit(onSubmit)}
|
|
294
|
-
>
|
|
295
|
-
<AppText
|
|
296
|
-
localization="customer.form.submit"
|
|
297
|
-
style={[styles.buttonText, { color: themeColors.light_text }]}
|
|
298
|
-
/>
|
|
299
|
-
</TouchableOpacity>
|
|
300
287
|
</View>
|
|
301
288
|
</ScrollView>
|
|
289
|
+
<TouchableOpacity
|
|
290
|
+
activeOpacity={activeOpacity}
|
|
291
|
+
style={[
|
|
292
|
+
styles.button,
|
|
293
|
+
{ backgroundColor: themeColors.dark_background },
|
|
294
|
+
]}
|
|
295
|
+
onPress={handleSubmit(onSubmit)}
|
|
296
|
+
>
|
|
297
|
+
<AppText
|
|
298
|
+
localization="customer.form.submit"
|
|
299
|
+
style={[styles.buttonText, { color: themeColors.light_text }]}
|
|
300
|
+
/>
|
|
301
|
+
</TouchableOpacity>
|
|
302
302
|
<CustomPopup
|
|
303
303
|
isVisible={popupVisible}
|
|
304
304
|
onClose={() => setPopupVisible(false)}
|
|
@@ -10,8 +10,7 @@ export const LocalizationList: Record<LanguageCode, LocalizationKeys> = {
|
|
|
10
10
|
'customer.form.country': 'Country',
|
|
11
11
|
'customer.form.submit': 'Contact Now',
|
|
12
12
|
'customer.form.error': 'Please fill in all required fields',
|
|
13
|
-
'customer.form.instructions':
|
|
14
|
-
'Complete the form below to receive personalized service',
|
|
13
|
+
'customer.form.instructions': 'How Can We Help You?',
|
|
15
14
|
'customer.form.error.country': 'Country is required',
|
|
16
15
|
'customer.form.error.email': 'Valid email is required',
|
|
17
16
|
'customer.form.error.phone': 'Phone is required',
|
|
@@ -57,9 +56,8 @@ export const LocalizationList: Record<LanguageCode, LocalizationKeys> = {
|
|
|
57
56
|
'customer.form.country': 'Ülke',
|
|
58
57
|
'customer.form.submit': 'Şimdi İletişime Geç',
|
|
59
58
|
'customer.form.error': 'Lütfen tüm zorunlu alanları doldurun',
|
|
60
|
-
'customer.form.instructions':
|
|
61
|
-
|
|
62
|
-
'customer.form.error.country': 'Ülke alanı zorunludur',
|
|
59
|
+
'customer.form.instructions': 'Size Nasıl Yardımcı Olabiliriz?',
|
|
60
|
+
'customer.form.error.country': 'Ülke zorunludur',
|
|
63
61
|
'customer.form.error.email': 'Geçerli bir e-posta adresi gerekli',
|
|
64
62
|
'customer.form.error.phone': 'Telefon alanı zorunludur',
|
|
65
63
|
'customer.form.placeholder.name': 'Adınızı girin',
|
|
@@ -104,9 +102,8 @@ export const LocalizationList: Record<LanguageCode, LocalizationKeys> = {
|
|
|
104
102
|
'customer.form.country': 'País',
|
|
105
103
|
'customer.form.submit': 'Contactar Ahora',
|
|
106
104
|
'customer.form.error': 'Por favor complete todos los campos requeridos',
|
|
107
|
-
'customer.form.instructions':
|
|
108
|
-
|
|
109
|
-
'customer.form.error.country': 'El país es requerido',
|
|
105
|
+
'customer.form.instructions': '¿Cómo Podemos Ayudarte?',
|
|
106
|
+
'customer.form.error.country': 'País es obligatorio',
|
|
110
107
|
'customer.form.error.email': 'Se requiere un correo electrónico válido',
|
|
111
108
|
'customer.form.error.phone': 'El teléfono es requerido',
|
|
112
109
|
'customer.form.placeholder.name': 'Ingrese su nombre',
|
|
@@ -153,9 +150,8 @@ export const LocalizationList: Record<LanguageCode, LocalizationKeys> = {
|
|
|
153
150
|
'customer.form.country': 'Pays',
|
|
154
151
|
'customer.form.submit': 'Contacter Maintenant',
|
|
155
152
|
'customer.form.error': 'Veuillez remplir tous les champs obligatoires',
|
|
156
|
-
'customer.form.instructions':
|
|
157
|
-
|
|
158
|
-
'customer.form.error.country': 'Le pays est requis',
|
|
153
|
+
'customer.form.instructions': 'Comment Pouvons-Nous Vous Aider?',
|
|
154
|
+
'customer.form.error.country': 'Le pays est obligatoire',
|
|
159
155
|
'customer.form.error.email': 'Un email valide est requis',
|
|
160
156
|
'customer.form.error.phone': 'Le téléphone est requis',
|
|
161
157
|
'customer.form.placeholder.name': 'Entrez votre nom',
|
|
@@ -203,8 +199,7 @@ export const LocalizationList: Record<LanguageCode, LocalizationKeys> = {
|
|
|
203
199
|
'customer.form.country': 'Land',
|
|
204
200
|
'customer.form.submit': 'Jetzt Kontaktieren',
|
|
205
201
|
'customer.form.error': 'Bitte füllen Sie alle erforderlichen Felder aus',
|
|
206
|
-
'customer.form.instructions':
|
|
207
|
-
'Füllen Sie das folgende Formular aus, um einen personalisierten Service zu erhalten',
|
|
202
|
+
'customer.form.instructions': 'Wie Können Wir Ihnen Helfen?',
|
|
208
203
|
'customer.form.error.country': 'Land ist erforderlich',
|
|
209
204
|
'customer.form.error.email': 'Eine gültige E-Mail-Adresse ist erforderlich',
|
|
210
205
|
'customer.form.error.phone': 'Telefon ist erforderlich',
|
|
@@ -254,8 +249,7 @@ export const LocalizationList: Record<LanguageCode, LocalizationKeys> = {
|
|
|
254
249
|
'customer.form.country': 'Paese',
|
|
255
250
|
'customer.form.submit': 'Contatta Ora',
|
|
256
251
|
'customer.form.error': 'Si prega di compilare tutti i campi obbligatori',
|
|
257
|
-
'customer.form.instructions':
|
|
258
|
-
'Completa il modulo sottostante per ricevere un servizio personalizzato',
|
|
252
|
+
'customer.form.instructions': 'Come Possiamo Aiutarti?',
|
|
259
253
|
'customer.form.error.country': 'Il paese è obbligatorio',
|
|
260
254
|
'customer.form.error.email': "È richiesta un'email valida",
|
|
261
255
|
'customer.form.error.phone': 'Il telefono è obbligatorio',
|
|
@@ -302,9 +296,8 @@ export const LocalizationList: Record<LanguageCode, LocalizationKeys> = {
|
|
|
302
296
|
'customer.form.country': 'País',
|
|
303
297
|
'customer.form.submit': 'Contactar Agora',
|
|
304
298
|
'customer.form.error': 'Por favor, preencha todos os campos obrigatórios',
|
|
305
|
-
'customer.form.instructions':
|
|
306
|
-
|
|
307
|
-
'customer.form.error.country': 'O país é obrigatório',
|
|
299
|
+
'customer.form.instructions': 'Como Podemos Ajudar Você?',
|
|
300
|
+
'customer.form.error.country': 'País é obrigatório',
|
|
308
301
|
'customer.form.error.email': 'Um email válido é obrigatório',
|
|
309
302
|
'customer.form.error.phone': 'O telefone é obrigatório',
|
|
310
303
|
'customer.form.placeholder.name': 'Digite seu nome',
|
|
@@ -327,7 +320,7 @@ export const LocalizationList: Record<LanguageCode, LocalizationKeys> = {
|
|
|
327
320
|
'customer.form.validation.name.maxLength':
|
|
328
321
|
'O nome deve ter menos de 30 caracteres',
|
|
329
322
|
'chat.empty.title': 'Você não tem mensagens.',
|
|
330
|
-
'chat.empty.description': 'As
|
|
323
|
+
'chat.empty.description': 'As mensaggi da equipe serão exibidas aqui.',
|
|
331
324
|
'chat.live': 'Chat ao Vivo',
|
|
332
325
|
'chat.support-team': 'Equipe de Suporte',
|
|
333
326
|
'customer.form.resend': 'Reenviar',
|
|
@@ -352,8 +345,7 @@ export const LocalizationList: Record<LanguageCode, LocalizationKeys> = {
|
|
|
352
345
|
'customer.form.country': 'Страна',
|
|
353
346
|
'customer.form.submit': 'Связаться Сейчас',
|
|
354
347
|
'customer.form.error': 'Пожалуйста, заполните все обязательные поля',
|
|
355
|
-
'customer.form.instructions':
|
|
356
|
-
'Заполните форму ниже, чтобы получить персонализированное обслуживание',
|
|
348
|
+
'customer.form.instructions': 'Как Мы Можем Вам Помочь?',
|
|
357
349
|
'customer.form.error.country': 'Страна обязательна',
|
|
358
350
|
'customer.form.error.email': 'Требуется действительный email',
|
|
359
351
|
'customer.form.error.phone': 'Телефон обязателен',
|
|
@@ -402,8 +394,7 @@ export const LocalizationList: Record<LanguageCode, LocalizationKeys> = {
|
|
|
402
394
|
'customer.form.country': '国',
|
|
403
395
|
'customer.form.submit': '今すぐ連絡する',
|
|
404
396
|
'customer.form.error': '必須項目をすべて入力してください',
|
|
405
|
-
'customer.form.instructions':
|
|
406
|
-
'パーソナライズされたサービスを受けるには、以下のフォームに記入してください',
|
|
397
|
+
'customer.form.instructions': 'どのようにお手伝いできますか?',
|
|
407
398
|
'customer.form.error.country': '国は必須です',
|
|
408
399
|
'customer.form.error.email': '有効なメールアドレスが必要です',
|
|
409
400
|
'customer.form.error.phone': '電話番号は必須です',
|
|
@@ -449,7 +440,7 @@ export const LocalizationList: Record<LanguageCode, LocalizationKeys> = {
|
|
|
449
440
|
'customer.form.country': '国家',
|
|
450
441
|
'customer.form.submit': '立即联系',
|
|
451
442
|
'customer.form.error': '请填写所有必填字段',
|
|
452
|
-
'customer.form.instructions': '
|
|
443
|
+
'customer.form.instructions': '我们能为您做什么?',
|
|
453
444
|
'customer.form.error.country': '国家为必填项',
|
|
454
445
|
'customer.form.error.email': '需要有效的电子邮件',
|
|
455
446
|
'customer.form.error.phone': '电话为必填项',
|