Fix left pane draft display and GV2 typing indicators

This commit is contained in:
Scott Nonnenberg 2020-11-03 16:16:20 -08:00 committed by GitHub
parent ab89c6c704
commit 18c71b291c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 58 additions and 31 deletions

View file

@ -103,6 +103,27 @@ story.add('Typing Status', () => {
return <ConversationListItem {...props} />; return <ConversationListItem {...props} />;
}); });
story.add('With draft', () => {
const props = createProps({
shouldShowDraft: true,
draftPreview: "I'm in the middle of typing this...",
});
return <ConversationListItem {...props} />;
});
story.add('Deleted for everyone', () => {
const props = createProps({
lastMessage: {
status: 'sent',
text: 'You should not see this!',
deletedForEveryone: true,
},
});
return <ConversationListItem {...props} />;
});
story.add('Message Request', () => { story.add('Message Request', () => {
const props = createProps({ const props = createProps({
acceptedMessageRequest: false, acceptedMessageRequest: false,

View file

@ -178,23 +178,14 @@ export class ConversationListItem extends React.PureComponent<Props> {
return null; return null;
} }
const messageBody = lastMessage ? lastMessage.text : '';
const withUnread = isNumber(unreadCount) && unreadCount > 0; const withUnread = isNumber(unreadCount) && unreadCount > 0;
const showingDraft = shouldShowDraft && draftPreview; const showingDraft = shouldShowDraft && draftPreview;
const deletedForEveryone = Boolean( const deletedForEveryone = Boolean(
lastMessage && lastMessage.deletedForEveryone lastMessage && lastMessage.deletedForEveryone
); );
// Note: instead of re-using showingDraft here we explode it because
// typescript can't tell that draftPreview is truthy otherwise
// Avoiding touching logic to fix linting
/* eslint-disable no-nested-ternary */ /* eslint-disable no-nested-ternary */
const text =
shouldShowDraft && draftPreview
? draftPreview
: lastMessage && lastMessage.text
? lastMessage.text
: '';
return ( return (
<div className="module-conversation-list-item__message"> <div className="module-conversation-list-item__message">
<div <div
@ -218,16 +209,24 @@ export class ConversationListItem extends React.PureComponent<Props> {
) : ( ) : (
<> <>
{showingDraft ? ( {showingDraft ? (
<span className="module-conversation-list-item__message__draft-prefix"> <>
{i18n('ConversationListItem--draft-prefix')} <span className="module-conversation-list-item__message__draft-prefix">
</span> {i18n('ConversationListItem--draft-prefix')}
</span>
<MessageBody
text={(draftPreview || '').split('\n')[0]}
disableJumbomoji
disableLinks
i18n={i18n}
/>
</>
) : deletedForEveryone ? ( ) : deletedForEveryone ? (
<span className="module-conversation-list-item__message__deleted-for-everyone"> <span className="module-conversation-list-item__message__deleted-for-everyone">
{i18n('message--deletedForEveryone')} {i18n('message--deletedForEveryone')}
</span> </span>
) : ( ) : (
<MessageBody <MessageBody
text={text.split('\n')[0]} text={(messageBody || '').split('\n')[0]}
disableJumbomoji disableJumbomoji
disableLinks disableLinks
i18n={i18n} i18n={i18n}

View file

@ -422,8 +422,8 @@ export class Lightbox extends React.Component<Props, State> {
const { contentType } = this.props; const { contentType } = this.props;
// These are the only image types supported by Electron's NativeImage // These are the only image types supported by Electron's NativeImage
if (contentType !== 'image/png' && contentType !== 'image/jpg') { if (event && contentType !== 'image/png' && contentType !== 'image/jpg') {
event?.preventDefault(); event.preventDefault();
} }
}; };

View file

@ -867,6 +867,23 @@ export class ConversationModel extends window.Backbone.Model<
}; };
} }
getGroupIdBuffer(): ArrayBuffer | undefined {
const groupIdString = this.get('groupId');
if (!groupIdString) {
return undefined;
}
if (this.isGroupV1()) {
return fromEncodedBinaryToArrayBuffer(groupIdString);
}
if (this.isGroupV2()) {
return base64ToArrayBuffer(groupIdString);
}
return undefined;
}
sendTypingMessage(isTyping: boolean): void { sendTypingMessage(isTyping: boolean): void {
if (!window.textsecure.messaging) { if (!window.textsecure.messaging) {
return; return;
@ -878,7 +895,7 @@ export class ConversationModel extends window.Backbone.Model<
} }
const recipientId = this.isPrivate() ? this.getSendTarget() : undefined; const recipientId = this.isPrivate() ? this.getSendTarget() : undefined;
const groupId = !this.isPrivate() ? this.get('groupId') : undefined; const groupId = this.getGroupIdBuffer();
const groupMembers = this.getRecipients(); const groupMembers = this.getRecipients();
// We don't send typing messages if our recipients list is empty // We don't send typing messages if our recipients list is empty
@ -1408,13 +1425,7 @@ export class ConversationModel extends window.Backbone.Model<
} }
); );
const groupId = this.get('groupId'); const groupId = this.getGroupIdBuffer();
let groupIdBuffer;
if (groupId && this.isGroupV1()) {
groupIdBuffer = fromEncodedBinaryToArrayBuffer(groupId);
} else if (groupId && this.isGroupV2()) {
groupIdBuffer = base64ToArrayBuffer(groupId);
}
try { try {
await wrap( await wrap(
@ -1422,7 +1433,7 @@ export class ConversationModel extends window.Backbone.Model<
{ {
threadE164: this.get('e164'), threadE164: this.get('e164'),
threadUuid: this.get('uuid'), threadUuid: this.get('uuid'),
groupId: groupIdBuffer, groupId,
type: response, type: response,
}, },
sendOptions sendOptions

View file

@ -21,7 +21,6 @@ import Crypto from './Crypto';
import { import {
base64ToArrayBuffer, base64ToArrayBuffer,
concatenateBytes, concatenateBytes,
fromEncodedBinaryToArrayBuffer,
getZeroes, getZeroes,
hexToArrayBuffer, hexToArrayBuffer,
} from '../Crypto'; } from '../Crypto';
@ -982,7 +981,7 @@ export default class MessageSender {
async sendTypingMessage( async sendTypingMessage(
options: { options: {
recipientId?: string; recipientId?: string;
groupId?: string; groupId?: ArrayBuffer;
groupMembers: Array<string>; groupMembers: Array<string>;
isTyping: boolean; isTyping: boolean;
timestamp?: number; timestamp?: number;
@ -1007,15 +1006,12 @@ export default class MessageSender {
const recipients = (groupId const recipients = (groupId
? without(groupMembers, myNumber, myUuid) ? without(groupMembers, myNumber, myUuid)
: [recipientId]) as Array<string>; : [recipientId]) as Array<string>;
const groupIdBuffer = groupId
? fromEncodedBinaryToArrayBuffer(groupId)
: null;
const action = isTyping ? ACTION_ENUM.STARTED : ACTION_ENUM.STOPPED; const action = isTyping ? ACTION_ENUM.STARTED : ACTION_ENUM.STOPPED;
const finalTimestamp = timestamp || Date.now(); const finalTimestamp = timestamp || Date.now();
const typingMessage = new window.textsecure.protobuf.TypingMessage(); const typingMessage = new window.textsecure.protobuf.TypingMessage();
typingMessage.groupId = groupIdBuffer; typingMessage.groupId = groupId || null;
typingMessage.action = action; typingMessage.action = action;
typingMessage.timestamp = finalTimestamp; typingMessage.timestamp = finalTimestamp;