stream-chat-react-native-core 5.18.0-beta.6 → 5.18.1-beta.1

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.
@@ -3,6 +3,7 @@ import { Keyboard, Platform, SafeAreaView, StyleSheet, View, ViewStyle } from 'r
3
3
  import {
4
4
  PanGestureHandler,
5
5
  PanGestureHandlerGestureEvent,
6
+ ScrollView,
6
7
  State,
7
8
  TapGestureHandler,
8
9
  } from 'react-native-gesture-handler';
@@ -158,6 +159,7 @@ const MessageOverlayWithContext = <
158
159
  const wrapMessageInTheme = clientId === message?.user?.id && !!myMessageTheme;
159
160
 
160
161
  const [myMessageThemeString, setMyMessageThemeString] = useState(JSON.stringify(myMessageTheme));
162
+ const [reactionListHeight, setReactionListHeight] = useState(0);
161
163
 
162
164
  useEffect(() => {
163
165
  if (myMessageTheme) {
@@ -302,6 +304,200 @@ const MessageOverlayWithContext = <
302
304
 
303
305
  const { Attachment, FileAttachmentGroup, Gallery, MessageAvatar, Reply } = messagesContext || {};
304
306
 
307
+ const renderContent = (messageTextNumberOfLines?: number) => (
308
+ <TapGestureHandler
309
+ maxDist={32}
310
+ onHandlerStateChange={({ nativeEvent: { state } }) => {
311
+ if (state === State.END) {
312
+ setOverlay('none');
313
+ }
314
+ }}
315
+ >
316
+ <Animated.View style={[styles.flex, panStyle]}>
317
+ {message && (
318
+ <View
319
+ style={[
320
+ styles.center,
321
+ styles.overlayPadding,
322
+ { padding: overlayPadding },
323
+ alignment === 'left' ? styles.alignStart : styles.alignEnd,
324
+ ]}
325
+ >
326
+ {handleReaction && ownCapabilities?.sendReaction ? (
327
+ <OverlayReactionList
328
+ messageLayout={messageLayout}
329
+ ownReactionTypes={message?.own_reactions?.map((reaction) => reaction.type) || []}
330
+ setReactionListHeight={setReactionListHeight}
331
+ showScreen={showScreen}
332
+ />
333
+ ) : null}
334
+ <Animated.View
335
+ onLayout={({
336
+ nativeEvent: {
337
+ layout: { height: layoutHeight, width: layoutWidth, x, y },
338
+ },
339
+ }) => {
340
+ messageLayout.value = {
341
+ x: alignment === 'left' ? x + layoutWidth : x,
342
+ y,
343
+ };
344
+ messageWidth.value = layoutWidth;
345
+ messageHeight.value = layoutHeight;
346
+ }}
347
+ style={[styles.alignEnd, styles.row, showScreenStyle]}
348
+ >
349
+ {alignment === 'left' && MessageAvatar && (
350
+ <MessageAvatar {...{ alignment, message, showAvatar: true }} />
351
+ )}
352
+ <View
353
+ pointerEvents='none'
354
+ style={[
355
+ styles.containerInner,
356
+ {
357
+ backgroundColor:
358
+ onlyEmojis && !message.quoted_message
359
+ ? transparent
360
+ : otherAttachments?.length
361
+ ? otherAttachments[0].type === 'giphy'
362
+ ? !message.quoted_message
363
+ ? transparent
364
+ : grey_gainsboro
365
+ : blue_alice
366
+ : alignment === 'left'
367
+ ? white_smoke
368
+ : grey_gainsboro,
369
+ borderBottomLeftRadius:
370
+ (groupStyle === 'left_bottom' || groupStyle === 'left_single') &&
371
+ (!hasThreadReplies || threadList)
372
+ ? borderRadiusS
373
+ : borderRadiusL,
374
+ borderBottomRightRadius:
375
+ (groupStyle === 'right_bottom' || groupStyle === 'right_single') &&
376
+ (!hasThreadReplies || threadList)
377
+ ? borderRadiusS
378
+ : borderRadiusL,
379
+ borderColor: grey_whisper,
380
+ },
381
+ (onlyEmojis && !message.quoted_message) || otherAttachments?.length
382
+ ? { borderWidth: 0 }
383
+ : {},
384
+ containerInner,
385
+ ]}
386
+ >
387
+ {messagesContext?.messageContentOrder?.map(
388
+ (messageContentType, messageContentOrderIndex) => {
389
+ switch (messageContentType) {
390
+ case 'quoted_reply':
391
+ return (
392
+ message.quoted_message &&
393
+ Reply && (
394
+ <View
395
+ key={`quoted_reply_${messageContentOrderIndex}`}
396
+ style={[styles.replyContainer, replyContainer]}
397
+ >
398
+ <Reply
399
+ quotedMessage={
400
+ message.quoted_message as ReplyProps<StreamChatGenerics>['quotedMessage']
401
+ }
402
+ styles={{
403
+ messageContainer: {
404
+ maxWidth: vw(60),
405
+ },
406
+ }}
407
+ />
408
+ </View>
409
+ )
410
+ );
411
+ case 'attachments':
412
+ return otherAttachments?.map(
413
+ (attachment, attachmentIndex) =>
414
+ Attachment && (
415
+ <Attachment
416
+ attachment={attachment}
417
+ key={`${message.id}-${attachmentIndex}`}
418
+ />
419
+ ),
420
+ );
421
+ case 'files':
422
+ return (
423
+ FileAttachmentGroup && (
424
+ <FileAttachmentGroup
425
+ files={files}
426
+ key={`file_attachment_group_${messageContentOrderIndex}`}
427
+ messageId={message.id}
428
+ />
429
+ )
430
+ );
431
+ case 'gallery':
432
+ return (
433
+ Gallery && (
434
+ <Gallery
435
+ alignment={alignment}
436
+ groupStyles={groupStyles}
437
+ hasThreadReplies={!!message?.reply_count}
438
+ images={images}
439
+ key={`gallery_${messageContentOrderIndex}`}
440
+ message={message}
441
+ threadList={threadList}
442
+ videos={videos}
443
+ />
444
+ )
445
+ );
446
+ case 'text':
447
+ default:
448
+ return otherAttachments?.length && otherAttachments[0].actions ? null : (
449
+ <MessageTextContainer<StreamChatGenerics>
450
+ key={`message_text_container_${messageContentOrderIndex}`}
451
+ message={message}
452
+ messageOverlay
453
+ messageTextNumberOfLines={messageTextNumberOfLines}
454
+ onlyEmojis={onlyEmojis}
455
+ />
456
+ );
457
+ }
458
+ },
459
+ )}
460
+ </View>
461
+ </Animated.View>
462
+ {messageActions && (
463
+ <MessageActionList
464
+ MessageActionListItem={MessageActionListItem}
465
+ showScreen={showScreen}
466
+ {...messageActionProps}
467
+ message={message}
468
+ />
469
+ )}
470
+ {!!messageReactionTitle &&
471
+ message.latest_reactions &&
472
+ message.latest_reactions.length > 0 ? (
473
+ <OverlayReactions
474
+ alignment={alignment}
475
+ OverlayReactionsAvatar={OverlayReactionsAvatar}
476
+ reactions={
477
+ message.latest_reactions.map((reaction) => ({
478
+ alignment: clientId && clientId === reaction.user?.id ? 'right' : 'left',
479
+ id: reaction?.user?.id || '',
480
+ image: reaction?.user?.image,
481
+ name: reaction?.user?.name || reaction.user_id || '',
482
+ type: reaction.type,
483
+ })) as Reaction[]
484
+ }
485
+ showScreen={showScreen}
486
+ supportedReactions={messagesContext?.supportedReactions}
487
+ title={messageReactionTitle}
488
+ />
489
+ ) : null}
490
+ </View>
491
+ )}
492
+ </Animated.View>
493
+ </TapGestureHandler>
494
+ );
495
+
496
+ // Scroll will only be enabled for message overlay when we show actions.
497
+ // When we show the reactions, we don't want to enable scroll since OverlayReactions component
498
+ // in itself is scrollable (FlatList). FlatList inside a ScrollView is not a good idea and results in error from RN.
499
+ const isScrollEnabled = !!messageActions && overlay === 'message';
500
+
305
501
  return (
306
502
  <ChatProvider value={chatContext}>
307
503
  <MessagesProvider value={messagesContext}>
@@ -319,198 +515,23 @@ const MessageOverlayWithContext = <
319
515
  >
320
516
  <Animated.View style={[StyleSheet.absoluteFillObject]}>
321
517
  <SafeAreaView style={styles.flex}>
322
- <TapGestureHandler
323
- maxDist={32}
324
- onHandlerStateChange={({ nativeEvent: { state } }) => {
325
- if (state === State.END) {
326
- setOverlay('none');
327
- }
328
- }}
329
- >
330
- <Animated.View style={[styles.flex, panStyle]}>
331
- {message && (
332
- <View
333
- style={[
334
- styles.center,
335
- styles.overlayPadding,
336
- { padding: overlayPadding },
337
- alignment === 'left' ? styles.alignStart : styles.alignEnd,
338
- ]}
339
- >
340
- {handleReaction && ownCapabilities?.sendReaction ? (
341
- <OverlayReactionList
342
- messageLayout={messageLayout}
343
- ownReactionTypes={
344
- message?.own_reactions?.map((reaction) => reaction.type) || []
345
- }
346
- showScreen={showScreen}
347
- />
348
- ) : null}
349
- <Animated.View
350
- onLayout={({
351
- nativeEvent: {
352
- layout: { height: layoutHeight, width: layoutWidth, x, y },
353
- },
354
- }) => {
355
- messageLayout.value = {
356
- x: alignment === 'left' ? x + layoutWidth : x,
357
- y,
358
- };
359
- messageWidth.value = layoutWidth;
360
- messageHeight.value = layoutHeight;
361
- }}
362
- style={[styles.alignEnd, styles.row, showScreenStyle]}
363
- >
364
- {alignment === 'left' && MessageAvatar && (
365
- <MessageAvatar {...{ alignment, message, showAvatar: true }} />
366
- )}
367
- <View
368
- pointerEvents='none'
369
- style={[
370
- styles.containerInner,
371
- {
372
- backgroundColor:
373
- onlyEmojis && !message.quoted_message
374
- ? transparent
375
- : otherAttachments?.length
376
- ? otherAttachments[0].type === 'giphy'
377
- ? !message.quoted_message
378
- ? transparent
379
- : grey_gainsboro
380
- : blue_alice
381
- : alignment === 'left'
382
- ? white_smoke
383
- : grey_gainsboro,
384
- borderBottomLeftRadius:
385
- (groupStyle === 'left_bottom' ||
386
- groupStyle === 'left_single') &&
387
- (!hasThreadReplies || threadList)
388
- ? borderRadiusS
389
- : borderRadiusL,
390
- borderBottomRightRadius:
391
- (groupStyle === 'right_bottom' ||
392
- groupStyle === 'right_single') &&
393
- (!hasThreadReplies || threadList)
394
- ? borderRadiusS
395
- : borderRadiusL,
396
- borderColor: grey_whisper,
397
- },
398
- (onlyEmojis && !message.quoted_message) ||
399
- otherAttachments?.length
400
- ? { borderWidth: 0 }
401
- : {},
402
- containerInner,
403
- ]}
404
- >
405
- {messagesContext?.messageContentOrder?.map(
406
- (messageContentType, messageContentOrderIndex) => {
407
- switch (messageContentType) {
408
- case 'quoted_reply':
409
- return (
410
- message.quoted_message &&
411
- Reply && (
412
- <View
413
- key={`quoted_reply_${messageContentOrderIndex}`}
414
- style={[styles.replyContainer, replyContainer]}
415
- >
416
- <Reply
417
- quotedMessage={
418
- message.quoted_message as ReplyProps<StreamChatGenerics>['quotedMessage']
419
- }
420
- styles={{
421
- messageContainer: {
422
- maxWidth: vw(60),
423
- },
424
- }}
425
- />
426
- </View>
427
- )
428
- );
429
- case 'attachments':
430
- return otherAttachments?.map(
431
- (attachment, attachmentIndex) =>
432
- Attachment && (
433
- <Attachment
434
- attachment={attachment}
435
- key={`${message.id}-${attachmentIndex}`}
436
- />
437
- ),
438
- );
439
- case 'files':
440
- return (
441
- FileAttachmentGroup && (
442
- <FileAttachmentGroup
443
- files={files}
444
- key={`file_attachment_group_${messageContentOrderIndex}`}
445
- messageId={message.id}
446
- />
447
- )
448
- );
449
- case 'gallery':
450
- return (
451
- Gallery && (
452
- <Gallery
453
- alignment={alignment}
454
- groupStyles={groupStyles}
455
- hasThreadReplies={!!message?.reply_count}
456
- images={images}
457
- key={`gallery_${messageContentOrderIndex}`}
458
- message={message}
459
- threadList={threadList}
460
- videos={videos}
461
- />
462
- )
463
- );
464
- case 'text':
465
- default:
466
- return otherAttachments?.length &&
467
- otherAttachments[0].actions ? null : (
468
- <MessageTextContainer<StreamChatGenerics>
469
- key={`message_text_container_${messageContentOrderIndex}`}
470
- message={message}
471
- messageOverlay
472
- messageTextNumberOfLines={messageTextNumberOfLines}
473
- onlyEmojis={onlyEmojis}
474
- />
475
- );
476
- }
477
- },
478
- )}
479
- </View>
480
- </Animated.View>
481
- {messageActions && (
482
- <MessageActionList
483
- MessageActionListItem={MessageActionListItem}
484
- showScreen={showScreen}
485
- {...messageActionProps}
486
- message={message}
487
- />
488
- )}
489
- {!!messageReactionTitle &&
490
- message.latest_reactions &&
491
- message.latest_reactions.length > 0 ? (
492
- <OverlayReactions
493
- alignment={alignment}
494
- OverlayReactionsAvatar={OverlayReactionsAvatar}
495
- reactions={
496
- message.latest_reactions.map((reaction) => ({
497
- alignment:
498
- clientId && clientId === reaction.user?.id ? 'right' : 'left',
499
- id: reaction?.user?.id || '',
500
- image: reaction?.user?.image,
501
- name: reaction?.user?.name || reaction.user_id || '',
502
- type: reaction.type,
503
- })) as Reaction[]
504
- }
505
- showScreen={showScreen}
506
- supportedReactions={messagesContext?.supportedReactions}
507
- title={messageReactionTitle}
508
- />
509
- ) : null}
510
- </View>
511
- )}
512
- </Animated.View>
513
- </TapGestureHandler>
518
+ {isScrollEnabled ? (
519
+ <ScrollView
520
+ alwaysBounceVertical={false}
521
+ contentContainerStyle={[
522
+ styles.center,
523
+ {
524
+ paddingTop: reactionListHeight,
525
+ },
526
+ ]}
527
+ showsVerticalScrollIndicator={false}
528
+ style={[styles.flex, styles.scrollView]}
529
+ >
530
+ {renderContent()}
531
+ </ScrollView>
532
+ ) : (
533
+ renderContent(messageTextNumberOfLines)
534
+ )}
514
535
  </SafeAreaView>
515
536
  </Animated.View>
516
537
  </PanGestureHandler>
@@ -239,6 +239,7 @@ export type OverlayReactionListPropsWithContext<
239
239
  y: number;
240
240
  }>;
241
241
  ownReactionTypes: string[];
242
+ setReactionListHeight: React.Dispatch<React.SetStateAction<number>>;
242
243
  showScreen: Animated.SharedValue<number>;
243
244
  fill?: FillProps['fill'];
244
245
  };
@@ -254,6 +255,7 @@ const OverlayReactionListWithContext = <
254
255
  handleReaction,
255
256
  messageLayout,
256
257
  ownReactionTypes,
258
+ setReactionListHeight,
257
259
  showScreen,
258
260
  setOverlay,
259
261
  supportedReactions = reactionData,
@@ -354,6 +356,7 @@ const OverlayReactionListWithContext = <
354
356
  }) => {
355
357
  reactionListLayout.value = { height, width: layoutWidth };
356
358
  reactionListHeight.value = height;
359
+ setReactionListHeight(height);
357
360
  }}
358
361
  style={[
359
362
  styles.reactionList,
package/src/version.json CHANGED
@@ -1,3 +1,3 @@
1
1
  {
2
- "version": "5.18.0-beta.6"
2
+ "version": "5.18.1-beta.1"
3
3
  }