isExporting -> forExport and wrap EventTile with Context Provider

This commit is contained in:
Jaiwanth 2021-06-08 18:35:45 +05:30
parent 9e298e9f45
commit 6f8c1638aa
8 changed files with 55 additions and 53 deletions

View file

@ -46,7 +46,7 @@ export default class ReplyThread extends React.Component {
permalinkCreator: PropTypes.instanceOf(RoomPermalinkCreator).isRequired, permalinkCreator: PropTypes.instanceOf(RoomPermalinkCreator).isRequired,
// Specifies which layout to use. // Specifies which layout to use.
layout: LayoutPropType, layout: LayoutPropType,
isExporting: PropTypes.bool, forExport: PropTypes.bool,
}; };
static contextType = MatrixClientContext; static contextType = MatrixClientContext;
@ -69,7 +69,7 @@ export default class ReplyThread extends React.Component {
this.unmounted = false; this.unmounted = false;
if (this.props.isExporting) return; if (this.props.forExport) return;
this.context.on("Event.replaced", this.onEventReplaced); this.context.on("Event.replaced", this.onEventReplaced);
this.room = this.context.getRoom(this.props.parentEv.getRoomId()); this.room = this.context.getRoom(this.props.parentEv.getRoomId());
@ -216,13 +216,13 @@ export default class ReplyThread extends React.Component {
}; };
} }
static makeThread(parentEv, onHeightChanged, permalinkCreator, ref, layout, isExporting) { static makeThread(parentEv, onHeightChanged, permalinkCreator, ref, layout, forExport) {
if (!ReplyThread.getParentEventId(parentEv)) { if (!ReplyThread.getParentEventId(parentEv)) {
return null; return null;
} }
return <ReplyThread return <ReplyThread
parentEv={parentEv} parentEv={parentEv}
isExporting={isExporting} forExport={forExport}
onHeightChanged={onHeightChanged} onHeightChanged={onHeightChanged}
ref={ref} ref={ref}
permalinkCreator={permalinkCreator} permalinkCreator={permalinkCreator}
@ -367,7 +367,7 @@ export default class ReplyThread extends React.Component {
}) })
} }
</blockquote>; </blockquote>;
} else if (this.props.isExporting) { } else if (this.props.forExport) {
const eventId = ReplyThread.getParentEventId(this.props.parentEv); const eventId = ReplyThread.getParentEventId(this.props.parentEv);
header = <p style={{ marginTop: -5, marginBottom: 5 }}> header = <p style={{ marginTop: -5, marginBottom: 5 }}>
In reply to <a className="mx_reply_anchor" href={`#${eventId}`} scroll-to={eventId}>this message</a> In reply to <a className="mx_reply_anchor" href={`#${eventId}`} scroll-to={eventId}>this message</a>

View file

@ -37,14 +37,14 @@ function getdaysArray() {
export default class DateSeparator extends React.Component { export default class DateSeparator extends React.Component {
static propTypes = { static propTypes = {
ts: PropTypes.number.isRequired, ts: PropTypes.number.isRequired,
isExporting: PropTypes.bool, forExport: PropTypes.bool,
}; };
getLabel() { getLabel() {
const date = new Date(this.props.ts); 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 // 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); if (this.props.forExport) return formatFullDateNoTime(date);
const today = new Date(); const today = new Date();
const yesterday = new Date(); const yesterday = new Date();

View file

@ -104,7 +104,7 @@ export default class MFileBody extends React.Component {
showGenericPlaceholder: PropTypes.bool, showGenericPlaceholder: PropTypes.bool,
/* to set source to local file path during export */ /* to set source to local file path during export */
mediaSrc: PropTypes.string, mediaSrc: PropTypes.string,
isExporting: PropTypes.bool, forExport: PropTypes.bool,
}; };
static defaultProps = { static defaultProps = {
@ -176,7 +176,7 @@ export default class MFileBody extends React.Component {
placeholder = ( placeholder = (
<div className="mx_MFileBody_info"> <div className="mx_MFileBody_info">
<span className="mx_MFileBody_info_icon" > <span className="mx_MFileBody_info_icon" >
{this.props.isExporting ? {this.props.forExport ?
<img alt="Attachment" className="mx_export_attach_icon" src="icons/attach.svg" /> <img alt="Attachment" className="mx_export_attach_icon" src="icons/attach.svg" />
: null} : null}
</span> </span>

View file

@ -48,7 +48,7 @@ export default class MessageEvent extends React.Component {
mediaSrc: PropTypes.string, mediaSrc: PropTypes.string,
/* to set source to local file path during export */ /* to set source to local file path during export */
isExporting: PropTypes.bool, forExport: PropTypes.bool,
/* the maximum image height to use, if the event is an image */ /* the maximum image height to use, if the event is an image */
maxImageHeight: PropTypes.number, maxImageHeight: PropTypes.number,
@ -127,7 +127,7 @@ export default class MessageEvent extends React.Component {
showUrlPreview={this.props.showUrlPreview} showUrlPreview={this.props.showUrlPreview}
tileShape={this.props.tileShape} tileShape={this.props.tileShape}
mediaSrc={this.props.mediaSrc} mediaSrc={this.props.mediaSrc}
isExporting={this.props.isExporting} forExport={this.props.forExport}
maxImageHeight={this.props.maxImageHeight} maxImageHeight={this.props.maxImageHeight}
replacingEventId={this.props.replacingEventId} replacingEventId={this.props.replacingEventId}
editState={this.props.editState} editState={this.props.editState}

View file

@ -21,17 +21,14 @@ import { _t } from "../../../languageHandler";
import MatrixClientContext from "../../../contexts/MatrixClientContext"; import MatrixClientContext from "../../../contexts/MatrixClientContext";
import { formatFullDate } from "../../../DateUtils"; import { formatFullDate } from "../../../DateUtils";
import SettingsStore from "../../../settings/SettingsStore"; import SettingsStore from "../../../settings/SettingsStore";
import { MatrixClientPeg } from "../../../MatrixClientPeg";
interface IProps { interface IProps {
mxEvent: MatrixEvent; mxEvent: MatrixEvent;
isExporting: boolean; forExport: boolean;
} }
const RedactedBody = React.forwardRef<any, IProps>(({mxEvent, isExporting}, ref) => { const RedactedBody = React.forwardRef<any, IProps>(({mxEvent, forExport}, ref) => {
let cli: MatrixClient = useContext(MatrixClientContext); const cli: MatrixClient = useContext(MatrixClientContext);
// As context doesn't propagate during export, we'll have to explicitly declare
if (isExporting) cli = MatrixClientPeg.get();
let text = _t("Message deleted"); let text = _t("Message deleted");
const unsigned = mxEvent.getUnsigned(); const unsigned = mxEvent.getUnsigned();
const redactedBecauseUserId = unsigned && unsigned.redacted_because && unsigned.redacted_because.sender; const redactedBecauseUserId = unsigned && unsigned.redacted_because && unsigned.redacted_because.sender;
@ -47,7 +44,7 @@ const RedactedBody = React.forwardRef<any, IProps>(({mxEvent, isExporting}, ref)
return ( return (
<span className="mx_RedactedBody" ref={ref} title={titleText}> <span className="mx_RedactedBody" ref={ref} title={titleText}>
{ isExporting ? <img alt="Redacted" className="mx_export_trash_icon" src="icons/trash.svg" /> : null } { forExport ? <img alt="Redacted" className="mx_export_trash_icon" src="icons/trash.svg" /> : null }
{ text } { text }
</span> </span>
); );

View file

@ -249,7 +249,7 @@ interface IProps {
// for now. // for now.
tileShape?: 'notif' | 'file_grid' | 'reply' | 'reply_preview'; tileShape?: 'notif' | 'file_grid' | 'reply' | 'reply_preview';
isExporting?: boolean; forExport?: boolean;
// Used while exporting to refer to the local source rather than the online one // Used while exporting to refer to the local source rather than the online one
mediaSrc?: string; mediaSrc?: string;
@ -320,7 +320,7 @@ export default class EventTile extends React.Component<IProps, IState> {
static defaultProps = { static defaultProps = {
// no-op function because onHeightChanged is optional yet some sub-components assume its existence // no-op function because onHeightChanged is optional yet some sub-components assume its existence
onHeightChanged: function() {}, onHeightChanged: function() {},
isExporting: false, forExport: false,
}; };
static contextType = MatrixClientContext; static contextType = MatrixClientContext;
@ -427,8 +427,6 @@ export default class EventTile extends React.Component<IProps, IState> {
// TODO: [REACT-WARNING] Move into constructor // TODO: [REACT-WARNING] Move into constructor
// eslint-disable-next-line camelcase // eslint-disable-next-line camelcase
UNSAFE_componentWillMount() { 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); this.verifyEvent(this.props.mxEvent);
} }
@ -631,7 +629,7 @@ export default class EventTile extends React.Component<IProps, IState> {
} }
shouldHighlight() { shouldHighlight() {
if (this.props.isExporting) return false; if (this.props.forExport) return false;
const actions = this.context.getPushActionsForEvent(this.props.mxEvent.replacingEvent() || this.props.mxEvent); const actions = this.context.getPushActionsForEvent(this.props.mxEvent.replacingEvent() || this.props.mxEvent);
if (!actions || !actions.tweaks) { return false; } if (!actions || !actions.tweaks) { return false; }
@ -981,7 +979,7 @@ export default class EventTile extends React.Component<IProps, IState> {
} }
const MessageActionBar = sdk.getComponent('messages.MessageActionBar'); const MessageActionBar = sdk.getComponent('messages.MessageActionBar');
const showMessageActionBar = !isEditing && !this.props.isExporting; const showMessageActionBar = !isEditing && !this.props.forExport;
const actionBar = showMessageActionBar ? <MessageActionBar const actionBar = showMessageActionBar ? <MessageActionBar
mxEvent={this.props.mxEvent} mxEvent={this.props.mxEvent}
reactions={this.state.reactions} reactions={this.state.reactions}
@ -1155,7 +1153,7 @@ export default class EventTile extends React.Component<IProps, IState> {
this.props.permalinkCreator, this.props.permalinkCreator,
this.replyThread, this.replyThread,
this.props.layout, this.props.layout,
this.props.isExporting, this.props.forExport,
); );
// tab-index=-1 to allow it to be focusable but do not add tab stop for it, primarily for screen readers // tab-index=-1 to allow it to be focusable but do not add tab stop for it, primarily for screen readers
@ -1179,7 +1177,7 @@ export default class EventTile extends React.Component<IProps, IState> {
{ thread } { thread }
<EventTileType ref={this.tile} <EventTileType ref={this.tile}
mxEvent={this.props.mxEvent} mxEvent={this.props.mxEvent}
isExporting={this.props.isExporting} forExport={this.props.forExport}
replacingEventId={this.props.replacingEventId} replacingEventId={this.props.replacingEventId}
editState={this.props.editState} editState={this.props.editState}
mediaSrc={this.props.mediaSrc} mediaSrc={this.props.mediaSrc}

View file

@ -23,16 +23,20 @@ import exportCSS from "./exportCSS";
import exportJS from "./exportJS"; import exportJS from "./exportJS";
import exportIcons from "./exportIcons"; import exportIcons from "./exportIcons";
import { exportTypes } from "./exportUtils"; import { exportTypes } from "./exportUtils";
import MatrixClientContext from "../../contexts/MatrixClientContext";
import { MatrixClient } from "matrix-js-sdk";
export default class HTMLExporter extends Exporter { export default class HTMLExporter extends Exporter {
protected zip: JSZip; protected zip: JSZip;
protected avatars: Map<string, boolean>; protected avatars: Map<string, boolean>;
protected permalinkCreator: RoomPermalinkCreator; protected permalinkCreator: RoomPermalinkCreator;
protected matrixClient: MatrixClient;
constructor(room: Room, exportType: exportTypes, numberOfEvents?: number) { constructor(room: Room, exportType: exportTypes, numberOfEvents?: number) {
super(room, exportType, numberOfEvents); super(room, exportType, numberOfEvents);
this.zip = new JSZip(); this.zip = new JSZip();
this.avatars = new Map<string, boolean>(); this.avatars = new Map<string, boolean>();
this.matrixClient = MatrixClientPeg.get();
this.permalinkCreator = new RoomPermalinkCreator(this.room); this.permalinkCreator = new RoomPermalinkCreator(this.room);
window.addEventListener("beforeunload", this.onBeforeUnload) window.addEventListener("beforeunload", this.onBeforeUnload)
} }
@ -214,7 +218,7 @@ export default class HTMLExporter extends Exporter {
protected getDateSeparator(event: MatrixEvent) { protected getDateSeparator(event: MatrixEvent) {
const ts = event.getTs(); const ts = event.getTs();
const dateSeparator = <li key={ts}><DateSeparator isExporting={true} key={ts} ts={ts} /></li>; const dateSeparator = <li key={ts}><DateSeparator forExport={true} key={ts} ts={ts} /></li>;
return renderToStaticMarkup(dateSeparator); return renderToStaticMarkup(dateSeparator);
} }
@ -258,12 +262,13 @@ export default class HTMLExporter extends Exporter {
if (hasAvatar) await this.saveAvatarIfNeeded(mxEv); if (hasAvatar) await this.saveAvatarIfNeeded(mxEv);
return <li className="mx_Export_EventWrapper" id={mxEv.getId()}> return <li className="mx_Export_EventWrapper" id={mxEv.getId()}>
<MatrixClientContext.Provider value = {this.matrixClient}>
<EventTile <EventTile
mxEvent={mxEv} mxEvent={mxEv}
continuation={continuation} continuation={continuation}
isRedacted={mxEv.isRedacted()} isRedacted={mxEv.isRedacted()}
replacingEventId={mxEv.replacingEventId()} replacingEventId={mxEv.replacingEventId()}
isExporting={true} forExport={true}
readReceipts={null} readReceipts={null}
readReceiptMap={null} readReceiptMap={null}
showUrlPreview={false} showUrlPreview={false}
@ -282,6 +287,7 @@ export default class HTMLExporter extends Exporter {
enableFlair={false} enableFlair={false}
showReadReceipts={false} showReadReceipts={false}
/> />
</MatrixClientContext.Provider>
</li> </li>
} }

View file

@ -10,6 +10,7 @@ export enum exportFormats {
export enum exportTypes { export enum exportTypes {
TIMELINE = "TIMELINE", TIMELINE = "TIMELINE",
BEGINNING = "BEGINNING", BEGINNING = "BEGINNING",
START_DATE = "START_DATE",
LAST_N_MESSAGES = "LAST_N_MESSAGES", LAST_N_MESSAGES = "LAST_N_MESSAGES",
} }
@ -17,11 +18,11 @@ const exportConversationalHistory = async (
room: Room, room: Room,
format: string, format: string,
exportType: exportTypes, exportType: exportTypes,
numberOfEvents?: number, exportTypeMetadata?: number,
) => { ) => {
switch (format) { switch (format) {
case exportFormats.HTML: case exportFormats.HTML:
await new HTMLExporter(room, exportType, numberOfEvents).export(); await new HTMLExporter(room, exportType, exportTypeMetadata).export();
break; break;
case exportFormats.JSON: case exportFormats.JSON:
break; break;