MessageComposer in place, supplied through{' '}
+ MessageComposerControllerProvider.
+ >
+ ),
+ id: 'inline-edit',
+ label: 'Edit inline',
+ read: (toggles) => toggles.inlineEdit,
+ write: (toggles, value) => ({ ...toggles, inlineEdit: value }),
+ },
{
comment: 'Mark own messages as unread too.',
id: 'mark-own-unread',
diff --git a/examples/vite/src/CustomMessageActions/ConfigurableMessageActions.tsx b/examples/vite/src/CustomMessageActions/ConfigurableMessageActions.tsx
index a393f31c3a..e23aeecfa3 100644
--- a/examples/vite/src/CustomMessageActions/ConfigurableMessageActions.tsx
+++ b/examples/vite/src/CustomMessageActions/ConfigurableMessageActions.tsx
@@ -34,6 +34,7 @@ import {
import { useAppSettingsSelector } from '../AppSettings';
import type { MessageActionSurface } from '../AppSettings';
+import { InlineEditMessageAction } from '../InlineEditMessage';
import {
MessageInfoPromptDialog,
messageInfoPromptDialogId,
@@ -286,7 +287,11 @@ const CustomViewMessageInfoAction = () => {
);
};
-type SupportedCustomMessageActionType = 'delete' | 'markOwnUnread' | 'viewMessageInfo';
+type SupportedCustomMessageActionType =
+ | 'delete'
+ | 'editInline'
+ | 'markOwnUnread'
+ | 'viewMessageInfo';
type CustomMessageActionOverrideSpec = {
actionSetItem: MessageActionSetItem;
@@ -379,6 +384,16 @@ export const ConfigurableMessageActions = (
},
mode: 'replace',
},
+ // Next to the built-in edit, so the two ways of editing read as alternatives.
+ editInline: {
+ actionSetItem: {
+ Component: InlineEditMessageAction,
+ placement: 'dropdown',
+ type: 'editInline',
+ },
+ insertBeforeType: 'edit',
+ mode: 'append',
+ },
markOwnUnread: {
actionSetItem: {
Component: CustomMarkOwnUnreadMessageAction,
@@ -404,6 +419,10 @@ export const ConfigurableMessageActions = (
...actionOverrides.delete,
enabled: customDeleteEnabled,
},
+ {
+ ...actionOverrides.editInline,
+ enabled: surfaceActions.inlineEdit,
+ },
{
...actionOverrides.markOwnUnread,
enabled: surfaceActions.markOwnUnread,
@@ -430,6 +449,7 @@ export const ConfigurableMessageActions = (
}, [
customDeleteEnabled,
surfaceActions.disabledActionTypes,
+ surfaceActions.inlineEdit,
surfaceActions.markOwnUnread,
surfaceActions.viewMessageInfo,
props.messageActionSet,
diff --git a/examples/vite/src/InlineEditMessage/InlineEditMessage.scss b/examples/vite/src/InlineEditMessage/InlineEditMessage.scss
new file mode 100644
index 0000000000..8a52dab6f1
--- /dev/null
+++ b/examples/vite/src/InlineEditMessage/InlineEditMessage.scss
@@ -0,0 +1,4 @@
+.app__inline-edit-message {
+ padding: 0.5rem 0;
+ width: 100%;
+}
diff --git a/examples/vite/src/InlineEditMessage/InlineEditMessage.tsx b/examples/vite/src/InlineEditMessage/InlineEditMessage.tsx
new file mode 100644
index 0000000000..4c30210206
--- /dev/null
+++ b/examples/vite/src/InlineEditMessage/InlineEditMessage.tsx
@@ -0,0 +1,145 @@
+import {
+ createContext,
+ useCallback,
+ useContext,
+ useEffect,
+ useMemo,
+ useState,
+} from 'react';
+import { MessageComposer as MessageComposerController } from 'stream-chat';
+import type { LocalMessage, MessageComposerState } from 'stream-chat';
+import {
+ asDynamicKey,
+ ContextMenuButton,
+ MessageUI as DefaultMessageUI,
+ IconEdit,
+ MessageComposer,
+ MessageComposerControllerProvider,
+ type MessageUIComponentProps,
+ useChatContext,
+ useContextMenuContext,
+ useMessageContext,
+ useStateStore,
+ useThreadContext,
+ useTranslationContext,
+} from 'stream-chat-react';
+
+import { useAppSettingsSelector } from '../AppSettings';
+import type { MessageActionSurface } from '../AppSettings';
+
+type InlineEditContextValue = {
+ startEditing: (message: LocalMessage) => void;
+};
+
+// Lets the "Edit inline" action, rendered deep in the message's actions menu, start editing the
+// row it belongs to.
+const InlineEditContext = createContext