Show error when editing messages after max edits

This commit is contained in:
ayumi-signal 2023-11-07 17:55:48 -08:00 committed by GitHub
parent 6d66bf1600
commit bb8e7af905
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 49 additions and 8 deletions

View file

@ -3771,6 +3771,14 @@
"messageformat": "Okay",
"description": "Button to dismiss popup dialog when user-initiated task has gone wrong"
},
"icu:MessageMaxEditsModal__Title": {
"messageformat": "Can't edit message",
"description": "Title in popup dialog when attempting to edit a message too many times."
},
"icu:MessageMaxEditsModal__Description": {
"messageformat": "Only {max, number} edits can be applied to this message.",
"description": "Description text in popup dialog when attempting to edit a message too many times."
},
"icu:unknown-sgnl-link": {
"messageformat": "Sorry, that sgnl:// link didn't make sense!",
"description": "Shown if you click on a sgnl:// link not currently supported by Desktop"

View file

@ -29,10 +29,12 @@ import * as Attachment from '../../types/Attachment';
import { isFileDangerous } from '../../util/isFileDangerous';
import type {
ShowSendAnywayDialogActionType,
ShowErrorModalActionType,
ToggleProfileEditorErrorActionType,
} from './globalModals';
import {
SHOW_SEND_ANYWAY_DIALOG,
SHOW_ERROR_MODAL,
TOGGLE_PROFILE_EDITOR_ERROR,
} from './globalModals';
import {
@ -90,6 +92,7 @@ import {
getMe,
getMessagesByConversation,
} from '../selectors/conversations';
import { getIntl } from '../selectors/user';
import type { AvatarDataType, AvatarUpdateType } from '../../types/Avatar';
import { getDefaultAvatars } from '../../types/Avatar';
import { getAvatarData } from '../../util/getAvatarData';
@ -164,7 +167,11 @@ import {
} from './composer';
import { ReceiptType } from '../../types/Receipt';
import { Sound, SoundType } from '../../util/Sound';
import { canEditMessage } from '../../util/canEditMessage';
import {
canEditMessage,
isWithinMaxEdits,
MESSAGE_MAX_EDIT_COUNT,
} from '../../util/canEditMessage';
import type { ChangeNavTabActionType } from './nav';
import { CHANGE_NAV_TAB, NavTab, actions as navActions } from './nav';
import { sortByMessageOrder } from '../../types/ForwardDraft';
@ -1770,7 +1777,12 @@ function discardEditMessage(
function setMessageToEdit(
conversationId: string,
messageId: string
): ThunkAction<void, RootStateType, unknown, SetFocusActionType> {
): ThunkAction<
void,
RootStateType,
unknown,
SetFocusActionType | ShowErrorModalActionType
> {
return async (dispatch, getState) => {
const conversation = window.ConversationController.get(conversationId);
@ -1787,6 +1799,20 @@ function setMessageToEdit(
return;
}
if (!isWithinMaxEdits(message)) {
const i18n = getIntl(getState());
dispatch({
type: SHOW_ERROR_MODAL,
payload: {
title: i18n('icu:MessageMaxEditsModal__Title'),
description: i18n('icu:MessageMaxEditsModal__Description', {
max: MESSAGE_MAX_EDIT_COUNT,
}),
},
});
return;
}
setQuoteByMessageId(conversationId, undefined)(
dispatch,
getState,

View file

@ -135,7 +135,7 @@ const CLOSE_GV2_MIGRATION_DIALOG = 'globalModals/CLOSE_GV2_MIGRATION_DIALOG';
const SHOW_STICKER_PACK_PREVIEW = 'globalModals/SHOW_STICKER_PACK_PREVIEW';
const CLOSE_STICKER_PACK_PREVIEW = 'globalModals/CLOSE_STICKER_PACK_PREVIEW';
const CLOSE_ERROR_MODAL = 'globalModals/CLOSE_ERROR_MODAL';
const SHOW_ERROR_MODAL = 'globalModals/SHOW_ERROR_MODAL';
export const SHOW_ERROR_MODAL = 'globalModals/SHOW_ERROR_MODAL';
const SHOW_FORMATTING_WARNING_MODAL =
'globalModals/SHOW_FORMATTING_WARNING_MODAL';
const SHOW_SEND_EDIT_WARNING_MODAL =
@ -286,7 +286,7 @@ type CloseErrorModalActionType = ReadonlyDeep<{
type: typeof CLOSE_ERROR_MODAL;
}>;
type ShowErrorModalActionType = ReadonlyDeep<{
export type ShowErrorModalActionType = ReadonlyDeep<{
type: typeof SHOW_ERROR_MODAL;
payload: {
description?: string;

View file

@ -1215,6 +1215,7 @@ export const getConversationTitle = createSelector(
getConversationTitleForPanelType(i18n, panel?.type)
);
// Note that this doesn't take into account max edit count. See canEditMessage.
export const getLastEditableMessageId = createSelector(
getConversationMessages,
getMessages,

View file

@ -8,7 +8,7 @@ import { isMoreRecentThan } from './timestamp';
import { isOutgoing } from '../messages/helpers';
import { isSent, someSendStatus } from '../messages/MessageSendState';
const MAX_EDIT_COUNT = 10;
export const MESSAGE_MAX_EDIT_COUNT = 10;
export function canEditMessage(message: MessageAttributesType): boolean {
const result =
@ -16,7 +16,6 @@ export function canEditMessage(message: MessageAttributesType): boolean {
!message.deletedForEveryone &&
isOutgoing(message) &&
isMoreRecentThan(message.sent_at, DAY) &&
(message.editHistory?.length ?? 0) <= MAX_EDIT_COUNT &&
someSendStatus(message.sendStateByConversationId, isSent) &&
Boolean(message.body);
@ -35,3 +34,7 @@ export function canEditMessage(message: MessageAttributesType): boolean {
return false;
}
export function isWithinMaxEdits(message: MessageAttributesType): boolean {
return (message.editHistory?.length ?? 0) <= MESSAGE_MAX_EDIT_COUNT;
}

View file

@ -15,7 +15,7 @@ import { ErrorWithToast } from '../types/ErrorWithToast';
import { SendStatus } from '../messages/MessageSendState';
import { ToastType } from '../types/Toast';
import type { AciString } from '../types/ServiceId';
import { canEditMessage } from './canEditMessage';
import { canEditMessage, isWithinMaxEdits } from './canEditMessage';
import {
conversationJobQueue,
conversationQueueJobEnum,
@ -77,7 +77,10 @@ export async function sendEditedMessage(
return;
}
if (!canEditMessage(targetMessage.attributes)) {
if (
!canEditMessage(targetMessage.attributes) ||
!isWithinMaxEdits(targetMessage.attributes)
) {
throw new ErrorWithToast(
`${idLog}: cannot edit`,
ToastType.CannotEditMessage