Happily handle empty text messages (#6825)
This commig refactors the message-deletion modal and reuses it for case of removing the entire message and trying to send it, which should trigger removal flow instead. Fix vector-im/element-web#18873
This commit is contained in:
parent
e95e59e2eb
commit
8331d4c7b7
4 changed files with 57 additions and 31 deletions
|
@ -34,8 +34,7 @@ import ForwardDialog from "../dialogs/ForwardDialog";
|
||||||
import { Action } from "../../../dispatcher/actions";
|
import { Action } from "../../../dispatcher/actions";
|
||||||
import ReportEventDialog from '../dialogs/ReportEventDialog';
|
import ReportEventDialog from '../dialogs/ReportEventDialog';
|
||||||
import ViewSource from '../../structures/ViewSource';
|
import ViewSource from '../../structures/ViewSource';
|
||||||
import ConfirmRedactDialog from '../dialogs/ConfirmRedactDialog';
|
import { createRedactEventDialog } from '../dialogs/ConfirmRedactDialog';
|
||||||
import ErrorDialog from '../dialogs/ErrorDialog';
|
|
||||||
import ShareDialog from '../dialogs/ShareDialog';
|
import ShareDialog from '../dialogs/ShareDialog';
|
||||||
import { RoomPermalinkCreator } from "../../../utils/permalinks/Permalinks";
|
import { RoomPermalinkCreator } from "../../../utils/permalinks/Permalinks";
|
||||||
import { IPosition, ChevronFace } from '../../structures/ContextMenu';
|
import { IPosition, ChevronFace } from '../../structures/ContextMenu';
|
||||||
|
@ -140,34 +139,11 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
|
||||||
};
|
};
|
||||||
|
|
||||||
private onRedactClick = (): void => {
|
private onRedactClick = (): void => {
|
||||||
Modal.createTrackedDialog('Confirm Redact Dialog', '', ConfirmRedactDialog, {
|
const { mxEvent, onCloseDialog } = this.props;
|
||||||
onFinished: async (proceed: boolean, reason?: string) => {
|
createRedactEventDialog({
|
||||||
if (!proceed) return;
|
mxEvent,
|
||||||
|
onCloseDialog,
|
||||||
const cli = MatrixClientPeg.get();
|
});
|
||||||
try {
|
|
||||||
this.props.onCloseDialog?.();
|
|
||||||
await cli.redactEvent(
|
|
||||||
this.props.mxEvent.getRoomId(),
|
|
||||||
this.props.mxEvent.getId(),
|
|
||||||
undefined,
|
|
||||||
reason ? { reason } : {},
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
const code = e.errcode || e.statusCode;
|
|
||||||
// only show the dialog if failing for something other than a network error
|
|
||||||
// (e.g. no errcode or statusCode) as in that case the redactions end up in the
|
|
||||||
// detached queue and we show the room status bar to allow retry
|
|
||||||
if (typeof code !== "undefined") {
|
|
||||||
// display error message stating you couldn't delete this.
|
|
||||||
Modal.createTrackedDialog('You cannot delete this message', '', ErrorDialog, {
|
|
||||||
title: _t('Error'),
|
|
||||||
description: _t('You cannot delete this message. (%(code)s)', { code }),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}, 'mx_Dialog_confirmredact');
|
|
||||||
this.closeMenu();
|
this.closeMenu();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -14,9 +14,13 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { MatrixEvent } from 'matrix-js-sdk/src/models/event';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { _t } from '../../../languageHandler';
|
import { _t } from '../../../languageHandler';
|
||||||
|
import { MatrixClientPeg } from '../../../MatrixClientPeg';
|
||||||
|
import Modal from '../../../Modal';
|
||||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||||
|
import ErrorDialog from './ErrorDialog';
|
||||||
import TextInputDialog from "./TextInputDialog";
|
import TextInputDialog from "./TextInputDialog";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
|
@ -42,3 +46,40 @@ export default class ConfirmRedactDialog extends React.Component<IProps> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function createRedactEventDialog({
|
||||||
|
mxEvent,
|
||||||
|
onCloseDialog = () => {},
|
||||||
|
}: {
|
||||||
|
mxEvent: MatrixEvent;
|
||||||
|
onCloseDialog?: () => void;
|
||||||
|
}) {
|
||||||
|
Modal.createTrackedDialog('Confirm Redact Dialog', '', ConfirmRedactDialog, {
|
||||||
|
onFinished: async (proceed: boolean, reason?: string) => {
|
||||||
|
if (!proceed) return;
|
||||||
|
|
||||||
|
const cli = MatrixClientPeg.get();
|
||||||
|
try {
|
||||||
|
onCloseDialog?.();
|
||||||
|
await cli.redactEvent(
|
||||||
|
mxEvent.getRoomId(),
|
||||||
|
mxEvent.getId(),
|
||||||
|
undefined,
|
||||||
|
reason ? { reason } : {},
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
const code = e.errcode || e.statusCode;
|
||||||
|
// only show the dialog if failing for something other than a network error
|
||||||
|
// (e.g. no errcode or statusCode) as in that case the redactions end up in the
|
||||||
|
// detached queue and we show the room status bar to allow retry
|
||||||
|
if (typeof code !== "undefined") {
|
||||||
|
// display error message stating you couldn't delete this.
|
||||||
|
Modal.createTrackedDialog('You cannot delete this message', '', ErrorDialog, {
|
||||||
|
title: _t('Error'),
|
||||||
|
description: _t('You cannot delete this message. (%(code)s)', { code }),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}, 'mx_Dialog_confirmredact');
|
||||||
|
}
|
||||||
|
|
|
@ -42,6 +42,7 @@ import ErrorDialog from "../dialogs/ErrorDialog";
|
||||||
import QuestionDialog from "../dialogs/QuestionDialog";
|
import QuestionDialog from "../dialogs/QuestionDialog";
|
||||||
import { ActionPayload } from "../../../dispatcher/payloads";
|
import { ActionPayload } from "../../../dispatcher/payloads";
|
||||||
import AccessibleButton from '../elements/AccessibleButton';
|
import AccessibleButton from '../elements/AccessibleButton';
|
||||||
|
import { createRedactEventDialog } from '../dialogs/ConfirmRedactDialog';
|
||||||
import SettingsStore from "../../../settings/SettingsStore";
|
import SettingsStore from "../../../settings/SettingsStore";
|
||||||
|
|
||||||
import { logger } from "matrix-js-sdk/src/logger";
|
import { logger } from "matrix-js-sdk/src/logger";
|
||||||
|
@ -331,6 +332,14 @@ export default class EditMessageComposer extends React.Component<IProps, IState>
|
||||||
|
|
||||||
let shouldSend = true;
|
let shouldSend = true;
|
||||||
|
|
||||||
|
if (newContent?.body === '') {
|
||||||
|
this.cancelPreviousPendingEdit();
|
||||||
|
createRedactEventDialog({
|
||||||
|
mxEvent: editedEvent,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// If content is modified then send an updated event into the room
|
// If content is modified then send an updated event into the room
|
||||||
if (this.isContentModified(newContent)) {
|
if (this.isContentModified(newContent)) {
|
||||||
const roomId = editedEvent.getRoomId();
|
const roomId = editedEvent.getRoomId();
|
||||||
|
|
|
@ -185,7 +185,7 @@ export function startsWith(model: EditorModel, prefix: string, caseSensitive = t
|
||||||
const firstPart = model.parts[0];
|
const firstPart = model.parts[0];
|
||||||
// part type will be "plain" while editing,
|
// part type will be "plain" while editing,
|
||||||
// and "command" while composing a message.
|
// and "command" while composing a message.
|
||||||
let text = firstPart && firstPart.text;
|
let text = firstPart?.text || '';
|
||||||
if (!caseSensitive) {
|
if (!caseSensitive) {
|
||||||
prefix = prefix.toLowerCase();
|
prefix = prefix.toLowerCase();
|
||||||
text = text.toLowerCase();
|
text = text.toLowerCase();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue