diff --git a/lib/shared/chat-message-item-utils.js b/lib/shared/chat-message-item-utils.js
new file mode 100644
--- /dev/null
+++ b/lib/shared/chat-message-item-utils.js
@@ -0,0 +1,25 @@
+// @flow
+
+import type { ReactionInfo } from '../selectors/chat-selectors.js';
+import { getMessageLabel } from '../shared/edit-messages-utils.js';
+import type { ThreadInfo } from '../types/minimally-encoded-thread-permissions-types.js';
+
+type BaseChatMessageItemForEngagementCheck = {
+  +threadCreatedFromMessage: ?ThreadInfo,
+  +reactions: ReactionInfo,
+  +hasBeenEdited?: ?boolean,
+  ...
+};
+function chatMessageItemHasEngagement(
+  item: BaseChatMessageItemForEngagementCheck,
+  threadID: string,
+): boolean {
+  const label = getMessageLabel(item.hasBeenEdited, threadID);
+  return (
+    !!label ||
+    !!item.threadCreatedFromMessage ||
+    Object.keys(item.reactions).length > 0
+  );
+}
+
+export { chatMessageItemHasEngagement };
diff --git a/native/chat/composed-message.react.js b/native/chat/composed-message.react.js
--- a/native/chat/composed-message.react.js
+++ b/native/chat/composed-message.react.js
@@ -11,6 +11,7 @@
   useAnimatedStyle,
 } from 'react-native-reanimated';
 
+import { chatMessageItemHasEngagement } from 'lib/shared/chat-message-item-utils.js';
 import { getMessageLabel } from 'lib/shared/edit-messages-utils.js';
 import { createMessageReply } from 'lib/shared/message-utils.js';
 import { assertComposableMessageType } from 'lib/types/message-types.js';
@@ -275,13 +276,9 @@
       ],
     );
 
+    const label = getMessageLabel(hasBeenEdited, item.threadInfo.id);
     const inlineEngagement = React.useMemo(() => {
-      const label = getMessageLabel(hasBeenEdited, item.threadInfo.id);
-      if (
-        !item.threadCreatedFromMessage &&
-        Object.keys(item.reactions).length <= 0 &&
-        !label
-      ) {
+      if (!chatMessageItemHasEngagement(item, item.threadInfo.id)) {
         return undefined;
       }
       const positioning = isViewer ? 'right' : 'left';
@@ -295,14 +292,7 @@
           label={label}
         />
       );
-    }, [
-      hasBeenEdited,
-      isViewer,
-      item.messageInfo,
-      item.reactions,
-      item.threadCreatedFromMessage,
-      item.threadInfo,
-    ]);
+    }, [label, isViewer, item]);
 
     const viewStyle = React.useMemo(() => {
       const baseStyle: Array<ViewStyle> = [styles.alignment];
diff --git a/native/chat/multimedia-message-tooltip-button.react.js b/native/chat/multimedia-message-tooltip-button.react.js
--- a/native/chat/multimedia-message-tooltip-button.react.js
+++ b/native/chat/multimedia-message-tooltip-button.react.js
@@ -3,6 +3,7 @@
 import * as React from 'react';
 import Animated from 'react-native-reanimated';
 
+import { chatMessageItemHasEngagement } from 'lib/shared/chat-message-item-utils.js';
 import {
   useViewerAlreadySelectedMessageReactions,
   useCanCreateReactionFromMessage,
@@ -71,7 +72,7 @@
   }, [initialCoordinates.height, initialCoordinates.x, progress, windowWidth]);
 
   const inlineEngagement = React.useMemo(() => {
-    if (!item.threadCreatedFromMessage) {
+    if (!chatMessageItemHasEngagement(item, item.threadInfo.id)) {
       return null;
     }
     return (
diff --git a/native/chat/robotext-message.react.js b/native/chat/robotext-message.react.js
--- a/native/chat/robotext-message.react.js
+++ b/native/chat/robotext-message.react.js
@@ -4,6 +4,7 @@
 import * as React from 'react';
 import { View } from 'react-native';
 
+import { chatMessageItemHasEngagement } from 'lib/shared/chat-message-item-utils.js';
 import { messageKey } from 'lib/shared/message-utils.js';
 import { useCanCreateSidebarFromMessage } from 'lib/shared/sidebar-utils.js';
 
@@ -62,7 +63,7 @@
 
   const styles = useStyles(unboundStyles);
   let inlineEngagement = null;
-  if (item.threadCreatedFromMessage || Object.keys(item.reactions).length > 0) {
+  if (chatMessageItemHasEngagement(item, item.threadInfo.id)) {
     inlineEngagement = (
       <View style={styles.sidebar}>
         <InlineEngagement
diff --git a/native/chat/text-message-tooltip-button.react.js b/native/chat/text-message-tooltip-button.react.js
--- a/native/chat/text-message-tooltip-button.react.js
+++ b/native/chat/text-message-tooltip-button.react.js
@@ -3,6 +3,7 @@
 import * as React from 'react';
 import Animated from 'react-native-reanimated';
 
+import { chatMessageItemHasEngagement } from 'lib/shared/chat-message-item-utils.js';
 import {
   useViewerAlreadySelectedMessageReactions,
   useCanCreateReactionFromMessage,
@@ -82,7 +83,7 @@
   );
 
   const inlineEngagement = React.useMemo(() => {
-    if (!item.threadCreatedFromMessage) {
+    if (!chatMessageItemHasEngagement(item, item.threadInfo.id)) {
       return null;
     }
     return (
diff --git a/web/chat/composed-message.react.js b/web/chat/composed-message.react.js
--- a/web/chat/composed-message.react.js
+++ b/web/chat/composed-message.react.js
@@ -10,6 +10,7 @@
 
 import { useStringForUser } from 'lib/hooks/ens-cache.js';
 import { type ComposableChatMessageInfoItem } from 'lib/selectors/chat-selectors.js';
+import { chatMessageItemHasEngagement } from 'lib/shared/chat-message-item-utils.js';
 import { getMessageLabel } from 'lib/shared/edit-messages-utils.js';
 import { assertComposableMessageType } from 'lib/types/message-types.js';
 import type { ThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
@@ -129,11 +130,7 @@
 
     const label = getMessageLabel(item.hasBeenEdited, threadInfo.id);
     const inlineEngagement = React.useMemo(() => {
-      if (
-        !item.threadCreatedFromMessage &&
-        Object.keys(item.reactions).length === 0 &&
-        !label
-      ) {
+      if (!chatMessageItemHasEngagement(item, threadInfo.id)) {
         return null;
       }
       const positioning = isViewer ? 'right' : 'left';
@@ -149,14 +146,7 @@
           />
         </div>
       );
-    }, [
-      item.threadCreatedFromMessage,
-      item.reactions,
-      label,
-      isViewer,
-      item.messageInfo,
-      threadInfo,
-    ]);
+    }, [item, label, isViewer, threadInfo]);
 
     const avatar = React.useMemo(() => {
       if (!isViewer && item.endsCluster) {