fix mentions shows display name in composition box but sends user id

pull/1381/head
Audric Ackermann 5 years ago
parent 53fa014742
commit 9f0fd6fa8a
No known key found for this signature in database
GPG Key ID: 999F434D76324AD4

@ -104,4 +104,5 @@ export interface ConversationModel
queueJob: any; queueJob: any;
sendGroupInfo: any; sendGroupInfo: any;
onUpdateGroupName: any; onUpdateGroupName: any;
getContactProfileNameOrShortenedPubKey: () => string;
} }

@ -2304,9 +2304,9 @@
const profileName = this.getProfileName(); const profileName = this.getProfileName();
const number = this.getNumber(); const number = this.getNumber();
let name; let name;
if (window.shortenPubKey) { if (window.shortenPubkey) {
name = profileName name = profileName
? `${profileName} (${window.shortenPubKey(number)})` ? `${profileName} (${window.shortenPubkey(number)})`
: number; : number;
} else { } else {
name = profileName ? `${profileName} (${number})` : number; name = profileName ? `${profileName} (${number})` : number;
@ -2333,7 +2333,7 @@
if (pubkey === textsecure.storage.user.getNumber()) { if (pubkey === textsecure.storage.user.getNumber()) {
return i18n('you'); return i18n('you');
} }
return profileName || window.shortenPubKey(pubkey); return profileName || window.shortenPubkey(pubkey);
}, },
/** /**

@ -5,6 +5,7 @@ import classNames from 'classnames';
import { MultiDeviceProtocol } from '../../session/protocols'; import { MultiDeviceProtocol } from '../../session/protocols';
import { FindMember } from '../../util'; import { FindMember } from '../../util';
import { useInterval } from '../../hooks/useInterval'; import { useInterval } from '../../hooks/useInterval';
import { ConversationModel } from '../../../js/models/conversations';
interface MentionProps { interface MentionProps {
key: string; key: string;
@ -13,7 +14,7 @@ interface MentionProps {
} }
const Mention = (props: MentionProps) => { const Mention = (props: MentionProps) => {
const [found, setFound] = React.useState<any>(undefined); const [found, setFound] = React.useState<ConversationModel | null>(null);
const [us, setUs] = React.useState(false); const [us, setUs] = React.useState(false);
const tryRenameMention = async () => { const tryRenameMention = async () => {
@ -22,10 +23,9 @@ const Mention = (props: MentionProps) => {
props.text.slice(1), props.text.slice(1),
props.convoId props.convoId
); );
if (foundMember) { if (foundMember) {
const itsUs = await MultiDeviceProtocol.isOurDevice( const itsUs = await MultiDeviceProtocol.isOurDevice(foundMember.id);
foundMember.authorPhoneNumber
);
setUs(itsUs); setUs(itsUs);
setFound(foundMember); setFound(foundMember);
// FIXME stop this interval once we found it. // FIXME stop this interval once we found it.
@ -42,9 +42,7 @@ const Mention = (props: MentionProps) => {
us && 'mention-profile-name-us' us && 'mention-profile-name-us'
); );
const profileName = found.authorProfileName; const displayedName = found.getContactProfileNameOrShortenedPubKey();
const displayedName =
profileName && profileName.length > 0 ? profileName : 'Anonymous';
return <span className={className}>{displayedName}</span>; return <span className={className}>{displayedName}</span>;
} else { } else {
return ( return (
@ -95,7 +93,6 @@ export class AddMentions extends React.Component<Props> {
const pubkey = text.slice(match.index, FIND_MENTIONS.lastIndex); const pubkey = text.slice(match.index, FIND_MENTIONS.lastIndex);
results.push(<Mention text={pubkey} key={`${key}`} convoId={convoId} />); results.push(<Mention text={pubkey} key={`${key}`} convoId={convoId} />);
// @ts-ignore
last = FIND_MENTIONS.lastIndex; last = FIND_MENTIONS.lastIndex;
match = FIND_MENTIONS.exec(text); match = FIND_MENTIONS.exec(text);
} }

@ -127,7 +127,7 @@ export class SessionCompositionBox extends React.Component<Props, State> {
private emojiPanel: any; private emojiPanel: any;
private linkPreviewAbortController?: AbortController; private linkPreviewAbortController?: AbortController;
private container: any; private container: any;
private readonly mentionsRegex = /@\(05[0-9a-f]{64}\)/g; private readonly mentionsRegex = /@\u{FFD2}05[0-9a-f]{64}:[^\u{FFD2}]+\u{FFD2}/gu;
constructor(props: any) { constructor(props: any) {
super(props); super(props);
@ -368,13 +368,15 @@ export class SessionCompositionBox extends React.Component<Props, State> {
rows={1} rows={1}
style={sendMessageStyle} style={sendMessageStyle}
suggestionsPortalHost={this.container} suggestionsPortalHost={this.container}
allowSuggestionsAboveCursor={true} // if only one suggestion, it might be rendered below forceSuggestionsAboveCursor={true} // force mentions to be rendered on top of the cursor, this is working with a fork of react-mentions for now
> >
<Mention <Mention
appendSpaceOnAdd={true} appendSpaceOnAdd={true}
markup="@(__id__)" // @__id__ does not work, see cleanMentions() // this will be cleaned on cleanMentions()
markup="@ᅭ__id__:__display__ᅭ" // ᅭ = \uFFD2 is one of the forbidden char for a display name (check displayNameRegex)
trigger="@" trigger="@"
displayTransform={id => `@(${id})`} // this is only for the composition box visible content. The real stuff on the backend box is the @markup
displayTransform={(_id, display) => `@${display}`}
data={this.fetchUsersForGroup} data={this.fetchUsersForGroup}
renderSuggestion={( renderSuggestion={(
suggestion, suggestion,
@ -408,23 +410,21 @@ export class SessionCompositionBox extends React.Component<Props, State> {
} }
private fetchUsersForGroup(query: any, callback: any) { private fetchUsersForGroup(query: any, callback: any) {
let overridenQuery = query;
if (!query) { if (!query) {
return; overridenQuery = '';
} }
if (this.props.isPublic) { if (this.props.isPublic) {
this.fetchUsersForOpenGroup(query, callback); this.fetchUsersForOpenGroup(overridenQuery, callback);
return; return;
} }
if (!this.props.isPrivate) { if (!this.props.isPrivate) {
this.fetchUsersForClosedGroup(query, callback); this.fetchUsersForClosedGroup(overridenQuery, callback);
return; return;
} }
} }
private fetchUsersForOpenGroup(query: any, callback: any) { private fetchUsersForOpenGroup(query: any, callback: any) {
if (!query) {
return;
}
void window.lokiPublicChatAPI void window.lokiPublicChatAPI
.getListOfMembers() .getListOfMembers()
.then(members => .then(members =>
@ -447,9 +447,6 @@ export class SessionCompositionBox extends React.Component<Props, State> {
} }
private fetchUsersForClosedGroup(query: any, callback: any) { private fetchUsersForClosedGroup(query: any, callback: any) {
if (!query) {
return;
}
const conversationModel = window.ConversationController.get( const conversationModel = window.ConversationController.get(
this.props.conversationKey this.props.conversationKey
); );
@ -470,16 +467,18 @@ export class SessionCompositionBox extends React.Component<Props, State> {
authorProfileName: profileName, authorProfileName: profileName,
}; };
}); });
// keep anonymous members so we can still quote them with their id
const members = allMembers const members = allMembers
.filter(d => !!d) .filter(d => !!d)
.filter(d => d.authorProfileName !== 'Anonymous') .filter(
.filter(d => d =>
d.authorProfileName?.toLowerCase()?.includes(query.toLowerCase()) d.authorProfileName?.toLowerCase()?.includes(query.toLowerCase()) ||
!d.authorProfileName
); );
// Transform the users to what react-mentions expects // Transform the users to what react-mentions expects
const mentionsData = members.map(user => ({ const mentionsData = members.map(user => ({
display: user.authorProfileName, display: user.authorProfileName || window.i18n('anonymous'),
id: user.authorPhoneNumber, id: user.authorPhoneNumber,
})); }));
callback(mentionsData); callback(mentionsData);
@ -738,12 +737,29 @@ export class SessionCompositionBox extends React.Component<Props, State> {
// tslint:disable-next-line: cyclomatic-complexity // tslint:disable-next-line: cyclomatic-complexity
private async onSendMessage() { private async onSendMessage() {
const toUnicode = (str: string) => {
return str
.split('')
.map(value => {
const temp = value
.charCodeAt(0)
.toString(16)
.toUpperCase();
if (temp.length > 2) {
return `\\u${temp}`;
}
return value;
})
.join('');
};
// this is dirty but we have to replace all @(xxx) by @xxx manually here // this is dirty but we have to replace all @(xxx) by @xxx manually here
const cleanMentions = (text: string): string => { const cleanMentions = (text: string): string => {
const textUnicode = toUnicode(text);
const matches = text.match(this.mentionsRegex); const matches = text.match(this.mentionsRegex);
let replacedMentions = text; let replacedMentions = text;
(matches || []).forEach(match => { (matches || []).forEach(match => {
const replacedMention = match.substring(2, match.length - 1); const replacedMention = match.substring(2, match.indexOf(':'));
replacedMentions = replacedMentions.replace( replacedMentions = replacedMentions.replace(
match, match,
`@${replacedMention}` `@${replacedMention}`

@ -1,10 +1,12 @@
import { ConversationModel } from '../../js/models/conversations';
// tslint:disable: no-unnecessary-class // tslint:disable: no-unnecessary-class
export class FindMember { export class FindMember {
public static async findMember( public static async findMember(
pubkey: String, pubkey: String,
convoId: string, convoId: string,
clearOurInterval?: any clearOurInterval?: any
) { ): Promise<ConversationModel | null> {
let groupMembers; let groupMembers;
const groupConvos = window.getConversations().models.filter((d: any) => { const groupConvos = window.getConversations().models.filter((d: any) => {
@ -20,12 +22,17 @@ export class FindMember {
clearOurInterval(); clearOurInterval();
} }
return; return null;
} }
if (thisConvo.isPublic()) { if (thisConvo.isPublic()) {
groupMembers = await window.lokiPublicChatAPI.getListOfMembers(); const publicMembers = await window.lokiPublicChatAPI.getListOfMembers();
groupMembers = groupMembers.filter((m: any) => !!m); const memberConversations = publicMembers
.map(publicMember =>
window.ConversationController.get(publicMember.authorPhoneNumber)
)
.filter((c: any) => !!c);
groupMembers = memberConversations;
} else { } else {
const privateConvos = window const privateConvos = window
.getConversations() .getConversations()
@ -37,21 +44,9 @@ export class FindMember {
const memberConversations = members const memberConversations = members
.map((m: any) => privateConvos.find((c: any) => c.id === m)) .map((m: any) => privateConvos.find((c: any) => c.id === m))
.filter((c: any) => !!c); .filter((c: any) => !!c);
groupMembers = memberConversations.map((m: any) => { groupMembers = memberConversations;
const name = m.getLokiProfile()
? m.getLokiProfile().displayName
: m.attributes.displayName;
return {
id: m.id,
authorPhoneNumber: m.id,
authorProfileName: name,
};
});
} }
return groupMembers.find( return groupMembers.find(({ id: pn }: any) => pn && pn === pubkey);
({ authorPhoneNumber: pn }: any) => pn && pn === pubkey
);
} }
} }

Loading…
Cancel
Save