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, +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 @@ ); + let editedMessage; + const isEditMode = this.isEditMode(); + if (isEditMode && this.props.editedMessagePreview) { + const { message } = this.props.editedMessagePreview; + editedMessage = ( + + + + Editing message + + + {message.text} + + + + + ); + } + return ( {typeaheadTooltip} {joinButton} + {editedMessage} {content} {keyboardInputHost} @@ -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 ( ); }