mirror of
https://github.com/element-hq/element-web
synced 2024-11-24 02:05:45 +03:00
feat: edit button on View Source dialog
reuse component SendCustomEvent swap it in place in the View Source dialog the Back button takes you to the View Source dialog, not the DevTools dialog do not display the flip toggle box for changing between State Event and Normal Event
This commit is contained in:
parent
725162ee00
commit
af5cfff51d
3 changed files with 152 additions and 49 deletions
|
@ -16,12 +16,13 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import SyntaxHighlight from '../views/elements/SyntaxHighlight';
|
||||
import {_t} from "../../languageHandler";
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import SyntaxHighlight from "../views/elements/SyntaxHighlight";
|
||||
import { _t } from "../../languageHandler";
|
||||
import * as sdk from "../../index";
|
||||
|
||||
import MatrixClientContext from "../../contexts/MatrixClientContext";
|
||||
import { SendCustomEvent } from "../views/dialogs/DevtoolsDialog";
|
||||
|
||||
export default class ViewSource extends React.Component {
|
||||
static propTypes = {
|
||||
|
@ -31,48 +32,157 @@ export default class ViewSource extends React.Component {
|
|||
eventId: PropTypes.string.isRequired,
|
||||
isEncrypted: PropTypes.bool.isRequired,
|
||||
decryptedContent: PropTypes.object,
|
||||
event: PropTypes.object.isRequired, // the MatrixEvent associated with the context menu
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
editComponent: null,
|
||||
};
|
||||
}
|
||||
|
||||
onBack() {
|
||||
this.setState({ editComponent: null });
|
||||
}
|
||||
|
||||
editEvent() {
|
||||
const isStateEvent = this.props.event.isState();
|
||||
console.log("isStateEvent", isStateEvent);
|
||||
if (isStateEvent) {
|
||||
this.setState({
|
||||
editComponent: (
|
||||
<MatrixClientContext.Consumer>
|
||||
{(cli) => (
|
||||
<SendCustomEvent
|
||||
room={cli.getRoom(this.props.roomId)}
|
||||
forceStateEvent={true}
|
||||
onBack={() => this.onBack()}
|
||||
inputs={{
|
||||
eventType: this.props.event.getType(),
|
||||
evContent: JSON.stringify(
|
||||
this.props.event.getContent(),
|
||||
null,
|
||||
"\t"
|
||||
),
|
||||
stateKey: this.props.event.getStateKey(),
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</MatrixClientContext.Consumer>
|
||||
),
|
||||
});
|
||||
} else {
|
||||
// send an edit-message event
|
||||
// prefill the "m.new_content" field
|
||||
const originalContent = this.props.event.getContent();
|
||||
const originalEventId = this.props.eventId;
|
||||
const content = {
|
||||
...originalContent,
|
||||
"m.new_content": originalContent,
|
||||
"m.relates_to": {
|
||||
rel_type: "m.replace",
|
||||
event_id: originalEventId,
|
||||
},
|
||||
};
|
||||
this.setState({
|
||||
editComponent: (
|
||||
<MatrixClientContext.Consumer>
|
||||
{(cli) => (
|
||||
<SendCustomEvent
|
||||
room={cli.getRoom(this.props.roomId)}
|
||||
forceStateEvent={false}
|
||||
forceGeneralEvent={true}
|
||||
onBack={() => this.onBack()}
|
||||
inputs={{
|
||||
eventType: this.props.event.getType(),
|
||||
evContent: JSON.stringify(
|
||||
content,
|
||||
null,
|
||||
"\t"
|
||||
),
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</MatrixClientContext.Consumer>
|
||||
),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
|
||||
const BaseDialog = sdk.getComponent("views.dialogs.BaseDialog");
|
||||
|
||||
let content;
|
||||
if (this.props.isEncrypted) {
|
||||
content = <>
|
||||
<details open className="mx_ViewSource_details">
|
||||
<summary>
|
||||
<span className="mx_ViewSource_heading">{_t("Decrypted event source")}</span>
|
||||
</summary>
|
||||
<SyntaxHighlight className="json">
|
||||
{ JSON.stringify(this.props.decryptedContent, null, 2) }
|
||||
</SyntaxHighlight>
|
||||
</details>
|
||||
<details className="mx_ViewSource_details">
|
||||
<summary>
|
||||
<span className="mx_ViewSource_heading">{_t("Original event source")}</span>
|
||||
</summary>
|
||||
<SyntaxHighlight className="json">
|
||||
{ JSON.stringify(this.props.content, null, 2) }
|
||||
</SyntaxHighlight>
|
||||
</details>
|
||||
</>;
|
||||
content = (
|
||||
<>
|
||||
<details open className="mx_ViewSource_details">
|
||||
<summary>
|
||||
<span className="mx_ViewSource_heading">
|
||||
{_t("Decrypted event source")}
|
||||
</span>
|
||||
</summary>
|
||||
<SyntaxHighlight className="json">
|
||||
{JSON.stringify(
|
||||
this.props.decryptedContent,
|
||||
null,
|
||||
2
|
||||
)}
|
||||
</SyntaxHighlight>
|
||||
</details>
|
||||
<details className="mx_ViewSource_details">
|
||||
<summary>
|
||||
<span className="mx_ViewSource_heading">
|
||||
{_t("Original event source")}
|
||||
</span>
|
||||
</summary>
|
||||
<SyntaxHighlight className="json">
|
||||
{JSON.stringify(this.props.content, null, 2)}
|
||||
</SyntaxHighlight>
|
||||
</details>
|
||||
</>
|
||||
);
|
||||
} else {
|
||||
content = <>
|
||||
<div className="mx_ViewSource_heading">{_t("Original event source")}</div>
|
||||
<SyntaxHighlight className="json">
|
||||
{ JSON.stringify(this.props.content, null, 2) }
|
||||
</SyntaxHighlight>
|
||||
</>;
|
||||
content = (
|
||||
<>
|
||||
<div className="mx_ViewSource_heading">
|
||||
{_t("Original event source")}
|
||||
</div>
|
||||
<SyntaxHighlight className="json">
|
||||
{JSON.stringify(this.props.content, null, 2)}
|
||||
</SyntaxHighlight>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
const isEditing = this.state.editComponent !== null;
|
||||
console.log(isEditing);
|
||||
|
||||
return (
|
||||
<BaseDialog className="mx_ViewSource" onFinished={this.props.onFinished} title={_t('View Source')}>
|
||||
<div className="mx_Dialog_content">
|
||||
<div className="mx_ViewSource_label_left">Room ID: { this.props.roomId }</div>
|
||||
<div className="mx_ViewSource_label_left">Event ID: { this.props.eventId }</div>
|
||||
<BaseDialog
|
||||
className="mx_ViewSource"
|
||||
onFinished={this.props.onFinished}
|
||||
title={_t("View Source")}
|
||||
>
|
||||
<div>
|
||||
<div className="mx_ViewSource_label_left">
|
||||
Room ID: {this.props.roomId}
|
||||
</div>
|
||||
<div className="mx_ViewSource_label_left">
|
||||
Event ID: {this.props.eventId}
|
||||
</div>
|
||||
<div className="mx_ViewSource_separator" />
|
||||
{ content }
|
||||
{isEditing ? this.state.editComponent : content}
|
||||
</div>
|
||||
{!isEditing && (
|
||||
<div className="mx_Dialog_buttons">
|
||||
<button onClick={() => this.editEvent()}>
|
||||
{_t("Edit")}
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</BaseDialog>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -130,20 +130,10 @@ export default class MessageContextMenu extends React.Component {
|
|||
roomId: ev.getRoomId(),
|
||||
eventId: ev.getId(),
|
||||
content: ev.event,
|
||||
event: ev,
|
||||
isEncrypted: this.props.mxEvent.getType() !== this.props.mxEvent.getWireType(),
|
||||
decryptedContent: ev._clearEvent,
|
||||
}, 'mx_Dialog_viewsource');
|
||||
this.closeMenu();
|
||||
};
|
||||
|
||||
onViewClearSourceClick = () => {
|
||||
const ev = this.props.mxEvent.replacingEvent() || this.props.mxEvent;
|
||||
const ViewSource = sdk.getComponent('structures.ViewSource');
|
||||
Modal.createTrackedDialog('View Clear Event Source', '', ViewSource, {
|
||||
roomId: ev.getRoomId(),
|
||||
eventId: ev.getId(),
|
||||
// FIXME: _clearEvent is private
|
||||
content: ev._clearEvent,
|
||||
decryptedContent: ev._clearEvent,
|
||||
}, 'mx_Dialog_viewsource');
|
||||
this.closeMenu();
|
||||
};
|
||||
|
|
|
@ -73,13 +73,14 @@ class GenericEditor extends React.PureComponent {
|
|||
}
|
||||
}
|
||||
|
||||
class SendCustomEvent extends GenericEditor {
|
||||
export class SendCustomEvent extends GenericEditor {
|
||||
static getLabel() { return _t('Send Custom Event'); }
|
||||
|
||||
static propTypes = {
|
||||
onBack: PropTypes.func.isRequired,
|
||||
room: PropTypes.instanceOf(Room).isRequired,
|
||||
forceStateEvent: PropTypes.bool,
|
||||
forceGeneralEvent: PropTypes.bool,
|
||||
inputs: PropTypes.object,
|
||||
};
|
||||
|
||||
|
@ -140,6 +141,8 @@ class SendCustomEvent extends GenericEditor {
|
|||
</div>;
|
||||
}
|
||||
|
||||
const showTglFlip = !this.state.message && !this.props.forceStateEvent && !this.props.forceGeneralEvent;
|
||||
|
||||
return <div>
|
||||
<div className="mx_DevTools_content">
|
||||
<div className="mx_DevTools_eventTypeStateKeyGroup">
|
||||
|
@ -155,7 +158,7 @@ class SendCustomEvent extends GenericEditor {
|
|||
<div className="mx_Dialog_buttons">
|
||||
<button onClick={this.onBack}>{ _t('Back') }</button>
|
||||
{ !this.state.message && <button onClick={this._send}>{ _t('Send') }</button> }
|
||||
{ !this.state.message && !this.props.forceStateEvent && <div style={{float: "right"}}>
|
||||
{ showTglFlip && <div style={{float: "right"}}>
|
||||
<input id="isStateEvent" className="mx_DevTools_tgl mx_DevTools_tgl-flip" type="checkbox" onChange={this._onChange} checked={this.state.isStateEvent} />
|
||||
<label className="mx_DevTools_tgl-btn" data-tg-off="Event" data-tg-on="State Event" htmlFor="isStateEvent" />
|
||||
</div> }
|
||||
|
|
Loading…
Reference in a new issue