stream-chat-react-native-core 9.4.0-beta.1 → 9.4.0-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/lib/commonjs/components/Attachment/Attachment.js +8 -4
  2. package/lib/commonjs/components/Attachment/Attachment.js.map +1 -1
  3. package/lib/commonjs/components/Attachment/Audio/AudioAttachment.js +2 -4
  4. package/lib/commonjs/components/Attachment/Audio/AudioAttachment.js.map +1 -1
  5. package/lib/commonjs/components/Message/Message.js +53 -16
  6. package/lib/commonjs/components/Message/Message.js.map +1 -1
  7. package/lib/commonjs/components/Message/MessageItemView/MessageItemView.js +6 -84
  8. package/lib/commonjs/components/Message/MessageItemView/MessageItemView.js.map +1 -1
  9. package/lib/commonjs/components/MessageInput/MessageComposer.js +8 -29
  10. package/lib/commonjs/components/MessageInput/MessageComposer.js.map +1 -1
  11. package/lib/commonjs/components/MessageMenu/MessageActionList.js +1 -1
  12. package/lib/commonjs/components/Poll/components/CreatePollHeader.js +5 -5
  13. package/lib/commonjs/components/Poll/components/CreatePollHeader.js.map +1 -1
  14. package/lib/commonjs/components/Poll/components/PollButtons.js +25 -56
  15. package/lib/commonjs/components/Poll/components/PollButtons.js.map +1 -1
  16. package/lib/commonjs/components/Poll/components/PollInputDialog.js +9 -11
  17. package/lib/commonjs/components/Poll/components/PollInputDialog.js.map +1 -1
  18. package/lib/commonjs/components/Poll/components/PollModal.js +50 -0
  19. package/lib/commonjs/components/Poll/components/PollModal.js.map +1 -0
  20. package/lib/commonjs/components/Poll/components/PollModalHeader.js +3 -3
  21. package/lib/commonjs/components/Poll/components/PollModalHeader.js.map +1 -1
  22. package/lib/commonjs/components/Poll/components/PollResults/PollResultItem.js +10 -24
  23. package/lib/commonjs/components/Poll/components/PollResults/PollResultItem.js.map +1 -1
  24. package/lib/commonjs/components/Poll/components/index.js +11 -0
  25. package/lib/commonjs/components/Poll/components/index.js.map +1 -1
  26. package/lib/commonjs/version.json +1 -1
  27. package/lib/module/components/Attachment/Attachment.js +8 -4
  28. package/lib/module/components/Attachment/Attachment.js.map +1 -1
  29. package/lib/module/components/Attachment/Audio/AudioAttachment.js +2 -4
  30. package/lib/module/components/Attachment/Audio/AudioAttachment.js.map +1 -1
  31. package/lib/module/components/Message/Message.js +53 -16
  32. package/lib/module/components/Message/Message.js.map +1 -1
  33. package/lib/module/components/Message/MessageItemView/MessageItemView.js +6 -84
  34. package/lib/module/components/Message/MessageItemView/MessageItemView.js.map +1 -1
  35. package/lib/module/components/MessageInput/MessageComposer.js +8 -29
  36. package/lib/module/components/MessageInput/MessageComposer.js.map +1 -1
  37. package/lib/module/components/MessageMenu/MessageActionList.js +1 -1
  38. package/lib/module/components/Poll/components/CreatePollHeader.js +5 -5
  39. package/lib/module/components/Poll/components/CreatePollHeader.js.map +1 -1
  40. package/lib/module/components/Poll/components/PollButtons.js +25 -56
  41. package/lib/module/components/Poll/components/PollButtons.js.map +1 -1
  42. package/lib/module/components/Poll/components/PollInputDialog.js +9 -11
  43. package/lib/module/components/Poll/components/PollInputDialog.js.map +1 -1
  44. package/lib/module/components/Poll/components/PollModal.js +50 -0
  45. package/lib/module/components/Poll/components/PollModal.js.map +1 -0
  46. package/lib/module/components/Poll/components/PollModalHeader.js +3 -3
  47. package/lib/module/components/Poll/components/PollModalHeader.js.map +1 -1
  48. package/lib/module/components/Poll/components/PollResults/PollResultItem.js +10 -24
  49. package/lib/module/components/Poll/components/PollResults/PollResultItem.js.map +1 -1
  50. package/lib/module/components/Poll/components/index.js +11 -0
  51. package/lib/module/components/Poll/components/index.js.map +1 -1
  52. package/lib/module/version.json +1 -1
  53. package/lib/typescript/components/Attachment/Audio/AudioAttachment.d.ts +1 -0
  54. package/lib/typescript/components/Attachment/Audio/AudioAttachment.d.ts.map +1 -1
  55. package/lib/typescript/components/Message/Message.d.ts.map +1 -1
  56. package/lib/typescript/components/Message/MessageItemView/MessageItemView.d.ts.map +1 -1
  57. package/lib/typescript/components/MessageInput/MessageComposer.d.ts.map +1 -1
  58. package/lib/typescript/components/Poll/components/CreatePollHeader.d.ts.map +1 -1
  59. package/lib/typescript/components/Poll/components/PollButtons.d.ts.map +1 -1
  60. package/lib/typescript/components/Poll/components/PollModal.d.ts +9 -0
  61. package/lib/typescript/components/Poll/components/PollModal.d.ts.map +1 -0
  62. package/lib/typescript/components/Poll/components/PollResults/PollResultItem.d.ts.map +1 -1
  63. package/lib/typescript/components/Poll/components/index.d.ts +1 -0
  64. package/lib/typescript/components/Poll/components/index.d.ts.map +1 -1
  65. package/package.json +1 -1
  66. package/src/components/Attachment/Attachment.tsx +9 -5
  67. package/src/components/Attachment/Audio/AudioAttachment.tsx +3 -4
  68. package/src/components/Message/Message.tsx +68 -22
  69. package/src/components/Message/MessageItemView/MessageItemView.tsx +5 -116
  70. package/src/components/Message/MessageItemView/__tests__/MessageItemView.test.tsx +22 -13
  71. package/src/components/MessageInput/MessageComposer.tsx +9 -30
  72. package/src/components/MessageMenu/MessageActionList.tsx +1 -1
  73. package/src/components/Poll/components/CreatePollHeader.tsx +12 -5
  74. package/src/components/Poll/components/PollButtons.tsx +14 -38
  75. package/src/components/Poll/components/PollInputDialog.tsx +12 -12
  76. package/src/components/Poll/components/PollModal.tsx +55 -0
  77. package/src/components/Poll/components/PollModalHeader.tsx +3 -3
  78. package/src/components/Poll/components/PollResults/PollResultItem.tsx +6 -18
  79. package/src/components/Poll/components/__tests__/CreatePollHeader.test.tsx +4 -36
  80. package/src/components/Poll/components/__tests__/PollModalHeader.test.tsx +8 -45
  81. package/src/components/Poll/components/index.ts +1 -0
  82. package/src/components/Thread/__tests__/__snapshots__/Thread.test.tsx.snap +5 -5
  83. package/src/version.json +1 -1
@@ -1,5 +1,5 @@
1
1
  import React, { useMemo } from 'react';
2
- import { Dimensions, StyleSheet, View, ViewStyle } from 'react-native';
2
+ import { Dimensions, StyleSheet, View } from 'react-native';
3
3
 
4
4
  import { SwipableMessageWrapper } from './MessageBubble';
5
5
 
@@ -22,25 +22,7 @@ import { FileTypes } from '../../../types/types';
22
22
  import { checkMessageEquality, checkQuotedMessageEquality } from '../../../utils/utils';
23
23
  import { useMessageData } from '../hooks/useMessageData';
24
24
 
25
- type GroupType = 'single' | 'top' | 'middle' | 'bottom' | undefined;
26
-
27
- const useStyles = ({
28
- alignment,
29
- isVeryLastMessage,
30
- messageGroupedSingle,
31
- messageGroupedBottom,
32
- messageGroupedTop,
33
- messageGroupedMiddle,
34
- enableMessageGroupingByUser,
35
- }: {
36
- alignment: Alignment;
37
- isVeryLastMessage: boolean;
38
- messageGroupedSingle: boolean;
39
- messageGroupedBottom: boolean;
40
- messageGroupedTop: boolean;
41
- messageGroupedMiddle: boolean;
42
- enableMessageGroupingByUser: boolean;
43
- }) => {
25
+ const useStyles = ({ alignment }: { alignment: Alignment }) => {
44
26
  const {
45
27
  theme: {
46
28
  messageItemView: {
@@ -53,24 +35,11 @@ const useStyles = ({
53
35
  repliesContainer,
54
36
  leftAlignItems,
55
37
  rightAlignItems,
56
- messageGroupedSingleStyles,
57
- messageGroupedBottomStyles,
58
- messageGroupedTopStyles,
59
- messageGroupedMiddleStyles,
60
- lastMessageContainer,
61
38
  },
62
39
  },
63
40
  } = useTheme();
64
41
 
65
- const groupType: GroupType = useMemo(() => {
66
- if (messageGroupedSingle) return 'single';
67
- if (messageGroupedTop) return 'top';
68
- if (messageGroupedMiddle) return 'middle';
69
- if (messageGroupedBottom) return 'bottom';
70
- return undefined;
71
- }, [messageGroupedSingle, messageGroupedTop, messageGroupedMiddle, messageGroupedBottom]);
72
-
73
- const styles = useMemo(
42
+ return useMemo(
74
43
  () =>
75
44
  StyleSheet.create({
76
45
  baseContainer: {
@@ -129,73 +98,6 @@ const useStyles = ({
129
98
  rightAlignItems,
130
99
  ],
131
100
  );
132
-
133
- const groupStylesMap = useMemo(() => {
134
- return {
135
- single: {
136
- paddingVertical: primitives.spacingXs,
137
- ...messageGroupedSingleStyles,
138
- },
139
- top: {
140
- paddingTop: primitives.spacingXs,
141
- paddingBottom: primitives.spacingXxs,
142
- ...messageGroupedTopStyles,
143
- },
144
- middle: {
145
- paddingBottom: primitives.spacingXxs,
146
- ...messageGroupedMiddleStyles,
147
- },
148
- bottom: {
149
- paddingBottom: primitives.spacingXs,
150
- ...messageGroupedBottomStyles,
151
- },
152
- };
153
- }, [
154
- messageGroupedBottomStyles,
155
- messageGroupedMiddleStyles,
156
- messageGroupedSingleStyles,
157
- messageGroupedTopStyles,
158
- ]);
159
-
160
- const containerStyle = useMemo(() => {
161
- let results: ViewStyle = styles.baseContainer;
162
-
163
- if (groupType) {
164
- results = {
165
- ...results,
166
- ...groupStylesMap[groupType],
167
- };
168
- }
169
-
170
- if (isVeryLastMessage && enableMessageGroupingByUser) {
171
- results = {
172
- ...results,
173
- marginBottom: primitives.spacingSm,
174
- ...lastMessageContainer,
175
- };
176
- }
177
-
178
- return results;
179
- }, [
180
- styles.baseContainer,
181
- groupStylesMap,
182
- groupType,
183
- isVeryLastMessage,
184
- enableMessageGroupingByUser,
185
- lastMessageContainer,
186
- ]);
187
-
188
- return {
189
- container: containerStyle,
190
- bubbleContentContainer: styles.bubbleContentContainer,
191
- bubbleErrorContainer: styles.bubbleErrorContainer,
192
- bubbleReactionListTopContainer: styles.bubbleReactionListTopContainer,
193
- bubbleWrapper: styles.bubbleWrapper,
194
- contentContainer: styles.contentContainer,
195
- repliesContainer: styles.repliesContainer,
196
- leftAlignItems: styles.leftAlignItems,
197
- rightAlignItems: styles.rightAlignItems,
198
- };
199
101
  };
200
102
 
201
103
  export type MessageItemViewPropsWithContext = Pick<
@@ -232,7 +134,6 @@ const MessageItemViewWithContext = (props: MessageItemViewPropsWithContext) => {
232
134
  channel,
233
135
  contextMenuAnchorRef,
234
136
  customMessageSwipeAction,
235
- enableMessageGroupingByUser,
236
137
  enableSwipeToReply,
237
138
  groupStyles,
238
139
  hasAttachmentActions,
@@ -273,22 +174,10 @@ const MessageItemViewWithContext = (props: MessageItemViewPropsWithContext) => {
273
174
  isMessageReceivedOrErrorType,
274
175
  isMessageTypeDeleted,
275
176
  isVeryLastMessage,
276
- messageGroupedSingle,
277
- messageGroupedBottom,
278
- messageGroupedTop,
279
177
  messageGroupedSingleOrBottom,
280
- messageGroupedMiddle,
281
178
  } = useMessageData({});
282
179
 
283
- const styles = useStyles({
284
- alignment,
285
- isVeryLastMessage,
286
- messageGroupedSingle,
287
- messageGroupedBottom,
288
- messageGroupedTop,
289
- messageGroupedMiddle,
290
- enableMessageGroupingByUser,
291
- });
180
+ const styles = useStyles({ alignment });
292
181
 
293
182
  const groupStyle = `${alignment}_${groupStyles?.[0]?.toLowerCase?.()}`;
294
183
  const hasVisibleQuotedReply = !!message.quoted_message && !hasAttachmentActions;
@@ -324,7 +213,7 @@ const MessageItemViewWithContext = (props: MessageItemViewPropsWithContext) => {
324
213
  });
325
214
 
326
215
  const itemViewContent = (
327
- <View pointerEvents='box-none' style={styles.container} testID='message-item-view-wrapper'>
216
+ <View pointerEvents='box-none' style={styles.baseContainer} testID='message-item-view-wrapper'>
328
217
  {alignment === 'left' ? <MessageAuthor /> : null}
329
218
  {isMessageTypeDeleted ? (
330
219
  <MessageDeleted date={message.created_at} groupStyle={groupStyle} />
@@ -223,38 +223,47 @@ describe('MessageItemView', () => {
223
223
  });
224
224
  });
225
225
 
226
- it('applies correct styles for when group styles are not single or bottom', async () => {
226
+ it('keeps message-item-view-wrapper free of group-positional padding', async () => {
227
227
  const user = generateUser();
228
228
  const message = generateMessage({ user });
229
229
 
230
230
  renderMessage({ groupStyles: ['top'], message });
231
231
 
232
232
  await waitFor(() => {
233
- expect(screen.getByTestId('message-item-view-wrapper').props.style).toMatchObject({
233
+ const innerStyle = screen.getByTestId('message-item-view-wrapper').props.style;
234
+ expect(innerStyle).toMatchObject({
234
235
  alignItems: 'flex-end',
235
236
  gap: 8,
236
237
  flexDirection: 'row',
237
- paddingTop: 8,
238
- paddingBottom: 4,
239
238
  });
239
+ expect(innerStyle.paddingTop).toBeUndefined();
240
+ expect(innerStyle.paddingBottom).toBeUndefined();
240
241
  });
241
242
  });
242
243
 
243
- it('applies correct styles for when group styles are single/bottom and not last message', async () => {
244
+ it('hoists the per-group padding delta onto message-wrapper for top messages', async () => {
244
245
  const user = generateUser();
245
246
  const message = generateMessage({ user });
246
247
 
247
- renderMessage({ message });
248
+ renderMessage({ groupStyles: ['top'], message });
248
249
 
249
250
  await waitFor(() => {
250
- const data = screen.getByTestId('message-item-view-wrapper').props.style;
251
+ expect(screen.getByTestId('message-wrapper').props.style).toEqual(
252
+ expect.arrayContaining([expect.objectContaining({ paddingTop: 8 })]),
253
+ );
254
+ });
255
+ });
251
256
 
252
- expect(data).toMatchObject({
253
- alignItems: 'flex-end',
254
- gap: 8,
255
- flexDirection: 'row',
256
- paddingBottom: 8,
257
- });
257
+ it('hoists the per-group padding delta onto message-wrapper for bottom messages', async () => {
258
+ const user = generateUser();
259
+ const message = generateMessage({ user });
260
+
261
+ renderMessage({ message });
262
+
263
+ await waitFor(() => {
264
+ expect(screen.getByTestId('message-wrapper').props.style).toEqual(
265
+ expect.arrayContaining([expect.objectContaining({ paddingBottom: 8 })]),
266
+ );
258
267
  });
259
268
  });
260
269
 
@@ -1,7 +1,6 @@
1
1
  import React, { useEffect, useMemo } from 'react';
2
- import { Modal, StyleSheet, View } from 'react-native';
2
+ import { StyleSheet, View } from 'react-native';
3
3
 
4
- import { GestureHandlerRootView } from 'react-native-gesture-handler';
5
4
  import Animated, {
6
5
  Extrapolation,
7
6
  interpolate,
@@ -52,9 +51,9 @@ import { MessageInputHeightState } from '../../state-store/message-input-height-
52
51
  import { primitives } from '../../theme';
53
52
  import { transitions } from '../../utils/animations/transitions';
54
53
  import { type TextInputOverrideComponent } from '../AutoCompleteInput/AutoCompleteInput';
54
+ import { PollModal } from '../Poll/components/PollModal';
55
55
  import { CreatePoll } from '../Poll/CreatePollContent';
56
56
  import { PortalWhileClosingView } from '../UIComponents/PortalWhileClosingView';
57
- import { SafeAreaViewWrapper } from '../UIComponents/SafeAreaViewWrapper';
58
57
 
59
58
  const useStyles = () => {
60
59
  const {
@@ -67,16 +66,6 @@ const useStyles = () => {
67
66
  flexShrink: 1,
68
67
  minWidth: 0,
69
68
  },
70
- pollModalWrapper: {
71
- alignItems: 'center',
72
- flex: 1,
73
- justifyContent: 'center',
74
- backgroundColor: semantics.backgroundCoreElevation1,
75
- },
76
- pollSafeArea: {
77
- flex: 1,
78
- backgroundColor: semantics.backgroundCoreElevation1,
79
- },
80
69
  container: {
81
70
  alignItems: 'center',
82
71
  flexDirection: 'row',
@@ -457,23 +446,13 @@ const MessageComposerWithContext = (props: MessageComposerPropsWithContext) => {
457
446
  </Animated.View>
458
447
 
459
448
  {showPollCreationDialog ? (
460
- <View style={styles.pollModalWrapper}>
461
- <Modal
462
- animationType='slide'
463
- onRequestClose={closePollCreationDialog}
464
- visible={showPollCreationDialog}
465
- >
466
- <GestureHandlerRootView style={styles.pollSafeArea}>
467
- <SafeAreaViewWrapper style={styles.pollSafeArea}>
468
- <CreatePoll
469
- closePollCreationDialog={closePollCreationDialog}
470
- createPollOptionGap={createPollOptionGap}
471
- sendMessage={sendMessage}
472
- />
473
- </SafeAreaViewWrapper>
474
- </GestureHandlerRootView>
475
- </Modal>
476
- </View>
449
+ <PollModal onRequestClose={closePollCreationDialog} visible={showPollCreationDialog}>
450
+ <CreatePoll
451
+ closePollCreationDialog={closePollCreationDialog}
452
+ createPollOptionGap={createPollOptionGap}
453
+ sendMessage={sendMessage}
454
+ />
455
+ </PollModal>
477
456
  ) : null}
478
457
  </MicPositionProvider>
479
458
  );
@@ -78,7 +78,7 @@ const useStyles = () => {
78
78
  StyleSheet.create({
79
79
  container: {
80
80
  borderRadius: primitives.radiusLg,
81
- marginTop: 6,
81
+ marginTop: 8,
82
82
  backgroundColor: semantics.backgroundCoreElevation2,
83
83
  borderWidth: 1,
84
84
  borderColor: semantics.borderCoreDefault,
@@ -4,7 +4,7 @@ import { StyleSheet, Text, View } from 'react-native';
4
4
  import { useTheme } from '../../../contexts/themeContext/ThemeContext';
5
5
  import { useTranslationContext } from '../../../contexts/translationContext/TranslationContext';
6
6
  import { Check, IconProps } from '../../../icons';
7
- import { ArrowLeft } from '../../../icons/arrow-left';
7
+ import { Cross } from '../../../icons/xmark-1';
8
8
  import { primitives } from '../../../theme';
9
9
  import { Button } from '../../ui';
10
10
  import { useCanCreatePoll } from '../hooks/useCanCreatePoll';
@@ -43,9 +43,16 @@ export const CreatePollHeader = ({
43
43
 
44
44
  const renderSendPollIcon = useCallback(
45
45
  (props: IconProps) => {
46
- return <Check {...props} height={18} stroke={semantics.textOnAccent} width={18} />;
46
+ return (
47
+ <Check
48
+ {...props}
49
+ height={18}
50
+ stroke={canCreatePoll ? semantics.textOnAccent : semantics.textDisabled}
51
+ width={18}
52
+ />
53
+ );
47
54
  },
48
- [semantics.textOnAccent],
55
+ [canCreatePoll, semantics.textOnAccent, semantics.textDisabled],
49
56
  );
50
57
 
51
58
  return (
@@ -54,9 +61,9 @@ export const CreatePollHeader = ({
54
61
  accessibilityLabelKey='a11y/Close poll creation'
55
62
  variant='secondary'
56
63
  onPress={onBackPressHandler}
57
- type='ghost'
64
+ type='outline'
58
65
  size='md'
59
- LeadingIcon={ArrowLeft}
66
+ LeadingIcon={Cross}
60
67
  iconOnly
61
68
  />
62
69
 
@@ -1,10 +1,10 @@
1
1
  import React, { useCallback, useMemo } from 'react';
2
- import { Modal, StyleSheet, View } from 'react-native';
3
- import { GestureHandlerRootView } from 'react-native-gesture-handler';
2
+ import { StyleSheet, View } from 'react-native';
4
3
 
5
4
  import { GenericPollButton, PollButtonProps } from './Button';
6
5
  import { PollAnswersList } from './PollAnswersList';
7
6
  import { PollInputDialog } from './PollInputDialog';
7
+ import { PollModal } from './PollModal';
8
8
  import { PollModalHeader } from './PollModalHeader';
9
9
  import { PollAllOptions } from './PollOption';
10
10
  import { PollResults } from './PollResults';
@@ -12,7 +12,6 @@ import { PollResults } from './PollResults';
12
12
  import { useChatContext, usePollContext, useTheme, useTranslationContext } from '../../../contexts';
13
13
  import { primitives } from '../../../theme';
14
14
  import { defaultPollOptionCount } from '../../../utils/constants';
15
- import { SafeAreaViewWrapper } from '../../UIComponents/SafeAreaViewWrapper';
16
15
  import {
17
16
  useAddCommentOpen,
18
17
  useAllCommentsOpen,
@@ -51,14 +50,10 @@ export const ViewResultsButton = (props: PollButtonProps) => {
51
50
  type='outline'
52
51
  />
53
52
  {showResults ? (
54
- <Modal animationType='slide' onRequestClose={closeViewResults} visible={showResults}>
55
- <GestureHandlerRootView style={styles.modalRoot}>
56
- <SafeAreaViewWrapper style={styles.safeArea}>
57
- <PollModalHeader onPress={closeViewResults} title={t('Poll Results')} />
58
- <PollResults message={message} poll={poll} />
59
- </SafeAreaViewWrapper>
60
- </GestureHandlerRootView>
61
- </Modal>
53
+ <PollModal onRequestClose={closeViewResults} visible={showResults}>
54
+ <PollModalHeader onPress={closeViewResults} title={t('Poll Results')} />
55
+ <PollResults message={message} poll={poll} />
56
+ </PollModal>
62
57
  ) : null}
63
58
  </>
64
59
  );
@@ -81,8 +76,6 @@ export const ShowAllOptionsButton = (props: PollButtonProps) => {
81
76
  openAllOptions();
82
77
  }, [message, onPress, openAllOptions, poll]);
83
78
 
84
- const styles = useStyles();
85
-
86
79
  return (
87
80
  <>
88
81
  {options && options.length > defaultPollOptionCount ? (
@@ -92,14 +85,10 @@ export const ShowAllOptionsButton = (props: PollButtonProps) => {
92
85
  />
93
86
  ) : null}
94
87
  {showAllOptions ? (
95
- <Modal animationType='slide' onRequestClose={closeAllOptions} visible={showAllOptions}>
96
- <GestureHandlerRootView style={styles.modalRoot}>
97
- <SafeAreaViewWrapper style={styles.safeArea}>
98
- <PollModalHeader onPress={closeAllOptions} title={t('Poll Options')} />
99
- <PollAllOptions message={message} poll={poll} />
100
- </SafeAreaViewWrapper>
101
- </GestureHandlerRootView>
102
- </Modal>
88
+ <PollModal onRequestClose={closeAllOptions} visible={showAllOptions}>
89
+ <PollModalHeader onPress={closeAllOptions} title={t('Poll Options')} />
90
+ <PollAllOptions message={message} poll={poll} />
91
+ </PollModal>
103
92
  ) : null}
104
93
  </>
105
94
  );
@@ -122,8 +111,6 @@ export const ShowAllCommentsButton = (props: PollButtonProps) => {
122
111
  openAllComments();
123
112
  }, [message, onPress, openAllComments, poll]);
124
113
 
125
- const styles = useStyles();
126
-
127
114
  return (
128
115
  <>
129
116
  {answersCount && answersCount > 0 ? (
@@ -133,14 +120,10 @@ export const ShowAllCommentsButton = (props: PollButtonProps) => {
133
120
  />
134
121
  ) : null}
135
122
  {showAnswers ? (
136
- <Modal animationType='slide' onRequestClose={closeAllComments} visible={showAnswers}>
137
- <GestureHandlerRootView style={styles.modalRoot}>
138
- <SafeAreaViewWrapper style={styles.safeArea}>
139
- <PollModalHeader onPress={closeAllComments} title={t('Poll Comments')} />
140
- <PollAnswersList message={message} poll={poll} />
141
- </SafeAreaViewWrapper>
142
- </GestureHandlerRootView>
143
- </Modal>
123
+ <PollModal onRequestClose={closeAllComments} visible={showAnswers}>
124
+ <PollModalHeader onPress={closeAllComments} title={t('Poll Comments')} />
125
+ <PollAnswersList message={message} poll={poll} />
126
+ </PollModal>
144
127
  ) : null}
145
128
  </>
146
129
  );
@@ -254,9 +237,6 @@ const useStyles = () => {
254
237
  return useMemo(() => {
255
238
  return StyleSheet.create({
256
239
  buttonsContainer: { gap: primitives.spacingXs },
257
- modalRoot: {
258
- flex: 1,
259
- },
260
240
  endVoteButton: {
261
241
  borderColor: isPollCreatedByClient
262
242
  ? semantics.chatBorderOnChatOutgoing
@@ -267,10 +247,6 @@ const useStyles = () => {
267
247
  ? semantics.chatBorderOnChatOutgoing
268
248
  : semantics.chatBorderOnChatIncoming,
269
249
  },
270
- safeArea: {
271
- backgroundColor: semantics.backgroundCoreElevation1,
272
- flex: 1,
273
- },
274
250
  });
275
251
  }, [semantics, isPollCreatedByClient]);
276
252
  };
@@ -72,19 +72,11 @@ export const PollInputDialog = ({
72
72
  />
73
73
  </View>
74
74
  <View style={[styles.buttonContainer, buttonContainer]}>
75
- <Button
76
- variant={'secondary'}
77
- type={'ghost'}
78
- label={t('Cancel')}
79
- size='md'
80
- onPress={closeDialog}
81
- style={styles.button}
82
- />
83
75
  <Button
84
76
  variant={'primary'}
85
77
  type={'solid'}
86
78
  label={t('Send')}
87
- size='md'
79
+ size='lg'
88
80
  onPress={() => {
89
81
  onSubmit(dialogInput);
90
82
  closeDialog();
@@ -92,6 +84,14 @@ export const PollInputDialog = ({
92
84
  style={styles.button}
93
85
  disabled={!dialogInput}
94
86
  />
87
+ <Button
88
+ variant={'secondary'}
89
+ type={'outline'}
90
+ label={t('Cancel')}
91
+ size='lg'
92
+ onPress={closeDialog}
93
+ style={styles.button}
94
+ />
95
95
  </View>
96
96
  </Animated.View>
97
97
  </KeyboardAvoidingView>
@@ -112,8 +112,8 @@ const useStyles = () => {
112
112
  return useMemo(
113
113
  () =>
114
114
  StyleSheet.create({
115
- button: { flex: 1, width: undefined, ...button },
116
- buttonContainer: { flexDirection: 'row', gap: primitives.spacingXs },
115
+ button: { width: undefined, ...button },
116
+ buttonContainer: { gap: primitives.spacingXs },
117
117
  container: {
118
118
  backgroundColor: semantics.backgroundCoreElevation1,
119
119
  borderRadius: primitives.radiusXl,
@@ -132,7 +132,7 @@ const useStyles = () => {
132
132
  input: {
133
133
  alignItems: 'center',
134
134
  borderColor: semantics.borderUtilityActive,
135
- borderRadius: primitives.radiusMd,
135
+ borderRadius: primitives.radiusLg,
136
136
  borderWidth: 1,
137
137
  fontSize: primitives.typographyFontSizeMd,
138
138
  padding: primitives.spacingSm,
@@ -0,0 +1,55 @@
1
+ import React, { PropsWithChildren, useMemo } from 'react';
2
+ import { Modal, ModalProps, StyleSheet } from 'react-native';
3
+ import { GestureHandlerRootView } from 'react-native-gesture-handler';
4
+
5
+ import { useTheme } from '../../../contexts';
6
+ import { SafeAreaViewWrapper } from '../../UIComponents/SafeAreaViewWrapper';
7
+
8
+ export type PollModalProps = PropsWithChildren<{
9
+ animationType?: ModalProps['animationType'];
10
+ onRequestClose?: () => void;
11
+ visible?: boolean;
12
+ }>;
13
+
14
+ export const PollModal = ({
15
+ animationType = 'slide',
16
+ children,
17
+ onRequestClose,
18
+ visible,
19
+ }: PollModalProps) => {
20
+ const styles = useStyles();
21
+
22
+ return (
23
+ <Modal
24
+ animationType={animationType}
25
+ navigationBarTranslucent
26
+ onRequestClose={onRequestClose}
27
+ presentationStyle='pageSheet'
28
+ statusBarTranslucent
29
+ visible={visible}
30
+ >
31
+ <GestureHandlerRootView style={styles.root}>
32
+ <SafeAreaViewWrapper style={styles.safeArea}>{children}</SafeAreaViewWrapper>
33
+ </GestureHandlerRootView>
34
+ </Modal>
35
+ );
36
+ };
37
+
38
+ const useStyles = () => {
39
+ const {
40
+ theme: { semantics },
41
+ } = useTheme();
42
+ return useMemo(
43
+ () =>
44
+ StyleSheet.create({
45
+ root: {
46
+ flex: 1,
47
+ },
48
+ safeArea: {
49
+ flex: 1,
50
+ backgroundColor: semantics.backgroundCoreElevation1,
51
+ },
52
+ }),
53
+ [semantics],
54
+ );
55
+ };
@@ -2,7 +2,7 @@ import React, { useMemo } from 'react';
2
2
  import { StyleSheet, Text, View } from 'react-native';
3
3
 
4
4
  import { useTheme } from '../../../contexts';
5
- import { ArrowLeft } from '../../../icons/arrow-left';
5
+ import { Cross } from '../../../icons/xmark-1';
6
6
  import { primitives } from '../../../theme';
7
7
  import { Button } from '../../ui';
8
8
 
@@ -27,10 +27,10 @@ export const PollModalHeader = ({ onPress, title }: PollModalHeaderProps) => {
27
27
  <Button
28
28
  accessibilityLabelKey='a11y/Close poll'
29
29
  variant='secondary'
30
- type='ghost'
30
+ type='outline'
31
31
  size='md'
32
32
  iconOnly
33
- LeadingIcon={ArrowLeft}
33
+ LeadingIcon={Cross}
34
34
  onPress={onPress}
35
35
  testID='poll-results-close-button'
36
36
  />
@@ -1,6 +1,5 @@
1
1
  import React, { useCallback, useMemo, useState } from 'react';
2
- import { Modal, StyleSheet, Text, View } from 'react-native';
3
- import { GestureHandlerRootView } from 'react-native-gesture-handler';
2
+ import { StyleSheet, Text, View } from 'react-native';
4
3
 
5
4
  import { LocalMessage, Poll, PollOption, PollVote as PollVoteClass } from 'stream-chat';
6
5
 
@@ -15,9 +14,9 @@ import {
15
14
  } from '../../../../contexts';
16
15
 
17
16
  import { primitives } from '../../../../theme';
18
- import { SafeAreaViewWrapper } from '../../../UIComponents/SafeAreaViewWrapper';
19
17
  import { usePollState } from '../../hooks/usePollState';
20
18
  import { GenericPollButton } from '../Button';
19
+ import { PollModal } from '../PollModal';
21
20
  import { PollModalHeader } from '../PollModalHeader';
22
21
 
23
22
  export type ShowAllVotesButtonProps = {
@@ -62,18 +61,14 @@ export const ShowAllVotesButton = (props: ShowAllVotesButtonProps) => {
62
61
  </View>
63
62
  ) : null}
64
63
  {showAllVotes ? (
65
- <Modal
64
+ <PollModal
66
65
  animationType='fade'
67
66
  onRequestClose={() => setShowAllVotes(false)}
68
67
  visible={showAllVotes}
69
68
  >
70
- <GestureHandlerRootView style={styles.modalRoot}>
71
- <SafeAreaViewWrapper style={styles.safeArea}>
72
- <PollModalHeader onPress={() => setShowAllVotes(false)} title={t('Votes')} />
73
- <PollOptionFullResults message={message} option={option} poll={poll} />
74
- </SafeAreaViewWrapper>
75
- </GestureHandlerRootView>
76
- </Modal>
69
+ <PollModalHeader onPress={() => setShowAllVotes(false)} title={t('Votes')} />
70
+ <PollOptionFullResults message={message} option={option} poll={poll} />
71
+ </PollModal>
77
72
  ) : null}
78
73
  </>
79
74
  );
@@ -156,9 +151,6 @@ const useStyles = () => {
156
151
  alignItems: 'center',
157
152
  paddingBottom: primitives.spacingXs,
158
153
  },
159
- modalRoot: {
160
- flex: 1,
161
- },
162
154
  title: {
163
155
  flex: 1,
164
156
  fontSize: primitives.typographyFontSizeLg,
@@ -183,10 +175,6 @@ const useStyles = () => {
183
175
  marginStart: primitives.spacingMd,
184
176
  textAlign: 'left',
185
177
  },
186
- safeArea: {
187
- backgroundColor: semantics.backgroundCoreElevation1,
188
- flex: 1,
189
- },
190
178
  inlineButton: {
191
179
  borderColor: semantics.borderCoreDefault,
192
180
  borderTopWidth: 1,