@selfcommunity/react-ui 0.7.0-alpha.318 → 0.7.0-alpha.319

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.
@@ -64,6 +64,11 @@ export interface CommentObjectProps {
64
64
  * @default null
65
65
  */
66
66
  onDelete?: (comment: SCCommentType) => void;
67
+ /**
68
+ * Show all summary initially (otherwise it will be truncated)
69
+ * @default false
70
+ */
71
+ truncateContent?: boolean;
67
72
  /**
68
73
  * Props to spread to single comment object skeleton
69
74
  * @default {elevation: 0}
@@ -95,7 +95,7 @@ function CommentObject(inProps) {
95
95
  props: inProps,
96
96
  name: PREFIX
97
97
  });
98
- const { id = `comment_object_${props.commentObjectId ? props.commentObjectId : props.commentObject ? props.commentObject.id : ''}`, className, commentObjectId, commentObject, feedObjectId, feedObject, feedObjectType = types_1.SCContributionType.POST, commentReply, onOpenReply, onDelete, onVote, elevation = 0, CommentObjectSkeletonProps = { elevation, WidgetProps: { variant: 'outlined' } }, CommentObjectReplyProps = { elevation, WidgetProps: { variant: 'outlined' } }, linkableCommentDateTime = true, cacheStrategy = utils_1.CacheStrategies.NETWORK_ONLY } = props, rest = tslib_1.__rest(props, ["id", "className", "commentObjectId", "commentObject", "feedObjectId", "feedObject", "feedObjectType", "commentReply", "onOpenReply", "onDelete", "onVote", "elevation", "CommentObjectSkeletonProps", "CommentObjectReplyProps", "linkableCommentDateTime", "cacheStrategy"]);
98
+ const { id = `comment_object_${props.commentObjectId ? props.commentObjectId : props.commentObject ? props.commentObject.id : ''}`, className, commentObjectId, commentObject, feedObjectId, feedObject, feedObjectType = types_1.SCContributionType.POST, commentReply, onOpenReply, onDelete, onVote, elevation = 0, truncateContent = false, CommentObjectSkeletonProps = { elevation, WidgetProps: { variant: 'outlined' } }, CommentObjectReplyProps = { elevation, WidgetProps: { variant: 'outlined' } }, linkableCommentDateTime = true, cacheStrategy = utils_1.CacheStrategies.NETWORK_ONLY } = props, rest = tslib_1.__rest(props, ["id", "className", "commentObjectId", "commentObject", "feedObjectId", "feedObject", "feedObjectType", "commentReply", "onOpenReply", "onDelete", "onVote", "elevation", "truncateContent", "CommentObjectSkeletonProps", "CommentObjectReplyProps", "linkableCommentDateTime", "cacheStrategy"]);
99
99
  // CONTEXT
100
100
  const scContext = (0, react_core_1.useSCContext)();
101
101
  const scUserContext = (0, react_1.useContext)(react_core_1.SCUserContext);
@@ -329,7 +329,7 @@ function CommentObject(inProps) {
329
329
  // or the comment author is the logged user
330
330
  return null;
331
331
  }
332
- const commentHtml = comment.summary_html ? comment.summary_html : comment.html;
332
+ const commentHtml = comment.summary_html && truncateContent ? comment.summary_html : comment.html;
333
333
  const summaryHtmlTruncated = comment.summary_truncated ? comment.summary_truncated : false;
334
334
  const summaryHtml = (0, contribution_1.getContributionHtml)(commentHtml, scRoutingContext.url);
335
335
  return (react_1.default.createElement(react_1.default.Fragment, { key: comment.id },
@@ -342,7 +342,7 @@ function CommentObject(inProps) {
342
342
  react_1.default.createElement(react_core_1.Link, Object.assign({ className: classes.author }, (!comment.author.deleted && { to: scRoutingContext.url(react_core_1.SCRoutes.USER_PROFILE_ROUTE_NAME, comment.author) }), { onClick: comment.author.deleted ? () => setOpenAlert(true) : null }),
343
343
  react_1.default.createElement(material_1.Typography, { component: "span" }, comment.author.username)),
344
344
  react_1.default.createElement(material_1.Typography, { className: classes.textContent, variant: "body2", gutterBottom: true, dangerouslySetInnerHTML: { __html: summaryHtml } }),
345
- summaryHtmlTruncated && (react_1.default.createElement(react_core_1.Link, { to: scRoutingContext.url(react_core_1.SCRoutes.COMMENT_ROUTE_NAME, (0, contribution_1.getRouteData)(comment)), className: classes.showMoreContent },
345
+ summaryHtmlTruncated && truncateContent && (react_1.default.createElement(react_core_1.Link, { to: scRoutingContext.url(react_core_1.SCRoutes.COMMENT_ROUTE_NAME, (0, contribution_1.getRouteData)(comment)), className: classes.showMoreContent },
346
346
  react_1.default.createElement(react_intl_1.FormattedMessage, { id: "ui.commentObject.showMore", defaultMessage: "ui.commentObject.showMore" })))),
347
347
  scUserContext.user && (react_1.default.createElement(material_1.Box, { className: classes.commentActionsMenu },
348
348
  react_1.default.createElement(ContributionActionsMenu_1.default, { commentObject: comment, onRestoreContribution: handleRestore, onHideContribution: handleHide, onDeleteContribution: handleDelete, onEditContribution: handleEdit })))),
@@ -8,10 +8,11 @@ const LexicalComposerContext_1 = require("@lexical/react/LexicalComposerContext"
8
8
  const useLexicalNodeSelection_1 = require("@lexical/react/useLexicalNodeSelection");
9
9
  const utils_1 = require("@lexical/utils");
10
10
  /**
11
- * Limit the width of an image
11
+ * Limit the width of an image (min/max)
12
12
  * Used to compute the padding-bottom of the div that wrap the img
13
13
  */
14
- const IMAGE_WIDTH_THRESHOLD = 500;
14
+ const IMAGE_MAX_WIDTH_THRESHOLD = 500;
15
+ const IMAGE_MIN_WIDTH_THRESHOLD = 375;
15
16
  /**
16
17
  * Calc aspect-ratio of image
17
18
  * @param width
@@ -35,13 +36,9 @@ function useSuspenseImage(src) {
35
36
  }
36
37
  function LazyImage({ altText, className, imageRef, src, width, height }) {
37
38
  useSuspenseImage(src);
38
- const aspectRatio = getAspectRatio(IMAGE_WIDTH_THRESHOLD, height);
39
+ const aspectRatio = getAspectRatio(width >= IMAGE_MAX_WIDTH_THRESHOLD ? width : IMAGE_MAX_WIDTH_THRESHOLD, height);
39
40
  return (react_1.default.createElement("div", { draggable: false, className: className, style: { position: 'relative', paddingBottom: `${100 / aspectRatio}%` } },
40
- react_1.default.createElement("img", { src: src, alt: altText, ref: imageRef, style: {
41
- position: 'absolute',
42
- height: `100%`,
43
- width: `100%`
44
- } })));
41
+ react_1.default.createElement("img", { src: src, alt: altText, ref: imageRef, style: Object.assign({ position: 'absolute' }, (width < IMAGE_MIN_WIDTH_THRESHOLD ? { paddingRight: IMAGE_MIN_WIDTH_THRESHOLD - width } : {})) })));
45
42
  }
46
43
  function ImageComponent({ src, altText, nodeKey, width, height }) {
47
44
  const imageRef = (0, react_1.useRef)(null);
@@ -32,11 +32,13 @@ function Image({ editor, className = '' }) {
32
32
  return file.type.startsWith('image/');
33
33
  };
34
34
  const handleUploadSuccess = (media) => {
35
- const image = media.image_thumbnail ? media.image_thumbnail : {
36
- url: media.image,
37
- width: media.image_width,
38
- height: media.image_height
39
- };
35
+ const image = media.image_thumbnail
36
+ ? media.image_thumbnail
37
+ : {
38
+ url: media.image,
39
+ width: media.image_width,
40
+ height: media.image_height
41
+ };
40
42
  const data = {
41
43
  altText: media.title,
42
44
  src: image.url,
@@ -42,7 +42,7 @@ function Activities(inProps) {
42
42
  feedObject,
43
43
  feedObjectType,
44
44
  cacheStrategy,
45
- pageSize: 3,
45
+ pageSize: 2,
46
46
  orderBy: selectedActivities === feedObject_1.SCFeedObjectActivitiesType.CONNECTIONS_COMMENTS
47
47
  ? comments_1.SCCommentsOrderBy.CONNECTION_DESC
48
48
  : selectedActivities === feedObject_1.SCFeedObjectActivitiesType.FIRST_COMMENTS
@@ -50,7 +50,7 @@ function Activities(inProps) {
50
50
  : comments_1.SCCommentsOrderBy.ADDED_AT_DESC
51
51
  });
52
52
  const objId = commentsObject.feedObject ? commentsObject.feedObject.id : null;
53
- const skeletonsCount = Math.min(3, commentsObject.feedObject ? commentsObject.feedObject.comment_count : 3);
53
+ const skeletonsCount = Math.min(3, commentsObject.feedObject ? commentsObject.feedObject.comment_count : 2);
54
54
  const existFeedObjectActivities = feedObjectActivities && feedObjectActivities.length > 0;
55
55
  /**
56
56
  * Sync activities type if prop change
@@ -80,11 +80,17 @@ function Activities(inProps) {
80
80
  function renderRelevantActivities() {
81
81
  return react_1.default.createElement(RelevantActivities_1.default, { activities: feedObjectActivities });
82
82
  }
83
+ /**
84
+ * Load comments
85
+ */
86
+ function handleNext() {
87
+ commentsObject.getNextPage();
88
+ }
83
89
  /**
84
90
  * Render comments of feedObject
85
91
  */
86
92
  function renderComments() {
87
- return (react_1.default.createElement(react_1.default.Fragment, null, (commentsObject.feedObject.comment_count > 0 || comments.length > 0) && (react_1.default.createElement(CommentsObject_1.default, Object.assign({ feedObject: commentsObject.feedObject, comments: commentsObject.comments, startComments: comments, next: commentsObject.next, isLoadingNext: commentsObject.isLoadingNext, handleNext: commentsObject.getNextPage, totalLoadedComments: commentsObject.comments.length + comments.length, totalComments: commentsObject.feedObject.comment_count, hideAdvertising: true, cacheStrategy: cacheStrategy }, CommentsObjectProps, { CommentsObjectSkeletonProps: { count: skeletonsCount }, CommentComponentProps: Object.assign(Object.assign({}, CommentComponentProps), { cacheStrategy }) })))));
93
+ return (react_1.default.createElement(react_1.default.Fragment, null, (commentsObject.feedObject.comment_count > 0 || comments.length > 0) && (react_1.default.createElement(CommentsObject_1.default, Object.assign({ feedObject: commentsObject.feedObject, comments: commentsObject.comments, startComments: comments, next: commentsObject.next, isLoadingNext: commentsObject.isLoadingNext, handleNext: handleNext, totalLoadedComments: commentsObject.comments.length + comments.length, totalComments: commentsObject.feedObject.comment_count, hideAdvertising: true }, CommentsObjectProps, { cacheStrategy: cacheStrategy, CommentsObjectSkeletonProps: { count: skeletonsCount }, CommentComponentProps: Object.assign(Object.assign(Object.assign({}, CommentComponentProps), { cacheStrategy }), (CommentsObjectProps.CommentComponentProps ? CommentsObjectProps.CommentComponentProps : {})) })))));
88
94
  }
89
95
  /**
90
96
  * Renders root object
@@ -458,7 +458,7 @@ function FeedObject(inProps) {
458
458
  template === feedObject_1.SCFeedObjectTemplateType.PREVIEW && (obj.comment_count > 0 || (feedObjectActivities && feedObjectActivities.length > 0)) && (react_1.default.createElement(material_1.Collapse, { in: expandedActivities, timeout: "auto", classes: { root: classes.activitiesSection } },
459
459
  react_1.default.createElement(CardContent_1.default, { className: classes.activitiesContent },
460
460
  react_1.default.createElement(Activities_1.default, Object.assign({ feedObject: obj, key: selectedActivities, feedObjectActivities: feedObjectActivities, activitiesType: selectedActivities, onSetSelectedActivities: handleSelectedActivities, comments: comments, CommentsObjectProps: {
461
- CommentComponentProps: Object.assign({ onDelete: handleDeleteComment }, CommentComponentProps),
461
+ CommentComponentProps: Object.assign({ onDelete: handleDeleteComment, truncateContent: true }, CommentComponentProps),
462
462
  CommentObjectSkeletonProps: CommentObjectSkeletonProps
463
463
  }, cacheStrategy: cacheStrategy }, ActivitiesProps))))),
464
464
  composerOpen && (react_1.default.createElement(Composer_1.default, { open: composerOpen, feedObject: obj, onClose: handleToggleEdit, onSuccess: handleEditSuccess, maxWidth: "sm", fullWidth: true, scroll: "body" })))) : (react_1.default.createElement(Skeleton_1.default, Object.assign({ template: template }, FeedObjectSkeletonProps)))));
@@ -99,9 +99,13 @@ function PrivateMessageEditor(inProps) {
99
99
  setMessage(event.target.value);
100
100
  };
101
101
  const handleEmojiClick = (emojiData, event) => {
102
- const cursor = ref.current.selectionStart;
103
- const text = message.slice(0, cursor) + emojiData.emoji;
104
- setMessage(text);
102
+ const cursorPosition = ref.current.selectionEnd;
103
+ const start = ref.current.value.substring(0, ref.current.selectionStart);
104
+ const end = ref.current.value.substring(ref.current.selectionStart);
105
+ setMessage(start + emojiData.emoji + end);
106
+ setTimeout(() => {
107
+ ref.current.selectionStart = ref.current.selectionEnd = cursorPosition + emojiData.emoji.length;
108
+ }, 50);
105
109
  };
106
110
  // EFFECTS
107
111
  (0, react_1.useEffect)(() => {
@@ -129,8 +133,7 @@ function PrivateMessageEditor(inProps) {
129
133
  return (react_1.default.createElement(react_1.default.Fragment, null, openMediaSection ? (react_1.default.createElement(MessageMediaUploader_1.default, { className: classes.uploadMediaSection, open: openMediaSection, onClose: handleMediaSectionClose, forwardMessageFile: handleMessageFiles, isUploading: setUploading, action: react_1.default.createElement(material_1.IconButton, { disabled: (!message && !messageFiles.length) || uploading, onClick: handleMessageSend },
130
134
  react_1.default.createElement(Icon_1.default, null, "send")) })) : (react_1.default.createElement(react_1.default.Fragment, null,
131
135
  openEmojiSection && react_1.default.createElement(EmojiPicker_1.default, { className: classes.emojiSection, onEmojiClick: handleEmojiClick, width: "100%", searchDisabled: true }),
132
- react_1.default.createElement(material_1.TextField, { size: "small", disabled: Boolean(messageFiles.length) || openMediaSection, ref: ref, className: classes.messageInput, multiline: true, placeholder: `${intl.formatMessage(messages.placeholder)}`, value: message, onChange: handleMessageInput, maxRows: 2, onSelect: () => setOpenEmojiSection(false), InputProps: {
133
- disableUnderline: true,
136
+ react_1.default.createElement(material_1.TextField, { size: "small", inputRef: ref, disabled: Boolean(messageFiles.length) || openMediaSection, className: classes.messageInput, multiline: true, placeholder: `${intl.formatMessage(messages.placeholder)}`, value: message, onChange: handleMessageInput, maxRows: 2, onSelect: () => setOpenEmojiSection(false), InputProps: {
134
137
  startAdornment: (react_1.default.createElement(react_1.default.Fragment, null,
135
138
  react_1.default.createElement(material_1.IconButton, { disabled: openMediaSection, onClick: () => setOpenEmojiSection(!openEmojiSection) },
136
139
  react_1.default.createElement(Icon_1.default, null, "sentiment_satisfied_alt")),
@@ -64,6 +64,11 @@ export interface CommentObjectProps {
64
64
  * @default null
65
65
  */
66
66
  onDelete?: (comment: SCCommentType) => void;
67
+ /**
68
+ * Show all summary initially (otherwise it will be truncated)
69
+ * @default false
70
+ */
71
+ truncateContent?: boolean;
67
72
  /**
68
73
  * Props to spread to single comment object skeleton
69
74
  * @default {elevation: 0}
@@ -93,7 +93,7 @@ export default function CommentObject(inProps) {
93
93
  props: inProps,
94
94
  name: PREFIX
95
95
  });
96
- const { id = `comment_object_${props.commentObjectId ? props.commentObjectId : props.commentObject ? props.commentObject.id : ''}`, className, commentObjectId, commentObject, feedObjectId, feedObject, feedObjectType = SCContributionType.POST, commentReply, onOpenReply, onDelete, onVote, elevation = 0, CommentObjectSkeletonProps = { elevation, WidgetProps: { variant: 'outlined' } }, CommentObjectReplyProps = { elevation, WidgetProps: { variant: 'outlined' } }, linkableCommentDateTime = true, cacheStrategy = CacheStrategies.NETWORK_ONLY } = props, rest = __rest(props, ["id", "className", "commentObjectId", "commentObject", "feedObjectId", "feedObject", "feedObjectType", "commentReply", "onOpenReply", "onDelete", "onVote", "elevation", "CommentObjectSkeletonProps", "CommentObjectReplyProps", "linkableCommentDateTime", "cacheStrategy"]);
96
+ const { id = `comment_object_${props.commentObjectId ? props.commentObjectId : props.commentObject ? props.commentObject.id : ''}`, className, commentObjectId, commentObject, feedObjectId, feedObject, feedObjectType = SCContributionType.POST, commentReply, onOpenReply, onDelete, onVote, elevation = 0, truncateContent = false, CommentObjectSkeletonProps = { elevation, WidgetProps: { variant: 'outlined' } }, CommentObjectReplyProps = { elevation, WidgetProps: { variant: 'outlined' } }, linkableCommentDateTime = true, cacheStrategy = CacheStrategies.NETWORK_ONLY } = props, rest = __rest(props, ["id", "className", "commentObjectId", "commentObject", "feedObjectId", "feedObject", "feedObjectType", "commentReply", "onOpenReply", "onDelete", "onVote", "elevation", "truncateContent", "CommentObjectSkeletonProps", "CommentObjectReplyProps", "linkableCommentDateTime", "cacheStrategy"]);
97
97
  // CONTEXT
98
98
  const scContext = useSCContext();
99
99
  const scUserContext = useContext(SCUserContext);
@@ -327,7 +327,7 @@ export default function CommentObject(inProps) {
327
327
  // or the comment author is the logged user
328
328
  return null;
329
329
  }
330
- const commentHtml = comment.summary_html ? comment.summary_html : comment.html;
330
+ const commentHtml = comment.summary_html && truncateContent ? comment.summary_html : comment.html;
331
331
  const summaryHtmlTruncated = comment.summary_truncated ? comment.summary_truncated : false;
332
332
  const summaryHtml = getContributionHtml(commentHtml, scRoutingContext.url);
333
333
  return (React.createElement(React.Fragment, { key: comment.id },
@@ -340,7 +340,7 @@ export default function CommentObject(inProps) {
340
340
  React.createElement(Link, Object.assign({ className: classes.author }, (!comment.author.deleted && { to: scRoutingContext.url(SCRoutes.USER_PROFILE_ROUTE_NAME, comment.author) }), { onClick: comment.author.deleted ? () => setOpenAlert(true) : null }),
341
341
  React.createElement(Typography, { component: "span" }, comment.author.username)),
342
342
  React.createElement(Typography, { className: classes.textContent, variant: "body2", gutterBottom: true, dangerouslySetInnerHTML: { __html: summaryHtml } }),
343
- summaryHtmlTruncated && (React.createElement(Link, { to: scRoutingContext.url(SCRoutes.COMMENT_ROUTE_NAME, getRouteData(comment)), className: classes.showMoreContent },
343
+ summaryHtmlTruncated && truncateContent && (React.createElement(Link, { to: scRoutingContext.url(SCRoutes.COMMENT_ROUTE_NAME, getRouteData(comment)), className: classes.showMoreContent },
344
344
  React.createElement(FormattedMessage, { id: "ui.commentObject.showMore", defaultMessage: "ui.commentObject.showMore" })))),
345
345
  scUserContext.user && (React.createElement(Box, { className: classes.commentActionsMenu },
346
346
  React.createElement(ContributionActionsMenu, { commentObject: comment, onRestoreContribution: handleRestore, onHideContribution: handleHide, onDeleteContribution: handleDelete, onEditContribution: handleEdit })))),
@@ -4,10 +4,11 @@ import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext
4
4
  import { useLexicalNodeSelection } from '@lexical/react/useLexicalNodeSelection';
5
5
  import { mergeRegister } from '@lexical/utils';
6
6
  /**
7
- * Limit the width of an image
7
+ * Limit the width of an image (min/max)
8
8
  * Used to compute the padding-bottom of the div that wrap the img
9
9
  */
10
- const IMAGE_WIDTH_THRESHOLD = 500;
10
+ const IMAGE_MAX_WIDTH_THRESHOLD = 500;
11
+ const IMAGE_MIN_WIDTH_THRESHOLD = 375;
11
12
  /**
12
13
  * Calc aspect-ratio of image
13
14
  * @param width
@@ -31,13 +32,9 @@ function useSuspenseImage(src) {
31
32
  }
32
33
  function LazyImage({ altText, className, imageRef, src, width, height }) {
33
34
  useSuspenseImage(src);
34
- const aspectRatio = getAspectRatio(IMAGE_WIDTH_THRESHOLD, height);
35
+ const aspectRatio = getAspectRatio(width >= IMAGE_MAX_WIDTH_THRESHOLD ? width : IMAGE_MAX_WIDTH_THRESHOLD, height);
35
36
  return (React.createElement("div", { draggable: false, className: className, style: { position: 'relative', paddingBottom: `${100 / aspectRatio}%` } },
36
- React.createElement("img", { src: src, alt: altText, ref: imageRef, style: {
37
- position: 'absolute',
38
- height: `100%`,
39
- width: `100%`
40
- } })));
37
+ React.createElement("img", { src: src, alt: altText, ref: imageRef, style: Object.assign({ position: 'absolute' }, (width < IMAGE_MIN_WIDTH_THRESHOLD ? { paddingRight: IMAGE_MIN_WIDTH_THRESHOLD - width } : {})) })));
41
38
  }
42
39
  function ImageComponent({ src, altText, nodeKey, width, height }) {
43
40
  const imageRef = useRef(null);
@@ -29,11 +29,13 @@ function Image({ editor, className = '' }) {
29
29
  return file.type.startsWith('image/');
30
30
  };
31
31
  const handleUploadSuccess = (media) => {
32
- const image = media.image_thumbnail ? media.image_thumbnail : {
33
- url: media.image,
34
- width: media.image_width,
35
- height: media.image_height
36
- };
32
+ const image = media.image_thumbnail
33
+ ? media.image_thumbnail
34
+ : {
35
+ url: media.image,
36
+ width: media.image_width,
37
+ height: media.image_height
38
+ };
37
39
  const data = {
38
40
  altText: media.title,
39
41
  src: image.url,
@@ -40,7 +40,7 @@ export default function Activities(inProps) {
40
40
  feedObject,
41
41
  feedObjectType,
42
42
  cacheStrategy,
43
- pageSize: 3,
43
+ pageSize: 2,
44
44
  orderBy: selectedActivities === SCFeedObjectActivitiesType.CONNECTIONS_COMMENTS
45
45
  ? SCCommentsOrderBy.CONNECTION_DESC
46
46
  : selectedActivities === SCFeedObjectActivitiesType.FIRST_COMMENTS
@@ -48,7 +48,7 @@ export default function Activities(inProps) {
48
48
  : SCCommentsOrderBy.ADDED_AT_DESC
49
49
  });
50
50
  const objId = commentsObject.feedObject ? commentsObject.feedObject.id : null;
51
- const skeletonsCount = Math.min(3, commentsObject.feedObject ? commentsObject.feedObject.comment_count : 3);
51
+ const skeletonsCount = Math.min(3, commentsObject.feedObject ? commentsObject.feedObject.comment_count : 2);
52
52
  const existFeedObjectActivities = feedObjectActivities && feedObjectActivities.length > 0;
53
53
  /**
54
54
  * Sync activities type if prop change
@@ -78,11 +78,17 @@ export default function Activities(inProps) {
78
78
  function renderRelevantActivities() {
79
79
  return React.createElement(RelevantActivities, { activities: feedObjectActivities });
80
80
  }
81
+ /**
82
+ * Load comments
83
+ */
84
+ function handleNext() {
85
+ commentsObject.getNextPage();
86
+ }
81
87
  /**
82
88
  * Render comments of feedObject
83
89
  */
84
90
  function renderComments() {
85
- return (React.createElement(React.Fragment, null, (commentsObject.feedObject.comment_count > 0 || comments.length > 0) && (React.createElement(CommentsObject, Object.assign({ feedObject: commentsObject.feedObject, comments: commentsObject.comments, startComments: comments, next: commentsObject.next, isLoadingNext: commentsObject.isLoadingNext, handleNext: commentsObject.getNextPage, totalLoadedComments: commentsObject.comments.length + comments.length, totalComments: commentsObject.feedObject.comment_count, hideAdvertising: true, cacheStrategy: cacheStrategy }, CommentsObjectProps, { CommentsObjectSkeletonProps: { count: skeletonsCount }, CommentComponentProps: Object.assign(Object.assign({}, CommentComponentProps), { cacheStrategy }) })))));
91
+ return (React.createElement(React.Fragment, null, (commentsObject.feedObject.comment_count > 0 || comments.length > 0) && (React.createElement(CommentsObject, Object.assign({ feedObject: commentsObject.feedObject, comments: commentsObject.comments, startComments: comments, next: commentsObject.next, isLoadingNext: commentsObject.isLoadingNext, handleNext: handleNext, totalLoadedComments: commentsObject.comments.length + comments.length, totalComments: commentsObject.feedObject.comment_count, hideAdvertising: true }, CommentsObjectProps, { cacheStrategy: cacheStrategy, CommentsObjectSkeletonProps: { count: skeletonsCount }, CommentComponentProps: Object.assign(Object.assign(Object.assign({}, CommentComponentProps), { cacheStrategy }), (CommentsObjectProps.CommentComponentProps ? CommentsObjectProps.CommentComponentProps : {})) })))));
86
92
  }
87
93
  /**
88
94
  * Renders root object
@@ -456,7 +456,7 @@ export default function FeedObject(inProps) {
456
456
  template === SCFeedObjectTemplateType.PREVIEW && (obj.comment_count > 0 || (feedObjectActivities && feedObjectActivities.length > 0)) && (React.createElement(Collapse, { in: expandedActivities, timeout: "auto", classes: { root: classes.activitiesSection } },
457
457
  React.createElement(CardContent, { className: classes.activitiesContent },
458
458
  React.createElement(Activities, Object.assign({ feedObject: obj, key: selectedActivities, feedObjectActivities: feedObjectActivities, activitiesType: selectedActivities, onSetSelectedActivities: handleSelectedActivities, comments: comments, CommentsObjectProps: {
459
- CommentComponentProps: Object.assign({ onDelete: handleDeleteComment }, CommentComponentProps),
459
+ CommentComponentProps: Object.assign({ onDelete: handleDeleteComment, truncateContent: true }, CommentComponentProps),
460
460
  CommentObjectSkeletonProps: CommentObjectSkeletonProps
461
461
  }, cacheStrategy: cacheStrategy }, ActivitiesProps))))),
462
462
  composerOpen && (React.createElement(Composer, { open: composerOpen, feedObject: obj, onClose: handleToggleEdit, onSuccess: handleEditSuccess, maxWidth: "sm", fullWidth: true, scroll: "body" })))) : (React.createElement(FeedObjectSkeleton, Object.assign({ template: template }, FeedObjectSkeletonProps)))));
@@ -97,9 +97,13 @@ export default function PrivateMessageEditor(inProps) {
97
97
  setMessage(event.target.value);
98
98
  };
99
99
  const handleEmojiClick = (emojiData, event) => {
100
- const cursor = ref.current.selectionStart;
101
- const text = message.slice(0, cursor) + emojiData.emoji;
102
- setMessage(text);
100
+ const cursorPosition = ref.current.selectionEnd;
101
+ const start = ref.current.value.substring(0, ref.current.selectionStart);
102
+ const end = ref.current.value.substring(ref.current.selectionStart);
103
+ setMessage(start + emojiData.emoji + end);
104
+ setTimeout(() => {
105
+ ref.current.selectionStart = ref.current.selectionEnd = cursorPosition + emojiData.emoji.length;
106
+ }, 50);
103
107
  };
104
108
  // EFFECTS
105
109
  useEffect(() => {
@@ -127,8 +131,7 @@ export default function PrivateMessageEditor(inProps) {
127
131
  return (React.createElement(React.Fragment, null, openMediaSection ? (React.createElement(MessageMediaUploader, { className: classes.uploadMediaSection, open: openMediaSection, onClose: handleMediaSectionClose, forwardMessageFile: handleMessageFiles, isUploading: setUploading, action: React.createElement(IconButton, { disabled: (!message && !messageFiles.length) || uploading, onClick: handleMessageSend },
128
132
  React.createElement(Icon, null, "send")) })) : (React.createElement(React.Fragment, null,
129
133
  openEmojiSection && React.createElement(EmojiPicker, { className: classes.emojiSection, onEmojiClick: handleEmojiClick, width: "100%", searchDisabled: true }),
130
- React.createElement(TextField, { size: "small", disabled: Boolean(messageFiles.length) || openMediaSection, ref: ref, className: classes.messageInput, multiline: true, placeholder: `${intl.formatMessage(messages.placeholder)}`, value: message, onChange: handleMessageInput, maxRows: 2, onSelect: () => setOpenEmojiSection(false), InputProps: {
131
- disableUnderline: true,
134
+ React.createElement(TextField, { size: "small", inputRef: ref, disabled: Boolean(messageFiles.length) || openMediaSection, className: classes.messageInput, multiline: true, placeholder: `${intl.formatMessage(messages.placeholder)}`, value: message, onChange: handleMessageInput, maxRows: 2, onSelect: () => setOpenEmojiSection(false), InputProps: {
132
135
  startAdornment: (React.createElement(React.Fragment, null,
133
136
  React.createElement(IconButton, { disabled: openMediaSection, onClick: () => setOpenEmojiSection(!openEmojiSection) },
134
137
  React.createElement(Icon, null, "sentiment_satisfied_alt")),