diff --git a/js/models/messages.js b/js/models/messages.js index 347fbb340..de66e2200 100644 --- a/js/models/messages.js +++ b/js/models/messages.js @@ -573,8 +573,12 @@ ? expireTimerStart + expirationLength : null; + // TODO: investigate why conversation is undefined + // for the public group chat const conversation = this.getConversation(); - const isGroup = conversation && !conversation.isPrivate(); + + const convoId = conversation ? conversation.id : undefined; + const isGroup = !!conversation && !conversation.isPrivate(); const attachments = this.get('attachments') || []; const firstAttachment = attachments[0]; @@ -592,6 +596,7 @@ authorProfileName: contact.profileName, authorPhoneNumber: contact.phoneNumber, conversationType: isGroup ? 'group' : 'direct', + convoId, attachments: attachments .filter(attachment => !attachment.error) .map(attachment => this.getPropsForAttachment(attachment)), diff --git a/js/views/conversation_view.js b/js/views/conversation_view.js index 3aca56024..cbe28b2ee 100644 --- a/js/views/conversation_view.js +++ b/js/views/conversation_view.js @@ -2389,7 +2389,7 @@ // Note: schedule the member list handler shortly afterwards, so // that the input element has time to update its cursor position to // what the user would expect - if (this.model.isPublic()) { + if (this.model.get('type') === 'group') { window.requestAnimationFrame(this.maybeShowMembers.bind(this, event)); } @@ -2521,10 +2521,31 @@ return query; }; - let allMembers = window.lokiPublicChatAPI.getListOfMembers(); - allMembers = allMembers.filter(d => !!d); - allMembers = allMembers.filter(d => d.authorProfileName !== 'Anonymous'); - allMembers = _.uniq(allMembers, true, d => d.authorPhoneNumber); + let allMembers; + + if (this.model.isPublic()) { + let members = window.lokiPublicChatAPI.getListOfMembers(); + members = members.filter(d => !!d); + members = members.filter(d => d.authorProfileName !== 'Anonymous'); + allMembers = _.uniq(members, true, d => d.authorPhoneNumber); + } else { + const members = this.model.get('members'); + if (!members || members.length === 0) { + return; + } + + const privateConvos = window + .getConversations() + .models.filter(d => d.isPrivate()); + const memberConvos = members + .map(m => privateConvos.find(c => c.id === m)) + .filter(c => !!c); + allMembers = memberConvos.map(m => ({ + id: m.id, + authorPhoneNumber: m.id, + authorProfileName: m.getLokiProfile().displayName, + })); + } const cursorPos = event.target.selectionStart; diff --git a/ts/components/conversation/AddMentions.tsx b/ts/components/conversation/AddMentions.tsx index 2b14e5488..87449e946 100644 --- a/ts/components/conversation/AddMentions.tsx +++ b/ts/components/conversation/AddMentions.tsx @@ -8,12 +8,14 @@ declare global { lokiPublicChatAPI: any; shortenPubkey: any; pubkeyPattern: any; + getConversations: any; } } interface MentionProps { key: number; text: string; + convoId: string; } interface MentionState { @@ -78,13 +80,41 @@ class Mention extends React.Component { } private findMember(pubkey: String) { - const members = window.lokiPublicChatAPI.getListOfMembers(); - if (!members) { - return null; + let groupMembers; + + const groupConvos = window.getConversations().models.filter((d: any) => { + return !d.isPrivate(); + }); + const thisConvo = groupConvos.find((d: any) => { + return d.id === this.props.convoId; + }); + + if (thisConvo.isPublic()) { + // TODO: make this work for other public chats as well + groupMembers = window.lokiPublicChatAPI + .getListOfMembers() + .filter((m: any) => !!m); + } else { + const privateConvos = window + .getConversations() + .models.filter((d: any) => d.isPrivate()); + const members = thisConvo.attributes.members; + if (!members) { + return null; + } + const memberConversations = members + .map((m: any) => privateConvos.find((c: any) => c.id === m)) + .filter((c: any) => !!c); + groupMembers = memberConversations.map((m: any) => { + return { + id: m.id, + authorPhoneNumber: m.id, + authorProfileName: m.getLokiProfile().displayName, + }; + }); } - const filtered = members.filter((m: any) => !!m); - return filtered.find( + return groupMembers.find( ({ authorPhoneNumber: pn }: any) => pn && pn === pubkey ); } @@ -93,6 +123,7 @@ class Mention extends React.Component { interface Props { text: string; renderOther?: RenderTextCallbackType; + convoId: string; } export class AddMentions extends React.Component { @@ -101,7 +132,7 @@ export class AddMentions extends React.Component { }; public render() { - const { text, renderOther } = this.props; + const { text, renderOther, convoId } = this.props; const results: Array = []; const FIND_MENTIONS = window.pubkeyPattern; @@ -126,7 +157,7 @@ export class AddMentions extends React.Component { } const pubkey = text.slice(match.index, FIND_MENTIONS.lastIndex); - results.push(); + results.push(); // @ts-ignore last = FIND_MENTIONS.lastIndex; diff --git a/ts/components/conversation/AddNewLines.tsx b/ts/components/conversation/AddNewLines.tsx index 986a9a5b7..356b1a6a8 100644 --- a/ts/components/conversation/AddNewLines.tsx +++ b/ts/components/conversation/AddNewLines.tsx @@ -6,6 +6,7 @@ interface Props { text: string; /** Allows you to customize now non-newlines are rendered. Simplest is just a . */ renderNonNewLine?: RenderTextCallbackType; + convoId: string; } export class AddNewLines extends React.Component { @@ -14,7 +15,7 @@ export class AddNewLines extends React.Component { }; public render() { - const { text, renderNonNewLine } = this.props; + const { text, renderNonNewLine, convoId } = this.props; const results: Array = []; const FIND_NEWLINES = /\n/g; @@ -29,14 +30,14 @@ export class AddNewLines extends React.Component { let count = 1; if (!match) { - return renderNonNewLine({ text, key: 0 }); + return renderNonNewLine({ text, key: 0, convoId }); } while (match) { if (last < match.index) { const textWithNoNewline = text.slice(last, match.index); results.push( - renderNonNewLine({ text: textWithNoNewline, key: count++ }) + renderNonNewLine({ text: textWithNoNewline, key: count++, convoId }) ); } @@ -48,7 +49,9 @@ export class AddNewLines extends React.Component { } if (last < text.length) { - results.push(renderNonNewLine({ text: text.slice(last), key: count++ })); + results.push( + renderNonNewLine({ text: text.slice(last), key: count++, convoId }) + ); } return results; diff --git a/ts/components/conversation/Emojify.tsx b/ts/components/conversation/Emojify.tsx index 0439de8df..ddd9f2359 100644 --- a/ts/components/conversation/Emojify.tsx +++ b/ts/components/conversation/Emojify.tsx @@ -56,17 +56,25 @@ interface Props { /** Allows you to customize now non-newlines are rendered. Simplest is just a . */ renderNonEmoji?: RenderTextCallbackType; i18n: LocalizerType; - isPublic?: boolean; + isGroup?: boolean; + convoId: string; } export class Emojify extends React.Component { public static defaultProps: Partial = { renderNonEmoji: ({ text }) => text || '', - isPublic: false, + isGroup: false, }; public render() { - const { text, sizeClass, renderNonEmoji, i18n, isPublic } = this.props; + const { + text, + sizeClass, + renderNonEmoji, + i18n, + isGroup, + convoId, + } = this.props; const results: Array = []; const regex = getRegex(); @@ -81,14 +89,19 @@ export class Emojify extends React.Component { let count = 1; if (!match) { - return renderNonEmoji({ text, key: 0, isPublic }); + return renderNonEmoji({ text, key: 0, isGroup, convoId }); } while (match) { if (last < match.index) { const textWithNoEmoji = text.slice(last, match.index); results.push( - renderNonEmoji({ text: textWithNoEmoji, key: count++, isPublic }) + renderNonEmoji({ + text: textWithNoEmoji, + key: count++, + isGroup, + convoId, + }) ); } @@ -100,7 +113,12 @@ export class Emojify extends React.Component { if (last < text.length) { results.push( - renderNonEmoji({ text: text.slice(last), key: count++, isPublic }) + renderNonEmoji({ + text: text.slice(last), + key: count++, + isGroup, + convoId, + }) ); } diff --git a/ts/components/conversation/Message.tsx b/ts/components/conversation/Message.tsx index 7059817a2..005335688 100644 --- a/ts/components/conversation/Message.tsx +++ b/ts/components/conversation/Message.tsx @@ -93,6 +93,7 @@ export interface Props { isExpired: boolean; expirationLength?: number; expirationTimestamp?: number; + convoId: string; isP2p?: boolean; isPublic?: boolean; isRss?: boolean; @@ -590,6 +591,7 @@ export class Message extends React.PureComponent { i18n, quote, isPublic, + convoId, } = this.props; if (!quote) { @@ -614,6 +616,8 @@ export class Message extends React.PureComponent { text={quote.text} attachment={quote.attachment} isIncoming={direction === 'incoming'} + conversationType={conversationType} + convoId={convoId} isPublic={isPublic} authorPhoneNumber={displayedPubkey} authorProfileName={quote.authorProfileName} @@ -718,7 +722,16 @@ export class Message extends React.PureComponent { } public renderText() { - const { text, textPending, i18n, direction, status, isRss } = this.props; + const { + text, + textPending, + i18n, + direction, + status, + isRss, + conversationType, + convoId, + } = this.props; const contents = direction === 'incoming' && status === 'error' @@ -745,7 +758,8 @@ export class Message extends React.PureComponent { isRss={isRss} i18n={i18n} textPending={textPending} - isPublic={this.props.isPublic} + isGroup={conversationType === 'group'} + convoId={convoId} /> ); diff --git a/ts/components/conversation/MessageBody.tsx b/ts/components/conversation/MessageBody.tsx index 7c72bd22b..8e7dea61d 100644 --- a/ts/components/conversation/MessageBody.tsx +++ b/ts/components/conversation/MessageBody.tsx @@ -16,12 +16,13 @@ interface Props { disableJumbomoji?: boolean; /** If set, links will be left alone instead of turned into clickable `` tags. */ disableLinks?: boolean; - isPublic?: boolean; + isGroup?: boolean; i18n: LocalizerType; + convoId: string; } - -const renderMentions: RenderTextCallbackType = ({ text, key }) => ( - +// eslint-disable-next-line +const renderMentions: RenderTextCallbackType = ({ text, key, convoId }) => ( + ); const renderDefault: RenderTextCallbackType = ({ text }) => text; @@ -29,15 +30,17 @@ const renderDefault: RenderTextCallbackType = ({ text }) => text; const renderNewLines: RenderTextCallbackType = ({ text: textWithNewLines, key, - isPublic, + isGroup, + convoId, }) => { - const renderOther = isPublic ? renderMentions : renderDefault; + const renderOther = isGroup ? renderMentions : renderDefault; return ( ); }; @@ -48,14 +51,16 @@ const renderEmoji = ({ key, sizeClass, renderNonEmoji, - isPublic, + isGroup, + convoId, }: { i18n: LocalizerType; text: string; key: number; sizeClass?: SizeClassType; renderNonEmoji: RenderTextCallbackType; - isPublic?: boolean; + isGroup?: boolean; + convoId?: string; }) => ( ); @@ -75,7 +81,7 @@ const renderEmoji = ({ */ export class MessageBody extends React.Component { public static defaultProps: Partial = { - isPublic: false, + isGroup: false, }; public addDownloading(jsx: JSX.Element): JSX.Element { @@ -102,7 +108,8 @@ export class MessageBody extends React.Component { disableLinks, isRss, i18n, - isPublic, + isGroup, + convoId, } = this.props; const sizeClass = disableJumbomoji ? undefined : getSizeClass(text); const textWithPending = textPending ? `${text}...` : text; @@ -115,7 +122,8 @@ export class MessageBody extends React.Component { sizeClass, key: 0, renderNonEmoji: renderNewLines, - isPublic, + isGroup, + convoId, }) ); } @@ -131,7 +139,8 @@ export class MessageBody extends React.Component { sizeClass, key, renderNonEmoji: renderNewLines, - isPublic, + isGroup, + convoId, }); }} /> diff --git a/ts/components/conversation/Quote.tsx b/ts/components/conversation/Quote.tsx index 7d7b381fb..6ae7bac30 100644 --- a/ts/components/conversation/Quote.tsx +++ b/ts/components/conversation/Quote.tsx @@ -19,6 +19,8 @@ interface Props { i18n: LocalizerType; isFromMe: boolean; isIncoming: boolean; + conversationType: 'group' | 'direct'; + convoId: string; isPublic?: boolean; withContentAbove: boolean; onClick?: () => void; @@ -215,7 +217,14 @@ export class Quote extends React.Component { } public renderText() { - const { i18n, text, attachment, isIncoming, isPublic } = this.props; + const { + i18n, + text, + attachment, + isIncoming, + conversationType, + convoId, + } = this.props; if (text) { return ( @@ -227,7 +236,8 @@ export class Quote extends React.Component { )} > JSX.Element | string;