make mentions work in react when emoji inserted inside at a rand pos

pull/1381/head
Audric Ackermann 4 years ago
parent b5af8eb215
commit c9e81454fb
No known key found for this signature in database
GPG Key ID: 999F434D76324AD4

@ -12,7 +12,6 @@
min-width: 20px;
}
.existing-member {
color: green;
}
@ -42,7 +41,6 @@
}
}
.invisible {
visibility: hidden;
}
@ -69,8 +67,6 @@
}
}
.mention-profile-name {
color: rgb(194, 244, 255);
background-color: rgb(66, 121, 150);

@ -28,7 +28,13 @@ export class MemberItem extends React.Component<MemberItemProps> {
}
public render() {
const {authorProfileName: name, authorPhoneNumber: pubkey, selected, existingMember, checkmarked} = this.props.member;
const {
authorProfileName: name,
authorPhoneNumber: pubkey,
selected,
existingMember,
checkmarked,
} = this.props.member;
const shortPubkey = window.shortenPubkey(pubkey);
let markType: 'none' | 'kicked' | 'added' | 'existing' = 'none';
@ -80,7 +86,6 @@ export class MemberItem extends React.Component<MemberItemProps> {
</div>
);
}
private handleClick() {
this.props.onClicked(this.props.member);
}

@ -15,6 +15,7 @@ const SessionToastContainerPrivate = () => {
draggable={true}
pauseOnHover={true}
transition={Slide}
limit={5}
/>
);
};

@ -124,7 +124,7 @@ export class SessionCompositionBox extends React.Component<Props, State> {
private emojiPanel: any;
private linkPreviewAbortController?: AbortController;
private container: any;
private mentionsData: Array<{ display: string; id: string }>;
private readonly mentionsRegex = /@\(05[0-9a-f]{64}\)/g;
constructor(props: any) {
super(props);
@ -132,7 +132,6 @@ export class SessionCompositionBox extends React.Component<Props, State> {
this.textarea = props.textarea;
this.fileInput = React.createRef();
this.mentionsData = [];
// Emojis
this.emojiPanel = null;
@ -143,9 +142,10 @@ export class SessionCompositionBox extends React.Component<Props, State> {
this.renderRecordingView = this.renderRecordingView.bind(this);
this.renderCompositionView = this.renderCompositionView.bind(this);
this.renderTextArea = this.renderTextArea.bind(this);
this.renderQuotedMessage = this.renderQuotedMessage.bind(this);
this.renderStagedLinkPreview = this.renderStagedLinkPreview.bind(this);
this.renderStagedLinkPreview = this.renderStagedLinkPreview.bind(this);
this.renderAttachmentsStaged = this.renderAttachmentsStaged.bind(this);
// Recording view functions
@ -185,7 +185,6 @@ export class SessionCompositionBox extends React.Component<Props, State> {
// reset the state on new conversation key
if (prevProps.conversationKey !== this.props.conversationKey) {
this.setState(getDefaultState());
this.mentionsData = [];
}
}
@ -248,20 +247,15 @@ export class SessionCompositionBox extends React.Component<Props, State> {
);
}
private renderCompositionView() {
private isTypingEnabled(): boolean {
const { isBlocked, isKickedFromGroup, leftGroup, isPrivate } = this.props;
const { showEmojiPanel, message } = this.state;
const typingEnabled = !(isBlocked || isKickedFromGroup || leftGroup);
const { i18n } = window;
const messagePlaceHolder = isKickedFromGroup
? i18n('youGotKickedFromGroup')
: leftGroup
? i18n('youLeftTheGroup')
: isBlocked && isPrivate
? i18n('unblockToSend')
: isBlocked && !isPrivate
? i18n('unblockGroupToSend')
: i18n('sendMessage');
return !(isBlocked || isKickedFromGroup || leftGroup);
}
private renderCompositionView() {
const { showEmojiPanel } = this.state;
const typingEnabled = this.isTypingEnabled();
return (
<>
@ -293,60 +287,12 @@ export class SessionCompositionBox extends React.Component<Props, State> {
<div
className="send-message-input"
role="main"
onClick={this.focusCompositionBox}
onClick={this.focusCompositionBox} // used to focus on the textarea when clicking in its container
ref={el => {
this.container = el;
}}
>
<MentionsInput
value={this.state.message}
onChange={this.onChange}
onKeyDown={this.onKeyDown}
placeholder={messagePlaceHolder}
spellCheck={false}
inputRef={this.textarea}
disabled={!typingEnabled}
maxLength={Constants.CONVERSATION.MAX_MESSAGE_BODY_LENGTH}
rows={1}
// maxRows={3}
style={sendMessageStyle}
suggestionsPortalHost={this.container}
allowSuggestionsAboveCursor={true}
>
<Mention
appendSpaceOnAdd={true}
markup="@(__id__)" // @__id__ does not work, see cleanMentions()
trigger="@"
displayTransform={id => `@${id}`}
data={this.fetchUsersForGroup}
renderSuggestion={(
suggestion,
_search,
_highlightedDisplay,
_index,
focused
) => (
<MemberItem
i18n={window.i18n}
selected={focused}
// tslint:disable-next-line: no-empty
onClicked={() => {}}
existingMember={false}
member={{
id: `${suggestion.id}`,
authorPhoneNumber: `${suggestion.id}`,
selected: false,
authorProfileName: `${suggestion.display}`,
authorName: `${suggestion.display}`,
existingMember: false,
checkmarked: false,
authorAvatarPath: '',
}}
checkmarked={false}
/>
)}
/>
</MentionsInput>
{this.renderTextArea()}
</div>
{typingEnabled && (
@ -382,6 +328,74 @@ export class SessionCompositionBox extends React.Component<Props, State> {
</>
);
}
private renderTextArea() {
const { i18n } = window;
const { message } = this.state;
const { isKickedFromGroup, leftGroup, isPrivate, isBlocked } = this.props;
const messagePlaceHolder = isKickedFromGroup
? i18n('youGotKickedFromGroup')
: leftGroup
? i18n('youLeftTheGroup')
: isBlocked && isPrivate
? i18n('unblockToSend')
: isBlocked && !isPrivate
? i18n('unblockGroupToSend')
: i18n('sendMessage');
const typingEnabled = this.isTypingEnabled();
return (
<MentionsInput
value={message}
onChange={this.onChange}
onKeyDown={this.onKeyDown}
placeholder={messagePlaceHolder}
spellCheck={false}
inputRef={this.textarea}
disabled={!typingEnabled}
maxLength={Constants.CONVERSATION.MAX_MESSAGE_BODY_LENGTH}
rows={1}
style={sendMessageStyle}
suggestionsPortalHost={this.container}
allowSuggestionsAboveCursor={true} // if only one suggestion, it might be rendered below
>
<Mention
appendSpaceOnAdd={true}
markup="@(__id__)" // @__id__ does not work, see cleanMentions()
trigger="@"
displayTransform={id => `@(${id})`}
data={this.fetchUsersForGroup}
renderSuggestion={(
suggestion,
_search,
_highlightedDisplay,
_index,
focused
) => (
<MemberItem
i18n={window.i18n}
selected={focused}
// tslint:disable-next-line: no-empty
onClicked={() => {}}
existingMember={false}
member={{
id: `${suggestion.id}`,
authorPhoneNumber: `${suggestion.id}`,
selected: false,
authorProfileName: `${suggestion.display}`,
authorName: `${suggestion.display}`,
existingMember: false,
checkmarked: false,
authorAvatarPath: '',
}}
checkmarked={false}
/>
)}
/>
</MentionsInput>
);
}
private fetchUsersForGroup(query: any, callback: any) {
if (!query) {
return;
@ -451,13 +465,12 @@ export class SessionCompositionBox extends React.Component<Props, State> {
.filter(d =>
d.authorProfileName?.toLowerCase()?.includes(query.toLowerCase())
);
// Transform the users to what react-mentions expects
// Transform the users to what react-mentions expects
const mentionsData = members.map(user => ({
display: user.authorProfileName,
id: user.authorPhoneNumber,
}));
this.mentionsData = mentionsData;
callback(mentionsData);
}
@ -654,10 +667,9 @@ export class SessionCompositionBox extends React.Component<Props, State> {
// tslint:disable-next-line: cyclomatic-complexity
private async onSendMessage() {
// replace all @(xxx) by @xxx
// this is dirty but we have to replace all @(xxx) by @xxx manually here
const cleanMentions = (text: string): string => {
const mentionRegex = /@\(05[0-9a-f]{64}\)/g;
const matches = text.match(mentionRegex);
const matches = text.match(this.mentionsRegex);
let replacedMentions = text;
(matches || []).forEach(match => {
const replacedMention = match.substring(2, match.length - 1);
@ -847,13 +859,14 @@ export class SessionCompositionBox extends React.Component<Props, State> {
this.setState({ message });
}
private onEmojiClick({ colons, native }: { colons: string; native: string }) {
private onEmojiClick({ colons }: { colons: string }) {
const messageBox = this.textarea.current;
if (!messageBox) {
return;
}
const { message } = this.state;
const currentSelectionStart = Number(messageBox.selectionStart);
const currentSelectionEnd = Number(messageBox.selectionEnd);

Loading…
Cancel
Save