Apply review suggestions
This commit is contained in:
parent
c62210b07c
commit
7207329c15
14 changed files with 201 additions and 195 deletions
|
@ -36,7 +36,6 @@ interface IProps extends Omit<React.ComponentProps<typeof BaseAvatar>, "name" |
|
|||
// Whether the onClick of the avatar should be overridden to dispatch `Action.ViewUser`
|
||||
viewUserOnClick?: boolean;
|
||||
title?: string;
|
||||
forExport?: boolean;
|
||||
}
|
||||
|
||||
interface IState {
|
||||
|
@ -90,8 +89,7 @@ export default class MemberAvatar extends React.Component<IProps, IState> {
|
|||
}
|
||||
|
||||
render() {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
let { member, fallbackUserId, onClick, viewUserOnClick, forExport, ...otherProps } = this.props;
|
||||
let { member, fallbackUserId, onClick, viewUserOnClick, ...otherProps } = this.props;
|
||||
const userId = member ? member.userId : fallbackUserId;
|
||||
|
||||
if (viewUserOnClick) {
|
||||
|
|
|
@ -29,13 +29,15 @@ import {
|
|||
textForFormat,
|
||||
textForType,
|
||||
} from "../../../utils/exportUtils/exportUtils";
|
||||
import { IFieldState, IValidationResult } from "../elements/Validation";
|
||||
import withValidation, { IFieldState, IValidationResult } from "../elements/Validation";
|
||||
import HTMLExporter from "../../../utils/exportUtils/HtmlExport";
|
||||
import JSONExporter from "../../../utils/exportUtils/JSONExport";
|
||||
import PlainTextExporter from "../../../utils/exportUtils/PlainTextExport";
|
||||
import { useStateCallback } from "../../../hooks/useStateCallback";
|
||||
import Exporter from "../../../utils/exportUtils/Exporter";
|
||||
import Spinner from "../elements/Spinner";
|
||||
import Modal from "../../../Modal";
|
||||
import InfoDialog from "./InfoDialog";
|
||||
|
||||
interface IProps extends IDialogProps {
|
||||
room: Room;
|
||||
|
@ -126,67 +128,85 @@ const ExportDialog: React.FC<IProps> = ({ room, onFinished }) => {
|
|||
await startExport();
|
||||
};
|
||||
|
||||
const onValidateSize = async ({
|
||||
value,
|
||||
}: Pick<IFieldState, "value">): Promise<IValidationResult> => {
|
||||
const parsedSize = parseFloat(value);
|
||||
const min = 1;
|
||||
const max = 2000;
|
||||
const validateSize = withValidation({
|
||||
rules: [
|
||||
{
|
||||
key: "required",
|
||||
test({ value, allowEmpty }) {
|
||||
return allowEmpty || !!value;
|
||||
},
|
||||
invalid: () => {
|
||||
const min = 1;
|
||||
const max = 10 ** 8;
|
||||
return _t("Enter a number between %(min)s and %(max)s", {
|
||||
min,
|
||||
max,
|
||||
});
|
||||
},
|
||||
}, {
|
||||
key: "number",
|
||||
test: ({ value }) => {
|
||||
const parsedSize = parseFloat(value);
|
||||
const min = 1;
|
||||
const max = 2000;
|
||||
return !(isNaN(parsedSize) || min > parsedSize || parsedSize > max);
|
||||
},
|
||||
invalid: () => {
|
||||
const min = 1;
|
||||
const max = 2000;
|
||||
return _t(
|
||||
"Size can only be a number between %(min)s MB and %(max)s MB",
|
||||
{ min, max },
|
||||
);
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
if (isNaN(parsedSize)) {
|
||||
return { valid: false, feedback: _t("Size must be a number") };
|
||||
}
|
||||
|
||||
if (min > parsedSize || parsedSize > max) {
|
||||
return {
|
||||
valid: false,
|
||||
feedback: _t(
|
||||
"Size can only be between %(min)s MB and %(max)s MB",
|
||||
{ min, max },
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
valid: true,
|
||||
feedback: _t("Enter size between %(min)s MB and %(max)s MB", {
|
||||
min,
|
||||
max,
|
||||
}),
|
||||
};
|
||||
const onValidateSize = async (fieldState: IFieldState): Promise<IValidationResult> => {
|
||||
const result = await validateSize(fieldState);
|
||||
return result;
|
||||
};
|
||||
|
||||
const onValidateNumberOfMessages = async ({
|
||||
value,
|
||||
}: Pick<IFieldState, "value">): Promise<IValidationResult> => {
|
||||
const parsedSize = parseFloat(value);
|
||||
const min = 1;
|
||||
const max = 10 ** 8;
|
||||
const validateNumberOfMessages = withValidation({
|
||||
rules: [
|
||||
{
|
||||
key: "required",
|
||||
test({ value, allowEmpty }) {
|
||||
return allowEmpty || !!value;
|
||||
},
|
||||
invalid: () => {
|
||||
const min = 1;
|
||||
const max = 10 ** 8;
|
||||
return _t("Enter a number between %(min)s and %(max)s", {
|
||||
min,
|
||||
max,
|
||||
});
|
||||
},
|
||||
}, {
|
||||
key: "number",
|
||||
test: ({ value }) => {
|
||||
const parsedSize = parseFloat(value);
|
||||
const min = 1;
|
||||
const max = 10 ** 8;
|
||||
if (isNaN(parsedSize)) return false;
|
||||
return !(min > parsedSize || parsedSize > max);
|
||||
},
|
||||
invalid: () => {
|
||||
const min = 1;
|
||||
const max = 10 ** 8;
|
||||
return _t(
|
||||
"Number of messages can only be a number between %(min)s and %(max)s",
|
||||
{ min, max },
|
||||
);
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
if (isNaN(parsedSize)) {
|
||||
return {
|
||||
valid: false,
|
||||
feedback: _t("Number of messages must be a number"),
|
||||
};
|
||||
}
|
||||
|
||||
if (min > parsedSize || parsedSize > max) {
|
||||
return {
|
||||
valid: false,
|
||||
feedback: _t(
|
||||
"Number of messages can only be between %(min)s and %(max)s",
|
||||
{ min, max },
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
valid: true,
|
||||
feedback: _t("Enter a number between %(min)s and %(max)s", {
|
||||
min,
|
||||
max,
|
||||
}),
|
||||
};
|
||||
const onValidateNumberOfMessages = async (fieldState: IFieldState): Promise<IValidationResult> => {
|
||||
const result = await validateNumberOfMessages(fieldState);
|
||||
return result;
|
||||
};
|
||||
|
||||
const onCancel = async () => {
|
||||
|
@ -236,42 +256,20 @@ const ExportDialog: React.FC<IProps> = ({ room, onFinished }) => {
|
|||
|
||||
if (exportCancelled) {
|
||||
// Display successful cancellation message
|
||||
return (
|
||||
<BaseDialog
|
||||
title={_t("Export Cancelled")}
|
||||
className="mx_ExportDialog"
|
||||
contentId="mx_Dialog_content"
|
||||
onFinished={onFinished}
|
||||
fixedWidth={true}
|
||||
>
|
||||
<p>{ _t("The export was cancelled successfully") }</p>
|
||||
|
||||
<DialogButtons
|
||||
primaryButton={_t("Okay")}
|
||||
hasCancel={false}
|
||||
onPrimaryButtonClick={onFinished}
|
||||
/>
|
||||
</BaseDialog>
|
||||
);
|
||||
Modal.createTrackedDialog("Export Cancelled", "", InfoDialog, {
|
||||
title: _t("Export Cancelled"),
|
||||
description: <p>{ _t("The export was cancelled successfully") }</p>,
|
||||
hasCloseButton: true,
|
||||
});
|
||||
return null;
|
||||
} else if (exportSuccessful) {
|
||||
// Display successful export message
|
||||
return (
|
||||
<BaseDialog
|
||||
title={_t("Export Successful")}
|
||||
className="mx_ExportDialog"
|
||||
contentId="mx_Dialog_content"
|
||||
onFinished={onFinished}
|
||||
fixedWidth={true}
|
||||
>
|
||||
<p>{ _t("Your messages were successfully exported") }</p>
|
||||
|
||||
<DialogButtons
|
||||
primaryButton={_t("Okay")}
|
||||
hasCancel={false}
|
||||
onPrimaryButtonClick={onFinished}
|
||||
/>
|
||||
</BaseDialog>
|
||||
);
|
||||
Modal.createTrackedDialog("Export Successful", "", InfoDialog, {
|
||||
title: _t("Export Successful"),
|
||||
description: <p>{ _t("Your messages were successfully exported") }</p>,
|
||||
hasCloseButton: true,
|
||||
});
|
||||
return null;
|
||||
} else if (displayCancel) {
|
||||
// Display cancel warning
|
||||
return (
|
||||
|
|
|
@ -355,10 +355,10 @@ export default class ReplyThread extends React.Component<IProps, IState> {
|
|||
} else if (this.props.forExport) {
|
||||
const eventId = ReplyThread.getParentEventId(this.props.parentEv);
|
||||
header = <p className="mx_ReplyThread_Export">
|
||||
{ _t("In reply to <messageLink/>",
|
||||
{ _t("In reply to <a>this message</a>",
|
||||
{},
|
||||
{ messageLink: () => (
|
||||
<a className="mx_reply_anchor" href={`#${eventId}`} scroll-to={eventId}> { _t("this message") } </a>
|
||||
{ a: (sub) => (
|
||||
<a className="mx_reply_anchor" href={`#${eventId}`} scroll-to={eventId}> { sub } </a>
|
||||
),
|
||||
})
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ export default class CallEvent extends React.Component<IProps, IState> {
|
|||
super(props);
|
||||
|
||||
this.state = {
|
||||
callState: this.props.callEventGrouper?.state,
|
||||
callState: this.props.callEventGrouper.state,
|
||||
silenced: false,
|
||||
};
|
||||
}
|
||||
|
@ -210,7 +210,7 @@ export default class CallEvent extends React.Component<IProps, IState> {
|
|||
render() {
|
||||
const event = this.props.mxEvent;
|
||||
const sender = event.sender ? event.sender.name : event.getSender();
|
||||
const isVoice = this.props.callEventGrouper?.isVoice;
|
||||
const isVoice = this.props.callEventGrouper.isVoice;
|
||||
const callType = isVoice ? _t("Voice call") : _t("Video call");
|
||||
const callState = this.state.callState;
|
||||
const hangupReason = this.props.callEventGrouper.hangupReason;
|
||||
|
|
|
@ -201,11 +201,7 @@ export default class MFileBody extends React.Component<IProps, IState> {
|
|||
if (this.props.showGenericPlaceholder) {
|
||||
placeholder = (
|
||||
<AccessibleButton className="mx_MediaBody mx_MFileBody_info" onClick={this.onPlaceholderClick}>
|
||||
<span className="mx_MFileBody_info_icon">
|
||||
{ this.props.forExport ?
|
||||
<img alt="Attachment" className="mx_export_attach_icon" src="icons/attach.svg" />
|
||||
: null }
|
||||
</span>
|
||||
<span className="mx_MFileBody_info_icon" />
|
||||
<TextWithTooltip tooltip={presentableTextForFile(this.content, _t("Attachment"), true)}>
|
||||
<span className="mx_MFileBody_info_filename">
|
||||
{ presentableTextForFile(this.content, _t("Attachment"), true, true) }
|
||||
|
|
|
@ -39,7 +39,6 @@ const RedactedBody = React.forwardRef<any, IBodyProps>(({ mxEvent, forExport },
|
|||
|
||||
return (
|
||||
<span className="mx_RedactedBody" ref={ref} title={titleText}>
|
||||
{ forExport ? <img alt={_t("Redacted")} className="mx_export_trash_icon" src="icons/trash.svg" /> : null }
|
||||
{ text }
|
||||
</span>
|
||||
);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue