isExporting -> forExport and wrap EventTile with Context Provider
This commit is contained in:
parent
9e298e9f45
commit
6f8c1638aa
8 changed files with 55 additions and 53 deletions
|
@ -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>
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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}
|
||||||
|
|
|
@ -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>
|
||||||
);
|
);
|
||||||
|
|
|
@ -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}
|
||||||
|
|
|
@ -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>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue