Rewrite export tool to use existing components to render output, use existing source URLs for media

This commit is contained in:
Jaiwanth 2021-05-31 19:01:32 +05:30
parent 60ef6f9332
commit 573a3ca983
8 changed files with 367 additions and 648 deletions

View file

@ -41,7 +41,7 @@ const continuedTypes = ['m.sticker', 'm.room.message'];
// check if there is a previous event and it has the same sender as this event
// and the types are the same/is in continuedTypes and the time between them is <= CONTINUATION_MAX_INTERVAL
function shouldFormContinuation(prevEvent, mxEvent) {
export function shouldFormContinuation(prevEvent, mxEvent) {
// sanity check inputs
if (!prevEvent || !prevEvent.sender || !mxEvent.sender) return false;
// check if within the max continuation period

View file

@ -46,6 +46,7 @@ export default class ReplyThread extends React.Component {
permalinkCreator: PropTypes.instanceOf(RoomPermalinkCreator).isRequired,
// Specifies which layout to use.
layout: LayoutPropType,
isExporting: PropTypes.bool,
};
static contextType = MatrixClientContext;
@ -67,6 +68,9 @@ export default class ReplyThread extends React.Component {
};
this.unmounted = false;
if (this.props.isExporting) return;
this.context.on("Event.replaced", this.onEventReplaced);
this.room = this.context.getRoom(this.props.parentEv.getRoomId());
this.room.on("Room.redaction", this.onRoomRedaction);
@ -212,12 +216,13 @@ export default class ReplyThread extends React.Component {
};
}
static makeThread(parentEv, onHeightChanged, permalinkCreator, ref, layout) {
static makeThread(parentEv, onHeightChanged, permalinkCreator, ref, layout, isExporting) {
if (!ReplyThread.getParentEventId(parentEv)) {
return <div className="mx_ReplyThread_wrapper_empty" />;
}
return <ReplyThread
parentEv={parentEv}
isExporting={isExporting}
onHeightChanged={onHeightChanged}
ref={ref}
permalinkCreator={permalinkCreator}
@ -366,6 +371,11 @@ export default class ReplyThread extends React.Component {
})
}
</blockquote>;
} else if (this.props.isExporting) {
const eventId = ReplyThread.getParentEventId(this.props.parentEv);
header = <p style={{ marginTop: -5, marginBottom: 5 }}>
In reply to <a className="mx_reply_anchor" scroll-to={`${eventId}`}>this message</a>
</p>;
} else if (this.state.loading) {
const Spinner = sdk.getComponent("elements.Spinner");
header = <Spinner w={16} h={16} />;

View file

@ -37,10 +37,15 @@ function getdaysArray() {
export default class DateSeparator extends React.Component {
static propTypes = {
ts: PropTypes.number.isRequired,
isExporting: PropTypes.bool,
};
getLabel() {
const date = new Date(this.props.ts);
// During the time the archive is being viewed, a specific day might not make sense, so we return the full date
if (this.props.isExporting) return formatFullDateNoTime(date);
const today = new Date();
const yesterday = new Date();
const days = getdaysArray();

View file

@ -249,6 +249,8 @@ interface IProps {
// for now.
tileShape?: 'notif' | 'file_grid' | 'reply' | 'reply_preview';
isExporting?: boolean;
// show twelve hour timestamps
isTwelveHour?: boolean;
@ -405,6 +407,8 @@ export default class EventTile extends React.Component<IProps, IState> {
// TODO: [REACT-WARNING] Move into constructor
// eslint-disable-next-line camelcase
UNSAFE_componentWillMount() {
// Context isn't propagated through renderToStaticMarkup so we'll have to explicitly set it during export
if (this.props.isExporting) this.context = MatrixClientPeg.get();
this.verifyEvent(this.props.mxEvent);
}
@ -607,6 +611,7 @@ export default class EventTile extends React.Component<IProps, IState> {
}
shouldHighlight() {
if (this.props.isExporting) return false;
const actions = this.context.getPushActionsForEvent(this.props.mxEvent.replacingEvent() || this.props.mxEvent);
if (!actions || !actions.tweaks) { return false; }
@ -951,7 +956,8 @@ export default class EventTile extends React.Component<IProps, IState> {
}
const MessageActionBar = sdk.getComponent('messages.MessageActionBar');
const actionBar = !isEditing ? <MessageActionBar
const showMessageActionBar = !isEditing && !this.props.isExporting;
const actionBar = showMessageActionBar ? <MessageActionBar
mxEvent={this.props.mxEvent}
reactions={this.state.reactions}
permalinkCreator={this.props.permalinkCreator}
@ -1127,6 +1133,7 @@ export default class EventTile extends React.Component<IProps, IState> {
this.props.permalinkCreator,
this.replyThread,
this.props.layout,
this.props.isExporting,
);
// tab-index=-1 to allow it to be focusable but do not add tab stop for it, primarily for screen readers
@ -1169,11 +1176,11 @@ export default class EventTile extends React.Component<IProps, IState> {
// XXX this'll eventually be dynamic based on the fields once we have extensible event types
const messageTypes = ['m.room.message', 'm.sticker'];
function isMessageEvent(ev) {
function isMessageEvent(ev: MatrixEvent): boolean {
return (messageTypes.includes(ev.getType()));
}
export function haveTileForEvent(e) {
export function haveTileForEvent(e: MatrixEvent): boolean {
// Only messages have a tile (black-rectangle) if redacted
if (e.isRedacted() && !isMessageEvent(e)) return false;
@ -1244,11 +1251,11 @@ class E2ePadlock extends React.Component<IE2ePadlockProps, IE2ePadlockState> {
}
onHoverStart = () => {
this.setState({hover: true});
this.setState({ hover: true });
};
onHoverEnd = () => {
this.setState({hover: false});
this.setState({ hover: false });
};
render() {
@ -1286,11 +1293,11 @@ class SentReceipt extends React.PureComponent<ISentReceiptProps, ISentReceiptSta
}
onHoverStart = () => {
this.setState({hover: true});
this.setState({ hover: true });
};
onHoverEnd = () => {
this.setState({hover: false});
this.setState({ hover: false });
};
render() {