mirror of
https://github.com/element-hq/element-web
synced 2024-11-26 19:26:04 +03:00
Merge pull request #5074 from vector-im/t3chguy/devtools-1
T3chguy/devtools 1
This commit is contained in:
commit
fbe1c82dfa
3 changed files with 97 additions and 21 deletions
|
@ -23,17 +23,28 @@ class SendCustomEvent extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
roomId: React.PropTypes.string.isRequired,
|
roomId: React.PropTypes.string.isRequired,
|
||||||
onBack: React.PropTypes.func.isRequired,
|
onBack: React.PropTypes.func.isRequired,
|
||||||
|
|
||||||
|
eventType: React.PropTypes.string.isRequired,
|
||||||
|
evContent: React.PropTypes.string.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
static defaultProps = {
|
||||||
|
eventType: '',
|
||||||
|
evContent: '{\n\n}',
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(props, context) {
|
constructor(props, context) {
|
||||||
super(props, context);
|
super(props, context);
|
||||||
this._send = this._send.bind(this);
|
this._send = this._send.bind(this);
|
||||||
this.onBack = this.onBack.bind(this);
|
this.onBack = this.onBack.bind(this);
|
||||||
}
|
this._onChange = this._onChange.bind(this);
|
||||||
|
|
||||||
state = {
|
this.state = {
|
||||||
message: null,
|
message: null,
|
||||||
};
|
input_eventType: this.props.eventType,
|
||||||
|
input_evContent: this.props.evContent,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
onBack() {
|
onBack() {
|
||||||
if (this.state.message) {
|
if (this.state.message) {
|
||||||
|
@ -51,13 +62,18 @@ class SendCustomEvent extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
send(content) {
|
send(content) {
|
||||||
return MatrixClientPeg.get().sendEvent(this.props.roomId, this.refs.eventType.value, content);
|
return MatrixClientPeg.get().sendEvent(this.props.roomId, this.state.input_eventType, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
async _send() {
|
async _send() {
|
||||||
|
if (this.state.input_eventType === '') {
|
||||||
|
this.setState({ message: _t('You must specify an event type!') });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let message;
|
let message;
|
||||||
try {
|
try {
|
||||||
const content = JSON.parse(this.refs.evContent.value);
|
const content = JSON.parse(this.state.input_evContent);
|
||||||
await this.send(content);
|
await this.send(content);
|
||||||
message = _t('Event sent!');
|
message = _t('Event sent!');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -67,7 +83,11 @@ class SendCustomEvent extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
_additionalFields() {
|
_additionalFields() {
|
||||||
return <div></div>;
|
return <div/>;
|
||||||
|
}
|
||||||
|
|
||||||
|
_onChange(e) {
|
||||||
|
this.setState({[`input_${e.target.id}`]: e.target.value});
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -87,14 +107,14 @@ class SendCustomEvent extends React.Component {
|
||||||
<label htmlFor="eventType"> { _t('Event Type') } </label>
|
<label htmlFor="eventType"> { _t('Event Type') } </label>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<input id="eventType" ref="eventType" className="mx_TextInputDialog_input" size="64" />
|
<input id="eventType" onChange={this._onChange} value={this.state.input_eventType} className="mx_TextInputDialog_input" size="64" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mx_TextInputDialog_label">
|
<div className="mx_TextInputDialog_label">
|
||||||
<label htmlFor="evContent"> { _t('Event Content') } </label>
|
<label htmlFor="evContent"> { _t('Event Content') } </label>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<textarea id="evContent" ref="evContent" className="mx_TextInputDialog_input" defaultValue={"{\n\n}"} cols="63" rows="5" />
|
<textarea id="evContent" onChange={this._onChange} value={this.state.input_evContent} className="mx_TextInputDialog_input" cols="63" rows="5" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{this._buttons()}
|
{this._buttons()}
|
||||||
|
@ -103,9 +123,29 @@ class SendCustomEvent extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
class SendCustomStateEvent extends SendCustomEvent {
|
class SendCustomStateEvent extends SendCustomEvent {
|
||||||
|
static propTypes = {
|
||||||
|
roomId: React.PropTypes.string.isRequired,
|
||||||
|
onBack: React.PropTypes.func.isRequired,
|
||||||
|
|
||||||
|
eventType: React.PropTypes.string.isRequired,
|
||||||
|
evContent: React.PropTypes.string.isRequired,
|
||||||
|
stateKey: React.PropTypes.string.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
static defaultProps = {
|
||||||
|
eventType: '',
|
||||||
|
evContent: '{\n\n}',
|
||||||
|
stateKey: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor(props, context) {
|
||||||
|
super(props, context);
|
||||||
|
this.state['input_stateKey'] = this.props.stateKey;
|
||||||
|
}
|
||||||
|
|
||||||
send(content) {
|
send(content) {
|
||||||
return MatrixClientPeg.get().sendStateEvent(this.props.roomId, this.refs.eventType.value, content,
|
const cli = MatrixClientPeg.get();
|
||||||
this.refs.stateKey.value);
|
return cli.sendStateEvent(this.props.roomId, this.state.input_eventType, content, this.state.input_stateKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
_additionalFields() {
|
_additionalFields() {
|
||||||
|
@ -114,7 +154,7 @@ class SendCustomStateEvent extends SendCustomEvent {
|
||||||
<label htmlFor="stateKey"> { _t('State Key') } </label>
|
<label htmlFor="stateKey"> { _t('State Key') } </label>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<input id="stateKey" ref="stateKey" className="mx_TextInputDialog_input" size="64" />
|
<input id="stateKey" onChange={this._onChange} value={this.state.input_stateKey} className="mx_TextInputDialog_input" size="64" />
|
||||||
</div>
|
</div>
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
|
@ -122,6 +162,7 @@ class SendCustomStateEvent extends SendCustomEvent {
|
||||||
|
|
||||||
class RoomStateExplorer extends React.Component {
|
class RoomStateExplorer extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
setMode: React.PropTypes.func.isRequired,
|
||||||
roomId: React.PropTypes.string.isRequired,
|
roomId: React.PropTypes.string.isRequired,
|
||||||
onBack: React.PropTypes.func.isRequired,
|
onBack: React.PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
@ -133,9 +174,12 @@ class RoomStateExplorer extends React.Component {
|
||||||
this.roomStateEvents = room.currentState.events;
|
this.roomStateEvents = room.currentState.events;
|
||||||
|
|
||||||
this.onBack = this.onBack.bind(this);
|
this.onBack = this.onBack.bind(this);
|
||||||
|
this.editEv = this.editEv.bind(this);
|
||||||
|
this.onQuery = this.onQuery.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
|
query: '',
|
||||||
eventType: null,
|
eventType: null,
|
||||||
event: null,
|
event: null,
|
||||||
};
|
};
|
||||||
|
@ -148,7 +192,7 @@ class RoomStateExplorer extends React.Component {
|
||||||
|
|
||||||
onViewSourceClick(event) {
|
onViewSourceClick(event) {
|
||||||
return () => {
|
return () => {
|
||||||
this.setState({ event: event.event });
|
this.setState({ event });
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,14 +206,28 @@ class RoomStateExplorer extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
editEv() {
|
||||||
|
const ev = this.state.event;
|
||||||
|
this.props.setMode(SendCustomStateEvent, {
|
||||||
|
eventType: ev.getType(),
|
||||||
|
evContent: JSON.stringify(ev.getContent(), null, '\t'),
|
||||||
|
stateKey: ev.getStateKey(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onQuery(ev) {
|
||||||
|
this.setState({ query: ev.target.value });
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
if (this.state.event) {
|
if (this.state.event) {
|
||||||
return <div className="mx_ViewSource">
|
return <div className="mx_ViewSource">
|
||||||
<div className="mx_Dialog_content">
|
<div className="mx_Dialog_content">
|
||||||
<pre>{JSON.stringify(this.state.event, null, 2)}</pre>
|
<pre>{JSON.stringify(this.state.event.event, null, 2)}</pre>
|
||||||
</div>
|
</div>
|
||||||
<div className="mx_Dialog_buttons">
|
<div className="mx_Dialog_buttons">
|
||||||
<button onClick={this.onBack}>{ _t('Back') }</button>
|
<button onClick={this.onBack}>{ _t('Back') }</button>
|
||||||
|
<button onClick={this.editEv}>{ _t('Edit') }</button>
|
||||||
</div>
|
</div>
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
|
@ -178,6 +236,9 @@ class RoomStateExplorer extends React.Component {
|
||||||
|
|
||||||
if (this.state.eventType === null) {
|
if (this.state.eventType === null) {
|
||||||
Object.keys(this.roomStateEvents).forEach((evType) => {
|
Object.keys(this.roomStateEvents).forEach((evType) => {
|
||||||
|
// Skip this entry if does not contain search query
|
||||||
|
if (this.state.query && !evType.includes(this.state.query)) return;
|
||||||
|
|
||||||
const stateGroup = this.roomStateEvents[evType];
|
const stateGroup = this.roomStateEvents[evType];
|
||||||
const stateKeys = Object.keys(stateGroup);
|
const stateKeys = Object.keys(stateGroup);
|
||||||
|
|
||||||
|
@ -196,6 +257,9 @@ class RoomStateExplorer extends React.Component {
|
||||||
const evType = this.state.eventType;
|
const evType = this.state.eventType;
|
||||||
const stateGroup = this.roomStateEvents[evType];
|
const stateGroup = this.roomStateEvents[evType];
|
||||||
Object.keys(stateGroup).forEach((stateKey) => {
|
Object.keys(stateGroup).forEach((stateKey) => {
|
||||||
|
// Skip this entry if does not contain search query
|
||||||
|
if (this.state.query && !stateKey.includes(this.state.query)) return;
|
||||||
|
|
||||||
const ev = stateGroup[stateKey];
|
const ev = stateGroup[stateKey];
|
||||||
rows.push(<button className="mx_DevTools_RoomStateExplorer_button" key={stateKey}
|
rows.push(<button className="mx_DevTools_RoomStateExplorer_button" key={stateKey}
|
||||||
onClick={this.onViewSourceClick(ev)}>
|
onClick={this.onViewSourceClick(ev)}>
|
||||||
|
@ -206,6 +270,7 @@ class RoomStateExplorer extends React.Component {
|
||||||
|
|
||||||
return <div>
|
return <div>
|
||||||
<div className="mx_Dialog_content">
|
<div className="mx_Dialog_content">
|
||||||
|
<input onChange={this.onQuery} placeholder={_t('Filter results')} size="64" className="mx_TextInputDialog_input mx_DevTools_RoomStateExplorer_query" value={this.state.query} />
|
||||||
{rows}
|
{rows}
|
||||||
</div>
|
</div>
|
||||||
<div className="mx_Dialog_buttons">
|
<div className="mx_Dialog_buttons">
|
||||||
|
@ -223,11 +288,13 @@ export default class DevtoolsDialog extends React.Component {
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
mode: null,
|
mode: null,
|
||||||
|
modeArgs: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(props, context) {
|
constructor(props, context) {
|
||||||
super(props, context);
|
super(props, context);
|
||||||
this.onBack = this.onBack.bind(this);
|
this.onBack = this.onBack.bind(this);
|
||||||
|
this.setMode = this.setMode.bind(this);
|
||||||
this.onCancel = this.onCancel.bind(this);
|
this.onCancel = this.onCancel.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,10 +304,14 @@ export default class DevtoolsDialog extends React.Component {
|
||||||
|
|
||||||
_setMode(mode) {
|
_setMode(mode) {
|
||||||
return () => {
|
return () => {
|
||||||
this.setState({ mode });
|
this.setMode(mode);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setMode(mode, modeArgs={}) {
|
||||||
|
this.setState({ mode, modeArgs });
|
||||||
|
}
|
||||||
|
|
||||||
onBack() {
|
onBack() {
|
||||||
this.setState({ mode: null });
|
this.setState({ mode: null });
|
||||||
}
|
}
|
||||||
|
@ -253,7 +324,8 @@ export default class DevtoolsDialog extends React.Component {
|
||||||
let body;
|
let body;
|
||||||
|
|
||||||
if (this.state.mode) {
|
if (this.state.mode) {
|
||||||
body = <this.state.mode {...this.props} onBack={this.onBack} />;
|
body =
|
||||||
|
<this.state.mode {...this.props} {...this.state.modeArgs} onBack={this.onBack} setMode={this.setMode} />;
|
||||||
} else {
|
} else {
|
||||||
body = <div>
|
body = <div>
|
||||||
<div className="mx_Dialog_content">
|
<div className="mx_Dialog_content">
|
||||||
|
@ -268,9 +340,11 @@ export default class DevtoolsDialog extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
|
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
|
||||||
return <BaseDialog className="mx_QuestionDialog" onFinished={this.props.onFinished} title={_t('Developer Tools')}>
|
return (
|
||||||
<div>Room ID: {this.props.roomId}</div>
|
<BaseDialog className="mx_QuestionDialog" onFinished={this.props.onFinished} title={_t('Developer Tools')}>
|
||||||
{ body }
|
<div>Room ID: { this.props.roomId }</div>
|
||||||
</BaseDialog>;
|
{ body }
|
||||||
|
</BaseDialog>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,6 +59,7 @@
|
||||||
"Favourite": "Favourite",
|
"Favourite": "Favourite",
|
||||||
"Fetching third party location failed": "Fetching third party location failed",
|
"Fetching third party location failed": "Fetching third party location failed",
|
||||||
"Files": "Files",
|
"Files": "Files",
|
||||||
|
"Filter results": "Filter results",
|
||||||
"Filter room names": "Filter room names",
|
"Filter room names": "Filter room names",
|
||||||
"Forget": "Forget",
|
"Forget": "Forget",
|
||||||
"Forward Message": "Forward Message",
|
"Forward Message": "Forward Message",
|
||||||
|
@ -156,6 +157,7 @@
|
||||||
"You are not receiving desktop notifications": "You are not receiving desktop notifications",
|
"You are not receiving desktop notifications": "You are not receiving desktop notifications",
|
||||||
"You are Rioting as a guest. <a>Register</a> or <a>sign in</a> to access more rooms and features!": "You are Rioting as a guest. <a>Register</a> or <a>sign in</a> to access more rooms and features!",
|
"You are Rioting as a guest. <a>Register</a> or <a>sign in</a> to access more rooms and features!": "You are Rioting as a guest. <a>Register</a> or <a>sign in</a> to access more rooms and features!",
|
||||||
"You might have configured them in a client other than Riot. You cannot tune them in Riot but they still apply": "You might have configured them in a client other than Riot. You cannot tune them in Riot but they still apply",
|
"You might have configured them in a client other than Riot. You cannot tune them in Riot but they still apply": "You might have configured them in a client other than Riot. You cannot tune them in Riot but they still apply",
|
||||||
|
"You must specify an event type!": "You must specify an event type!",
|
||||||
"Thank you!": "Thank you!",
|
"Thank you!": "Thank you!",
|
||||||
"Sunday": "Sunday",
|
"Sunday": "Sunday",
|
||||||
"Monday": "Monday",
|
"Monday": "Monday",
|
||||||
|
|
|
@ -14,6 +14,6 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.mx_DevTools_RoomStateExplorer_button {
|
.mx_DevTools_RoomStateExplorer_button, .mx_DevTools_RoomStateExplorer_query {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue