Delete for everyone: Track sends and show failure states
This commit is contained in:
parent
688cca1806
commit
0a52318be6
24 changed files with 426 additions and 60 deletions
|
@ -104,6 +104,8 @@ const createProps = (overrideProps: Partial<Props> = {}): Props => ({
|
|||
canReply: true,
|
||||
canDownload: true,
|
||||
canDeleteForEveryone: overrideProps.canDeleteForEveryone || false,
|
||||
canRetry: overrideProps.canRetry || false,
|
||||
canRetryDeleteForEveryone: overrideProps.canRetryDeleteForEveryone || false,
|
||||
checkForAccount: action('checkForAccount'),
|
||||
clearSelectedMessage: action('clearSelectedMessage'),
|
||||
collapseMetadata: overrideProps.collapseMetadata,
|
||||
|
@ -165,6 +167,7 @@ const createProps = (overrideProps: Partial<Props> = {}): Props => ({
|
|||
renderAudioAttachment,
|
||||
replyToMessage: action('replyToMessage'),
|
||||
retrySend: action('retrySend'),
|
||||
retryDeleteForEveryone: action('retryDeleteForEveryone'),
|
||||
scrollToQuotedMessage: action('scrollToQuotedMessage'),
|
||||
selectMessage: action('selectMessage'),
|
||||
showContactDetail: action('showContactDetail'),
|
||||
|
@ -574,13 +577,23 @@ story.add('Sticker', () => {
|
|||
});
|
||||
|
||||
story.add('Deleted', () => {
|
||||
const props = createProps({
|
||||
const propsSent = createProps({
|
||||
conversationType: 'group',
|
||||
deletedForEveryone: true,
|
||||
status: 'sent',
|
||||
});
|
||||
const propsSending = createProps({
|
||||
conversationType: 'group',
|
||||
deletedForEveryone: true,
|
||||
status: 'sending',
|
||||
});
|
||||
|
||||
return renderBothDirections(props);
|
||||
return (
|
||||
<>
|
||||
{renderBothDirections(propsSent)}
|
||||
{renderBothDirections(propsSending)}
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
||||
story.add('Deleted with expireTimer', () => {
|
||||
|
@ -596,6 +609,30 @@ story.add('Deleted with expireTimer', () => {
|
|||
return renderBothDirections(props);
|
||||
});
|
||||
|
||||
story.add('Deleted with error', () => {
|
||||
const propsPartialError = createProps({
|
||||
timestamp: Date.now() - 60 * 1000,
|
||||
canDeleteForEveryone: true,
|
||||
conversationType: 'group',
|
||||
deletedForEveryone: true,
|
||||
status: 'partial-sent',
|
||||
});
|
||||
const propsError = createProps({
|
||||
timestamp: Date.now() - 60 * 1000,
|
||||
canDeleteForEveryone: true,
|
||||
conversationType: 'group',
|
||||
deletedForEveryone: true,
|
||||
status: 'error',
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
{renderBothDirections(propsPartialError)}
|
||||
{renderBothDirections(propsError)}
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
||||
story.add('Can delete for everyone', () => {
|
||||
const props = createProps({
|
||||
status: 'read',
|
||||
|
@ -609,6 +646,7 @@ story.add('Can delete for everyone', () => {
|
|||
story.add('Error', () => {
|
||||
const props = createProps({
|
||||
status: 'error',
|
||||
canRetry: true,
|
||||
text: 'I hope you get this.',
|
||||
});
|
||||
|
||||
|
@ -1298,6 +1336,8 @@ story.add('All the context menus', () => {
|
|||
],
|
||||
status: 'partial-sent',
|
||||
canDeleteForEveryone: true,
|
||||
canRetry: true,
|
||||
canRetryDeleteForEveryone: true,
|
||||
});
|
||||
|
||||
return <Message {...props} direction="outgoing" />;
|
||||
|
|
|
@ -197,6 +197,8 @@ export type PropsData = {
|
|||
|
||||
deletedForEveryone?: boolean;
|
||||
|
||||
canRetry: boolean;
|
||||
canRetryDeleteForEveryone: boolean;
|
||||
canReact: boolean;
|
||||
canReply: boolean;
|
||||
canDownload: boolean;
|
||||
|
@ -234,6 +236,7 @@ export type PropsActions = {
|
|||
{ emoji, remove }: { emoji: string; remove: boolean }
|
||||
) => void;
|
||||
replyToMessage: (id: string) => void;
|
||||
retryDeleteForEveryone: (id: string) => void;
|
||||
retrySend: (id: string) => void;
|
||||
showForwardMessageModal: (id: string) => void;
|
||||
deleteMessage: (id: string) => void;
|
||||
|
@ -424,7 +427,7 @@ export class Message extends React.PureComponent<Props, State> {
|
|||
|
||||
public override componentDidMount(): void {
|
||||
const { conversationId } = this.props;
|
||||
window.ConversationController.onConvoMessageMount(conversationId);
|
||||
window.ConversationController?.onConvoMessageMount(conversationId);
|
||||
|
||||
this.startSelectedTimer();
|
||||
this.startDeleteForEveryoneTimerIfApplicable();
|
||||
|
@ -1486,29 +1489,24 @@ export class Message extends React.PureComponent<Props, State> {
|
|||
canDownload,
|
||||
canReact,
|
||||
canReply,
|
||||
canRetry,
|
||||
canRetryDeleteForEveryone,
|
||||
deleteMessage,
|
||||
deleteMessageForEveryone,
|
||||
deletedForEveryone,
|
||||
direction,
|
||||
i18n,
|
||||
id,
|
||||
isSticker,
|
||||
isTapToView,
|
||||
replyToMessage,
|
||||
retrySend,
|
||||
retryDeleteForEveryone,
|
||||
showForwardMessageModal,
|
||||
showMessageDetail,
|
||||
status,
|
||||
text,
|
||||
} = this.props;
|
||||
|
||||
const canForward = !isTapToView && !deletedForEveryone;
|
||||
|
||||
const showRetry =
|
||||
(status === 'paused' ||
|
||||
status === 'error' ||
|
||||
status === 'partial-sent') &&
|
||||
direction === 'outgoing';
|
||||
const multipleAttachments = attachments && attachments.length > 1;
|
||||
|
||||
const shouldShowAdditional =
|
||||
|
@ -1583,7 +1581,7 @@ export class Message extends React.PureComponent<Props, State> {
|
|||
>
|
||||
{i18n('moreInfo')}
|
||||
</MenuItem>
|
||||
{showRetry ? (
|
||||
{canRetry ? (
|
||||
<MenuItem
|
||||
attributes={{
|
||||
className:
|
||||
|
@ -1599,6 +1597,22 @@ export class Message extends React.PureComponent<Props, State> {
|
|||
{i18n('retrySend')}
|
||||
</MenuItem>
|
||||
) : null}
|
||||
{canRetryDeleteForEveryone ? (
|
||||
<MenuItem
|
||||
attributes={{
|
||||
className:
|
||||
'module-message__context--icon module-message__context__delete-message-for-everyone',
|
||||
}}
|
||||
onClick={(event: React.MouseEvent) => {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
|
||||
retryDeleteForEveryone(id);
|
||||
}}
|
||||
>
|
||||
{i18n('retryDeleteForEveryone')}
|
||||
</MenuItem>
|
||||
) : null}
|
||||
{canForward ? (
|
||||
<MenuItem
|
||||
attributes={{
|
||||
|
|
|
@ -29,6 +29,8 @@ const defaultMessage: MessageDataPropsType = {
|
|||
}),
|
||||
canReact: true,
|
||||
canReply: true,
|
||||
canRetry: true,
|
||||
canRetryDeleteForEveryone: true,
|
||||
canDeleteForEveryone: true,
|
||||
canDownload: true,
|
||||
conversationColor: 'crimson',
|
||||
|
@ -84,6 +86,7 @@ const createProps = (overrideProps: Partial<Props> = {}): Props => ({
|
|||
renderReactionPicker: () => <div />,
|
||||
replyToMessage: action('replyToMessage'),
|
||||
retrySend: action('retrySend'),
|
||||
retryDeleteForEveryone: action('retryDeleteForEveryone'),
|
||||
showContactDetail: action('showContactDetail'),
|
||||
showContactModal: action('showContactModal'),
|
||||
showExpiredIncomingTapToViewToast: action(
|
||||
|
|
|
@ -81,6 +81,7 @@ export type PropsBackboneActions = Pick<
|
|||
| 'renderEmojiPicker'
|
||||
| 'renderReactionPicker'
|
||||
| 'replyToMessage'
|
||||
| 'retryDeleteForEveryone'
|
||||
| 'retrySend'
|
||||
| 'showContactDetail'
|
||||
| 'showContactModal'
|
||||
|
@ -303,6 +304,7 @@ export class MessageDetail extends React.Component<Props, State> {
|
|||
renderEmojiPicker,
|
||||
renderReactionPicker,
|
||||
replyToMessage,
|
||||
retryDeleteForEveryone,
|
||||
retrySend,
|
||||
showContactDetail,
|
||||
showContactModal,
|
||||
|
@ -358,6 +360,7 @@ export class MessageDetail extends React.Component<Props, State> {
|
|||
renderEmojiPicker={renderEmojiPicker}
|
||||
renderReactionPicker={renderReactionPicker}
|
||||
replyToMessage={replyToMessage}
|
||||
retryDeleteForEveryone={retryDeleteForEveryone}
|
||||
retrySend={retrySend}
|
||||
showForwardMessageModal={showForwardMessageModal}
|
||||
scrollToQuotedMessage={() => {
|
||||
|
|
|
@ -61,7 +61,9 @@ export const MessageMetadata: FunctionComponent<PropsType> = props => {
|
|||
if (isError || isPartiallySent || isPaused) {
|
||||
let statusInfo: React.ReactChild;
|
||||
if (isError) {
|
||||
statusInfo = i18n('sendFailed');
|
||||
statusInfo = deletedForEveryone
|
||||
? i18n('deleteFailed')
|
||||
: i18n('sendFailed');
|
||||
} else if (isPaused) {
|
||||
statusInfo = i18n('sendPaused');
|
||||
} else {
|
||||
|
@ -76,7 +78,9 @@ export const MessageMetadata: FunctionComponent<PropsType> = props => {
|
|||
showMessageDetail(id);
|
||||
}}
|
||||
>
|
||||
{i18n('partiallySent')}
|
||||
{deletedForEveryone
|
||||
? i18n('partiallyDeleted')
|
||||
: i18n('partiallySent')}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
@ -136,7 +140,7 @@ export const MessageMetadata: FunctionComponent<PropsType> = props => {
|
|||
<Spinner svgSize="small" size="14px" direction={direction} />
|
||||
</div>
|
||||
) : null}
|
||||
{!deletedForEveryone &&
|
||||
{(!deletedForEveryone || status === 'sending') &&
|
||||
!textPending &&
|
||||
direction === 'outgoing' &&
|
||||
status !== 'error' &&
|
||||
|
|
|
@ -39,6 +39,8 @@ const defaultMessageProps: MessagesProps = {
|
|||
}),
|
||||
canReact: true,
|
||||
canReply: true,
|
||||
canRetry: true,
|
||||
canRetryDeleteForEveryone: true,
|
||||
canDeleteForEveryone: true,
|
||||
canDownload: true,
|
||||
checkForAccount: action('checkForAccount'),
|
||||
|
@ -78,6 +80,7 @@ const defaultMessageProps: MessagesProps = {
|
|||
renderAudioAttachment: () => <div>*AudioAttachment*</div>,
|
||||
replyToMessage: action('default--replyToMessage'),
|
||||
retrySend: action('default--retrySend'),
|
||||
retryDeleteForEveryone: action('default--retryDeleteForEveryone'),
|
||||
scrollToQuotedMessage: action('default--scrollToQuotedMessage'),
|
||||
selectMessage: action('default--selectMessage'),
|
||||
showContactDetail: action('default--showContactDetail'),
|
||||
|
|
|
@ -50,6 +50,8 @@ const items: Record<string, TimelineItemType> = {
|
|||
canDownload: true,
|
||||
canReact: true,
|
||||
canReply: true,
|
||||
canRetry: true,
|
||||
canRetryDeleteForEveryone: true,
|
||||
conversationColor: 'forest',
|
||||
conversationId: 'conversation-id',
|
||||
conversationType: 'group',
|
||||
|
@ -72,6 +74,8 @@ const items: Record<string, TimelineItemType> = {
|
|||
canDownload: true,
|
||||
canReact: true,
|
||||
canReply: true,
|
||||
canRetry: true,
|
||||
canRetryDeleteForEveryone: true,
|
||||
conversationColor: 'forest',
|
||||
conversationId: 'conversation-id',
|
||||
conversationType: 'group',
|
||||
|
@ -108,6 +112,8 @@ const items: Record<string, TimelineItemType> = {
|
|||
canDownload: true,
|
||||
canReact: true,
|
||||
canReply: true,
|
||||
canRetry: true,
|
||||
canRetryDeleteForEveryone: true,
|
||||
conversationColor: 'crimson',
|
||||
conversationId: 'conversation-id',
|
||||
conversationType: 'group',
|
||||
|
@ -205,6 +211,8 @@ const items: Record<string, TimelineItemType> = {
|
|||
canDownload: true,
|
||||
canReact: true,
|
||||
canReply: true,
|
||||
canRetry: true,
|
||||
canRetryDeleteForEveryone: true,
|
||||
conversationColor: 'plum',
|
||||
conversationId: 'conversation-id',
|
||||
conversationType: 'group',
|
||||
|
@ -228,6 +236,8 @@ const items: Record<string, TimelineItemType> = {
|
|||
canDownload: true,
|
||||
canReact: true,
|
||||
canReply: true,
|
||||
canRetry: true,
|
||||
canRetryDeleteForEveryone: true,
|
||||
conversationColor: 'crimson',
|
||||
conversationId: 'conversation-id',
|
||||
conversationType: 'group',
|
||||
|
@ -251,6 +261,8 @@ const items: Record<string, TimelineItemType> = {
|
|||
canDownload: true,
|
||||
canReact: true,
|
||||
canReply: true,
|
||||
canRetry: true,
|
||||
canRetryDeleteForEveryone: true,
|
||||
conversationColor: 'crimson',
|
||||
conversationId: 'conversation-id',
|
||||
conversationType: 'group',
|
||||
|
@ -274,6 +286,8 @@ const items: Record<string, TimelineItemType> = {
|
|||
canDownload: true,
|
||||
canReact: true,
|
||||
canReply: true,
|
||||
canRetry: true,
|
||||
canRetryDeleteForEveryone: true,
|
||||
conversationColor: 'crimson',
|
||||
conversationId: 'conversation-id',
|
||||
conversationType: 'group',
|
||||
|
@ -297,6 +311,8 @@ const items: Record<string, TimelineItemType> = {
|
|||
canDownload: true,
|
||||
canReact: true,
|
||||
canReply: true,
|
||||
canRetry: true,
|
||||
canRetryDeleteForEveryone: true,
|
||||
conversationColor: 'crimson',
|
||||
conversationId: 'conversation-id',
|
||||
conversationType: 'group',
|
||||
|
@ -340,6 +356,7 @@ const actions = () => ({
|
|||
|
||||
reactToMessage: action('reactToMessage'),
|
||||
replyToMessage: action('replyToMessage'),
|
||||
retryDeleteForEveryone: action('retryDeleteForEveryone'),
|
||||
retrySend: action('retrySend'),
|
||||
deleteMessage: action('deleteMessage'),
|
||||
deleteMessageForEveryone: action('deleteMessageForEveryone'),
|
||||
|
|
|
@ -217,6 +217,7 @@ const getActions = createSelector(
|
|||
'checkForAccount',
|
||||
'reactToMessage',
|
||||
'replyToMessage',
|
||||
'retryDeleteForEveryone',
|
||||
'retrySend',
|
||||
'showForwardMessageModal',
|
||||
'deleteMessage',
|
||||
|
|
|
@ -63,6 +63,7 @@ const getDefaultProps = () => ({
|
|||
clearSelectedMessage: action('clearSelectedMessage'),
|
||||
contactSupport: action('contactSupport'),
|
||||
replyToMessage: action('replyToMessage'),
|
||||
retryDeleteForEveryone: action('retryDeleteForEveryone'),
|
||||
retrySend: action('retrySend'),
|
||||
deleteMessage: action('deleteMessage'),
|
||||
deleteMessageForEveryone: action('deleteMessageForEveryone'),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue