Fix left pane draft display and GV2 typing indicators
This commit is contained in:
parent
ab89c6c704
commit
18c71b291c
5 changed files with 58 additions and 31 deletions
|
@ -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,
|
||||||
|
|
|
@ -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}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue