diff --git a/lib/shared/message-utils.js b/lib/shared/message-utils.js
--- a/lib/shared/message-utils.js
+++ b/lib/shared/message-utils.js
@@ -468,7 +468,7 @@
   // unread has highest contrast, followed by primary, followed by secondary
   +style: 'unread' | 'primary' | 'secondary',
 };
-type MessagePreviewResult = {
+export type MessagePreviewResult = {
   +message: MessagePreviewPart,
   +username: ?MessagePreviewPart,
 };
diff --git a/native/chat/chat-input-bar.react.js b/native/chat/chat-input-bar.react.js
--- a/native/chat/chat-input-bar.react.js
+++ b/native/chat/chat-input-bar.react.js
@@ -37,7 +37,12 @@
   type Selection,
   getMentionsCandidates,
 } from 'lib/shared/mention-utils.js';
-import { localIDPrefix, trimMessage } from 'lib/shared/message-utils.js';
+import {
+  localIDPrefix,
+  trimMessage,
+  useMessagePreview,
+  type MessagePreviewResult,
+} from 'lib/shared/message-utils.js';
 import SearchIndex from 'lib/shared/search-index.js';
 import {
   threadHasPermission,
@@ -75,6 +80,7 @@
 import type { SyncedSelectionData } from '../components/selectable-text-input.js';
 // eslint-disable-next-line import/extensions
 import SelectableTextInput from '../components/selectable-text-input.react';
+import { SingleLine } from '../components/single-line.react.js';
 import SWMansionIcon from '../components/swmansion-icon.react.js';
 import { type InputState, InputStateContext } from '../input/input-state.js';
 import KeyboardInputHost from '../keyboard/keyboard-input-host.react.js';
@@ -83,6 +89,7 @@
   KeyboardContext,
 } from '../keyboard/keyboard-state.js';
 import { getKeyboardHeight } from '../keyboard/keyboard.js';
+import { getDefaultTextMessageRules } from '../markdown/rules.react.js';
 import {
   nonThreadCalendarQuery,
   activeThreadSelector,
@@ -139,6 +146,7 @@
   +userSearchIndex: SearchIndex,
   +mentionsCandidates: $ReadOnlyArray<RelativeMemberInfo>,
   +parentThreadInfo: ?ThreadInfo,
+  +editedMessagePreview: ?MessagePreviewResult,
 };
 type State = {
   +text: string,
@@ -422,6 +430,7 @@
       threadPermissions.JOIN_THREAD,
     );
     let joinButton = null;
+    const threadColor = `#${this.props.threadInfo.color}`;
     if (!isMember && canJoin && !this.props.threadCreationInProgress) {
       let buttonContent;
       if (this.props.joinThreadLoadingStatus === 'loading') {
@@ -450,7 +459,7 @@
             iosActiveOpacity={0.85}
             style={[
               this.props.styles.joinButton,
-              { backgroundColor: `#${this.props.threadInfo.color}` },
+              { backgroundColor: threadColor },
             ]}
           >
             {buttonContent}
@@ -532,6 +541,33 @@
         <KeyboardInputHost textInputRef={this.textInput} />
       );
 
+    let editedMessage;
+    const isEditMode = this.isEditMode();
+    if (isEditMode && this.props.editedMessagePreview) {
+      const { message } = this.props.editedMessagePreview;
+      editedMessage = (
+        <AnimatedView style={this.props.styles.editView}>
+          <View style={this.props.styles.editViewContent}>
+            <Text
+              style={[{ color: threadColor }, this.props.styles.editingLabel]}
+            >
+              Editing message
+            </Text>
+            <SingleLine style={this.props.styles.editingMessagePreview}>
+              {message.text}
+            </SingleLine>
+          </View>
+          <SWMansionIcon
+            style={this.props.styles.exitEditButton}
+            name="cross"
+            size={22}
+            color={threadColor}
+            onPress={this.onPressExitEditMode}
+          />
+        </AnimatedView>
+      );
+    }
+
     return (
       <View
         style={this.props.styles.container}
@@ -539,6 +575,7 @@
       >
         {typeaheadTooltip}
         {joinButton}
+        {editedMessage}
         {content}
         {keyboardInputHost}
       </View>
@@ -736,6 +773,15 @@
     );
   };
 
+  isEditMode = () => {
+    const editState = this.props.inputState?.editState;
+    return editState && editState.editedMessage !== null;
+  };
+
+  onPressExitEditMode = () => {
+    this.props.inputState?.setEditedMessage(null);
+  };
+
   onPressJoin = () => {
     this.props.dispatchActionPromise(joinThreadActionTypes, this.joinAction());
   };
@@ -844,6 +890,26 @@
     height: 48,
     marginBottom: 8,
   },
+  editView: {
+    marginLeft: 20,
+    marginRight: 20,
+    padding: 10,
+    flexDirection: 'row',
+    justifyContent: 'space-between',
+  },
+  editViewContent: {
+    flex: 1,
+    paddingRight: 6,
+  },
+  exitEditButton: {
+    marginTop: 6,
+  },
+  editingLabel: {
+    paddingBottom: 4,
+  },
+  editingMessagePreview: {
+    color: 'listForegroundLabel',
+  },
   joinButtonContent: {
     flexDirection: 'row',
     justifyContent: 'center',
@@ -948,6 +1014,13 @@
     parentThreadInfo,
   );
 
+  const editedMessageInfo = inputState?.editState.editedMessage;
+  const editedMessagePreview = useMessagePreview(
+    editedMessageInfo,
+    props.threadInfo,
+    getDefaultTextMessageRules().simpleMarkdownRules,
+  );
+
   return (
     <ChatInputBar
       {...props}
@@ -969,6 +1042,7 @@
       userSearchIndex={userSearchIndex}
       mentionsCandidates={mentionsCandidates}
       parentThreadInfo={parentThreadInfo}
+      editedMessagePreview={editedMessagePreview}
     />
   );
 }