@developer_tribe/react-native-comnyx 0.3.8 → 0.3.10

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.
@@ -8,6 +8,7 @@ import {
8
8
  Image,
9
9
  TouchableOpacity,
10
10
  Keyboard,
11
+ StatusBar,
11
12
  } from 'react-native';
12
13
  import { getCustomerConversation, sendCustomerMessage } from '../api';
13
14
  import type { AppConversationMessage } from '../types/Conversation';
@@ -513,131 +514,141 @@ export function ChatList({ onBack }: { onBack?: () => void }) {
513
514
  }
514
515
 
515
516
  return (
516
- <View
517
- style={[styles.container, { backgroundColor: themeColors.background }]}
518
- >
519
- <TouchableOpacity
520
- style={[styles.iconContainer]}
521
- onPress={onBack}
522
- activeOpacity={activeOpacity}
523
- >
524
- <Image
525
- source={closeIcon}
526
- style={[styles.closeIcon, { tintColor: themeColors.text }]}
527
- />
528
- </TouchableOpacity>
517
+ <>
518
+ <StatusBar
519
+ barStyle={'dark-content'}
520
+ backgroundColor={themeColors.background}
521
+ animated={false}
522
+ translucent
523
+ />
529
524
  <View
530
- style={[
531
- styles.headerContainer,
532
- {
533
- backgroundColor: themeColors.background,
534
- borderBottomColor: themeColors.lavender,
535
- },
536
- ]}
525
+ style={[styles.container, { backgroundColor: themeColors.background }]}
537
526
  >
538
- <AppText
539
- localization="chat.support-team"
540
- style={[styles.header, { color: themeColors.text }]}
541
- />
527
+ <TouchableOpacity
528
+ style={[styles.iconContainer]}
529
+ onPress={onBack}
530
+ activeOpacity={activeOpacity}
531
+ >
532
+ <Image
533
+ source={closeIcon}
534
+ style={[styles.closeIcon, { tintColor: themeColors.text }]}
535
+ />
536
+ </TouchableOpacity>
542
537
  <View
543
538
  style={[
544
- styles.headerText,
545
- { backgroundColor: themeColors.background },
539
+ styles.headerContainer,
540
+ {
541
+ backgroundColor: themeColors.background,
542
+ borderBottomColor: themeColors.lavender,
543
+ },
546
544
  ]}
547
545
  >
548
- <Image
549
- source={headphonesIcon}
550
- style={[styles.headphonesIcon, { tintColor: themeColors.text }]}
551
- />
552
546
  <AppText
553
- localization="chat.live"
554
- style={[styles.liveChat, { color: themeColors.text }]}
547
+ localization="chat.support-team"
548
+ style={[styles.header, { color: themeColors.text }]}
555
549
  />
556
- <View style={[styles.dot, { backgroundColor: themeColors.green }]} />
550
+ <View
551
+ style={[
552
+ styles.headerText,
553
+ { backgroundColor: themeColors.background },
554
+ ]}
555
+ >
556
+ <Image
557
+ source={headphonesIcon}
558
+ style={[styles.headphonesIcon, { tintColor: themeColors.text }]}
559
+ />
560
+ <AppText
561
+ localization="chat.live"
562
+ style={[styles.liveChat, { color: themeColors.text }]}
563
+ />
564
+ <View
565
+ style={[styles.dot, { backgroundColor: themeColors.green }]}
566
+ />
567
+ </View>
557
568
  </View>
558
- </View>
559
569
 
560
- <View style={styles.listContainer}>
561
- <AppText
562
- style={[
563
- styles.fixedDateText,
564
- { color: themeColors.slate, backgroundColor: themeColors.ghost },
565
- ]}
566
- >
567
- {currentSection}
568
- </AppText>
569
-
570
- <SectionList
571
- ref={ref}
572
- sections={sections}
573
- inverted
574
- renderItem={renderItem}
575
- contentContainerStyle={[
576
- styles.contentContainer,
577
- { backgroundColor: themeColors.background },
578
- ]}
579
- style={styles.list}
580
- ListEmptyComponent={
581
- !loading && (!sections || sections.length === 0) ? (
582
- <EmptyList />
583
- ) : null
584
- }
585
- ListFooterComponent={loading ? <LoadingItem /> : null}
586
- keyExtractor={(item: AppConversationMessage) =>
587
- item.id + '-' + item.created_at
588
- }
589
- removeClippedSubviews={true}
590
- maxToRenderPerBatch={10}
591
- windowSize={21}
592
- initialNumToRender={MESSAGES_PER_PAGE}
593
- getItemLayout={(_: any, index: number) => ({
594
- length: MESSAGE_MIN_HEIGHT + 10,
595
- offset: (MESSAGE_MIN_HEIGHT + 10) * index,
596
- index,
597
- })}
598
- onScroll={handleScroll}
599
- scrollEventThrottle={16}
600
- viewabilityConfigCallbackPairs={
601
- viewabilityConfigCallbackPairs.current
602
- }
603
- stickySectionHeadersEnabled={false}
570
+ <View style={styles.listContainer}>
571
+ <AppText
572
+ style={[
573
+ styles.fixedDateText,
574
+ { color: themeColors.slate, backgroundColor: themeColors.ghost },
575
+ ]}
576
+ >
577
+ {currentSection}
578
+ </AppText>
579
+
580
+ <SectionList
581
+ ref={ref}
582
+ sections={sections}
583
+ inverted
584
+ renderItem={renderItem}
585
+ contentContainerStyle={[
586
+ styles.contentContainer,
587
+ { backgroundColor: themeColors.background },
588
+ ]}
589
+ style={styles.list}
590
+ ListEmptyComponent={
591
+ !loading && (!sections || sections.length === 0) ? (
592
+ <EmptyList />
593
+ ) : null
594
+ }
595
+ ListFooterComponent={loading ? <LoadingItem /> : null}
596
+ keyExtractor={(item: AppConversationMessage) =>
597
+ item.id + '-' + item.created_at
598
+ }
599
+ removeClippedSubviews={true}
600
+ maxToRenderPerBatch={10}
601
+ windowSize={21}
602
+ initialNumToRender={MESSAGES_PER_PAGE}
603
+ getItemLayout={(_: any, index: number) => ({
604
+ length: MESSAGE_MIN_HEIGHT + 10,
605
+ offset: (MESSAGE_MIN_HEIGHT + 10) * index,
606
+ index,
607
+ })}
608
+ onScroll={handleScroll}
609
+ scrollEventThrottle={16}
610
+ viewabilityConfigCallbackPairs={
611
+ viewabilityConfigCallbackPairs.current
612
+ }
613
+ stickySectionHeadersEnabled={false}
614
+ />
615
+ </View>
616
+ {isScrollingUp && (
617
+ <TouchableOpacity
618
+ activeOpacity={activeOpacity}
619
+ style={[
620
+ styles.scrollDownButton,
621
+ { backgroundColor: themeColors.ghost },
622
+ isKeyboardVisible && styles.scrollDownButtonWithKeyboard,
623
+ ]}
624
+ onPress={() => scrollToBottom(true)}
625
+ >
626
+ <Image
627
+ source={require('../assets/down.png')}
628
+ style={[styles.scrollUpIcon, { tintColor: themeColors.text }]}
629
+ />
630
+ </TouchableOpacity>
631
+ )}
632
+ <MessageInput
633
+ scrollToBottom={scrollToBottom}
634
+ selectedMessage={selectedMessage}
635
+ />
636
+ <CustomPopup
637
+ isVisible={popupVisible}
638
+ onClose={() => setPopupVisible(false)}
639
+ title={'chat.list-failed-message.title'}
640
+ description={'chat.list-failed-message.description'}
641
+ onCancelButton={() => {
642
+ setPopupVisible(false);
643
+ }}
644
+ onResendButton={() => {
645
+ resendMessage();
646
+ setPopupVisible(false);
647
+ }}
648
+ buttonText={'chat.list-cancel' as keyof LocalizationKeys}
604
649
  />
605
650
  </View>
606
- {isScrollingUp && (
607
- <TouchableOpacity
608
- activeOpacity={activeOpacity}
609
- style={[
610
- styles.scrollDownButton,
611
- { backgroundColor: themeColors.ghost },
612
- isKeyboardVisible && styles.scrollDownButtonWithKeyboard,
613
- ]}
614
- onPress={() => scrollToBottom(true)}
615
- >
616
- <Image
617
- source={require('../assets/down.png')}
618
- style={[styles.scrollUpIcon, { tintColor: themeColors.text }]}
619
- />
620
- </TouchableOpacity>
621
- )}
622
- <MessageInput
623
- scrollToBottom={scrollToBottom}
624
- selectedMessage={selectedMessage}
625
- />
626
- <CustomPopup
627
- isVisible={popupVisible}
628
- onClose={() => setPopupVisible(false)}
629
- title={'chat.list-failed-message.title'}
630
- description={'chat.list-failed-message.description'}
631
- onCancelButton={() => {
632
- setPopupVisible(false);
633
- }}
634
- onResendButton={() => {
635
- resendMessage();
636
- setPopupVisible(false);
637
- }}
638
- buttonText={'chat.list-cancel' as keyof LocalizationKeys}
639
- />
640
- </View>
651
+ </>
641
652
  );
642
653
  }
643
654
 
@@ -2,10 +2,10 @@ import {
2
2
  View,
3
3
  TextInput,
4
4
  TouchableOpacity,
5
- Pressable,
6
5
  Keyboard,
7
6
  Image,
8
7
  ScrollView,
8
+ StatusBar,
9
9
  } from 'react-native';
10
10
  import { useForm, Controller } from 'react-hook-form';
11
11
  import { useAppStore } from '../store';
@@ -96,208 +96,222 @@ export function CustomerForm({ onBack }: { onBack: () => void }) {
96
96
  };
97
97
 
98
98
  return (
99
- <Pressable
100
- style={[styles.container, { backgroundColor: themeColors.background }]}
101
- onPress={Keyboard.dismiss}
102
- >
103
- <ScrollView
104
- contentContainerStyle={styles.scrollContainer}
105
- keyboardShouldPersistTaps="handled"
99
+ <>
100
+ <StatusBar
101
+ barStyle={'dark-content'}
102
+ backgroundColor={themeColors.dark_background}
103
+ animated={false}
104
+ translucent
105
+ />
106
+ <TouchableOpacity
107
+ style={[styles.container, { backgroundColor: themeColors.background }]}
108
+ onPress={Keyboard.dismiss}
109
+ activeOpacity={activeOpacity}
106
110
  >
107
- <View
108
- style={[
109
- styles.container,
110
- { backgroundColor: themeColors.background },
111
- ]}
111
+ <ScrollView
112
+ contentContainerStyle={styles.scrollContainer}
113
+ keyboardShouldPersistTaps="handled"
112
114
  >
113
- <TouchableOpacity
114
- activeOpacity={activeOpacity}
115
- style={[
116
- styles.iconContainer,
117
- { backgroundColor: themeColors.dark_background },
118
- ]}
119
- onPress={onBack}
120
- >
121
- <Image
122
- source={closeIcon}
123
- style={[styles.closeIcon, { tintColor: themeColors.light_text }]}
124
- />
125
- </TouchableOpacity>
126
115
  <View
127
116
  style={[
128
- styles.headerContainer,
129
- { backgroundColor: themeColors.dark_background },
117
+ styles.container,
118
+ { backgroundColor: themeColors.background },
130
119
  ]}
131
120
  >
132
- <AppText
133
- localization="customer.form.title"
134
- style={[styles.headerText, { color: themeColors.gainsboro }]}
135
- />
136
- <AppText
137
- localization="customer.form.instructions"
138
- style={[styles.headerText, { color: themeColors.light_text }]}
139
- />
140
- </View>
141
- <View style={styles.titleContainer}>
142
- <AppText
121
+ <TouchableOpacity
122
+ activeOpacity={activeOpacity}
143
123
  style={[
144
- styles.title,
145
- {
146
- color: themeColors.slate,
147
- },
124
+ styles.iconContainer,
125
+ { backgroundColor: themeColors.dark_background },
148
126
  ]}
127
+ onPress={onBack}
149
128
  >
150
- {localize('customer.form.name')}
151
- </AppText>
152
- <Controller
153
- control={control}
154
- rules={{
155
- maxLength: {
156
- value: 30,
157
- message: localize('customer.form.validation.name.maxLength'),
158
- },
159
- }}
160
- render={({ field: { onChange, value } }) => (
161
- <View
162
- style={[
163
- styles.inputContainer,
164
- { borderBottomColor: themeColors.ghost },
165
- ]}
166
- >
167
- <TextInput
168
- style={inputStyle}
169
- placeholder={localize('customer.form.placeholder.name')}
170
- placeholderTextColor={themeColors.gainsboro}
171
- value={value}
172
- onChangeText={onChange}
173
- />
174
- {errors.name && (
175
- <InfoButton
176
- title={'customer.form.failed.name'}
177
- description={'customer.form.failed.name.desc'}
178
- />
179
- )}
180
- </View>
181
- )}
182
- name="name"
183
- />
184
- <AppText
129
+ <Image
130
+ source={closeIcon}
131
+ style={[
132
+ styles.closeIcon,
133
+ { tintColor: themeColors.light_text },
134
+ ]}
135
+ />
136
+ </TouchableOpacity>
137
+ <View
185
138
  style={[
186
- styles.title,
187
- {
188
- color: themeColors.slate,
189
- },
139
+ styles.headerContainer,
140
+ { backgroundColor: themeColors.dark_background },
190
141
  ]}
191
142
  >
192
- Email
193
- </AppText>
194
- <Controller
195
- control={control}
196
- rules={{
197
- pattern: {
198
- value: /^\S+@\S+$/i,
199
- message: localize('customer.form.validation.email.pattern'),
200
- },
201
- }}
202
- render={({ field: { onChange, value } }) => (
203
- <View
204
- style={[
205
- styles.inputContainer,
206
- { borderBottomColor: themeColors.ghost },
207
- ]}
208
- >
209
- <TextInput
210
- style={inputStyle}
211
- placeholder={localize('customer.form.placeholder.email')}
212
- placeholderTextColor={themeColors.gainsboro}
213
- value={value}
214
- onChangeText={onChange}
215
- keyboardType="email-address"
216
- />
217
- {errors.email && (
218
- <InfoButton
219
- title={'customer.form.failed.email'}
220
- description={'customer.form.failed.email.desc'}
143
+ <AppText
144
+ localization="customer.form.title"
145
+ style={[styles.headerText, { color: themeColors.gainsboro }]}
146
+ />
147
+ <AppText
148
+ localization="customer.form.instructions"
149
+ style={[styles.headerText, { color: themeColors.light_text }]}
150
+ />
151
+ </View>
152
+ <View style={styles.titleContainer}>
153
+ <AppText
154
+ style={[
155
+ styles.title,
156
+ {
157
+ color: themeColors.slate,
158
+ },
159
+ ]}
160
+ >
161
+ {localize('customer.form.name')}
162
+ </AppText>
163
+ <Controller
164
+ control={control}
165
+ rules={{
166
+ maxLength: {
167
+ value: 30,
168
+ message: localize(
169
+ 'customer.form.validation.name.maxLength'
170
+ ),
171
+ },
172
+ }}
173
+ render={({ field: { onChange, value } }) => (
174
+ <View
175
+ style={[
176
+ styles.inputContainer,
177
+ { borderBottomColor: themeColors.ghost },
178
+ ]}
179
+ >
180
+ <TextInput
181
+ style={inputStyle}
182
+ placeholder={localize('customer.form.placeholder.name')}
183
+ placeholderTextColor={themeColors.gainsboro}
184
+ value={value}
185
+ onChangeText={onChange}
186
+ />
187
+ {errors.name && (
188
+ <InfoButton
189
+ title={'customer.form.failed.name'}
190
+ description={'customer.form.failed.name.desc'}
191
+ />
192
+ )}
193
+ </View>
194
+ )}
195
+ name="name"
196
+ />
197
+ <AppText
198
+ style={[
199
+ styles.title,
200
+ {
201
+ color: themeColors.slate,
202
+ },
203
+ ]}
204
+ >
205
+ Email
206
+ </AppText>
207
+ <Controller
208
+ control={control}
209
+ rules={{
210
+ pattern: {
211
+ value: /^\S+@\S+$/i,
212
+ message: localize('customer.form.validation.email.pattern'),
213
+ },
214
+ }}
215
+ render={({ field: { onChange, value } }) => (
216
+ <View
217
+ style={[
218
+ styles.inputContainer,
219
+ { borderBottomColor: themeColors.ghost },
220
+ ]}
221
+ >
222
+ <TextInput
223
+ style={inputStyle}
224
+ placeholder={localize('customer.form.placeholder.email')}
225
+ placeholderTextColor={themeColors.gainsboro}
226
+ value={value}
227
+ onChangeText={onChange}
228
+ keyboardType="email-address"
221
229
  />
222
- )}
223
- </View>
224
- )}
225
- name="email"
226
- />
227
- <AppText
230
+ {errors.email && (
231
+ <InfoButton
232
+ title={'customer.form.failed.email'}
233
+ description={'customer.form.failed.email.desc'}
234
+ />
235
+ )}
236
+ </View>
237
+ )}
238
+ name="email"
239
+ />
240
+ <AppText
241
+ style={[
242
+ styles.title,
243
+ {
244
+ color: themeColors.slate,
245
+ },
246
+ ]}
247
+ >
248
+ Phone
249
+ </AppText>
250
+ <Controller
251
+ control={control}
252
+ rules={{
253
+ validate: (value) => {
254
+ if (!value) return true;
255
+ return (
256
+ typeof value === 'string' ||
257
+ localize('customer.form.validation.phone.invalid')
258
+ );
259
+ },
260
+ }}
261
+ render={({ field: { onChange, value } }) => (
262
+ <View
263
+ style={[
264
+ styles.inputContainer,
265
+ { borderBottomColor: themeColors.ghost },
266
+ ]}
267
+ >
268
+ <TextInput
269
+ style={inputStyle}
270
+ placeholder={localize('customer.form.placeholder.phone')}
271
+ placeholderTextColor={themeColors.gainsboro}
272
+ value={value}
273
+ onChangeText={onChange}
274
+ keyboardType="phone-pad"
275
+ />
276
+ {errors.phone && (
277
+ <InfoButton
278
+ title={'customer.form.failed.phone'}
279
+ description={'customer.form.failed.phone.desc'}
280
+ />
281
+ )}
282
+ </View>
283
+ )}
284
+ name="phone"
285
+ />
286
+ </View>
287
+ <TouchableOpacity
288
+ activeOpacity={activeOpacity}
228
289
  style={[
229
- styles.title,
230
- {
231
- color: themeColors.slate,
232
- },
290
+ styles.button,
291
+ { backgroundColor: themeColors.dark_background },
233
292
  ]}
293
+ onPress={handleSubmit(onSubmit)}
234
294
  >
235
- Phone
236
- </AppText>
237
- <Controller
238
- control={control}
239
- rules={{
240
- validate: (value) => {
241
- if (!value) return true;
242
- return (
243
- typeof value === 'string' ||
244
- localize('customer.form.validation.phone.invalid')
245
- );
246
- },
247
- }}
248
- render={({ field: { onChange, value } }) => (
249
- <View
250
- style={[
251
- styles.inputContainer,
252
- { borderBottomColor: themeColors.ghost },
253
- ]}
254
- >
255
- <TextInput
256
- style={inputStyle}
257
- placeholder={localize('customer.form.placeholder.phone')}
258
- placeholderTextColor={themeColors.gainsboro}
259
- value={value}
260
- onChangeText={onChange}
261
- keyboardType="phone-pad"
262
- />
263
- {errors.phone && (
264
- <InfoButton
265
- title={'customer.form.failed.phone'}
266
- description={'customer.form.failed.phone.desc'}
267
- />
268
- )}
269
- </View>
270
- )}
271
- name="phone"
272
- />
295
+ <AppText
296
+ localization="customer.form.submit"
297
+ style={[styles.buttonText, { color: themeColors.light_text }]}
298
+ />
299
+ </TouchableOpacity>
273
300
  </View>
274
- <TouchableOpacity
275
- activeOpacity={activeOpacity}
276
- style={[
277
- styles.button,
278
- { backgroundColor: themeColors.dark_background },
279
- ]}
280
- onPress={handleSubmit(onSubmit)}
281
- >
282
- <AppText
283
- localization="customer.form.submit"
284
- style={[styles.buttonText, { color: themeColors.light_text }]}
285
- />
286
- </TouchableOpacity>
287
- </View>
288
- </ScrollView>
289
- <CustomPopup
290
- isVisible={popupVisible}
291
- onClose={() => setPopupVisible(false)}
292
- title={popupContent.title}
293
- description={popupContent.description}
294
- onCancelButton={() => {
295
- setPopupVisible(false);
296
- setPopupContent({ title: '', description: '' });
297
- }}
298
- buttonText={'customer.form.cancel' as keyof LocalizationKeys}
299
- />
300
- </Pressable>
301
+ </ScrollView>
302
+ <CustomPopup
303
+ isVisible={popupVisible}
304
+ onClose={() => setPopupVisible(false)}
305
+ title={popupContent.title}
306
+ description={popupContent.description}
307
+ onCancelButton={() => {
308
+ setPopupVisible(false);
309
+ setPopupContent({ title: '', description: '' });
310
+ }}
311
+ buttonText={'customer.form.cancel' as keyof LocalizationKeys}
312
+ />
313
+ </TouchableOpacity>
314
+ </>
301
315
  );
302
316
  }
303
317