Merge pull request #2124 from matrix-org/dbkr/tombstone
Support m.room.tombstone events
This commit is contained in:
commit
2c1ba6f104
4 changed files with 88 additions and 2 deletions
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
Copyright 2015, 2016 OpenMarket Ltd
|
||||
Copyright 2018 New Vector Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
@ -22,6 +23,29 @@ limitations under the License.
|
|||
position: relative;
|
||||
}
|
||||
|
||||
.mx_MessageComposer_replaced_wrapper {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.mx_MessageComposer_replaced_valign {
|
||||
height: 60px;
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.mx_MessageComposer_roomReplaced_icon {
|
||||
float: left;
|
||||
margin-right: 20px;
|
||||
margin-top: 5px;
|
||||
width: 31px;
|
||||
height: 31px;
|
||||
}
|
||||
|
||||
.mx_MessageComposer_roomReplaced_header {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.mx_MessageComposer_autocomplete_wrapper {
|
||||
position: relative;
|
||||
height: 0;
|
||||
|
|
13
res/img/room_replaced.svg
Normal file
13
res/img/room_replaced.svg
Normal file
|
@ -0,0 +1,13 @@
|
|||
<svg width="31" height="31" viewBox="0 0 31 31" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="31" height="31" fill="black" fill-opacity="0"/>
|
||||
<circle cx="15.5" cy="15.5" r="15.5" fill="#A2A2A2"/>
|
||||
<path d="M22.8553 15.5C22.8553 19.5622 19.5622 22.8553 15.5 22.8553C11.4378 22.8553 8.14474 19.5622 8.14474 15.5C8.14474 11.4378 11.4378 8.14474 15.5 8.14474C19.5622 8.14474 22.8553 11.4378 22.8553 15.5ZM15.5 24.25C20.3325 24.25 24.25 20.3325 24.25 15.5C24.25 10.6675 20.3325 6.75 15.5 6.75C10.6675 6.75 6.75 10.6675 6.75 15.5C6.75 20.3325 10.6675 24.25 15.5 24.25Z" fill="white" stroke="white" stroke-width="0.5"/>
|
||||
<rect x="16.2666" y="30.5032" width="1.5" height="29.4046" transform="rotate(179.987 16.2666 30.5032)" fill="#A2A2A2"/>
|
||||
<rect x="8.89404" y="28.8434" width="1.5" height="29.6593" transform="rotate(-149.607 8.89404 28.8434)" fill="#A2A2A2"/>
|
||||
<rect x="2.87988" y="24.495" width="1.5" height="30.0747" transform="rotate(-121.597 2.87988 24.495)" fill="#A2A2A2"/>
|
||||
<rect x="2.16284" y="23.3413" width="1.5" height="29.6434" transform="rotate(-116.581 2.16284 23.3413)" fill="#A2A2A2"/>
|
||||
<rect x="1.55176" y="22.1343" width="1.5" height="29.5016" transform="rotate(-111.584 1.55176 22.1343)" fill="#A2A2A2"/>
|
||||
<path d="M9.5 17L7.5 20L5.5 17L9.5 17Z" fill="white" stroke="white"/>
|
||||
<path d="M21.5 15L23.5 12L25.5 15H21.5Z" fill="white" stroke="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Copyright 2015, 2016 OpenMarket Ltd
|
||||
Copyright 2017 New Vector Ltd
|
||||
Copyright 2017, 2018 New Vector Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
@ -25,6 +25,7 @@ import dis from '../../../dispatcher';
|
|||
import RoomViewStore from '../../../stores/RoomViewStore';
|
||||
import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
|
||||
import Stickerpicker from './Stickerpicker';
|
||||
import { makeRoomPermalink } from '../../../matrix-to';
|
||||
|
||||
const formatButtonList = [
|
||||
_td("bold"),
|
||||
|
@ -51,7 +52,9 @@ export default class MessageComposer extends React.Component {
|
|||
this.onToggleMarkdownClicked = this.onToggleMarkdownClicked.bind(this);
|
||||
this.onInputStateChanged = this.onInputStateChanged.bind(this);
|
||||
this.onEvent = this.onEvent.bind(this);
|
||||
this._onRoomStateEvents = this._onRoomStateEvents.bind(this);
|
||||
this._onRoomViewStoreUpdate = this._onRoomViewStoreUpdate.bind(this);
|
||||
this._onTombstoneClick = this._onTombstoneClick.bind(this);
|
||||
|
||||
this.state = {
|
||||
inputState: {
|
||||
|
@ -61,6 +64,7 @@ export default class MessageComposer extends React.Component {
|
|||
},
|
||||
showFormatting: SettingsStore.getValue('MessageComposer.showFormatting'),
|
||||
isQuoting: Boolean(RoomViewStore.getQuotingEvent()),
|
||||
tombstone: this._getRoomTombstone(),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -70,6 +74,7 @@ export default class MessageComposer extends React.Component {
|
|||
// marked as encrypted.
|
||||
// XXX: fragile as all hell - fixme somehow, perhaps with a dedicated Room.encryption event or something.
|
||||
MatrixClientPeg.get().on("event", this.onEvent);
|
||||
MatrixClientPeg.get().on("RoomState.events", this._onRoomStateEvents);
|
||||
this._roomStoreToken = RoomViewStore.addListener(this._onRoomViewStoreUpdate);
|
||||
this._waitForOwnMember();
|
||||
}
|
||||
|
@ -93,6 +98,7 @@ export default class MessageComposer extends React.Component {
|
|||
componentWillUnmount() {
|
||||
if (MatrixClientPeg.get()) {
|
||||
MatrixClientPeg.get().removeListener("event", this.onEvent);
|
||||
MatrixClientPeg.get().removeListener("RoomState.events", this._onRoomStateEvents);
|
||||
}
|
||||
if (this._roomStoreToken) {
|
||||
this._roomStoreToken.remove();
|
||||
|
@ -105,6 +111,18 @@ export default class MessageComposer extends React.Component {
|
|||
this.forceUpdate();
|
||||
}
|
||||
|
||||
_onRoomStateEvents(ev, state) {
|
||||
if (ev.getRoomId() !== this.props.room.roomId) return;
|
||||
|
||||
if (ev.getType() === 'm.room.tombstone') {
|
||||
this.setState({tombstone: this._getRoomTombstone()});
|
||||
}
|
||||
}
|
||||
|
||||
_getRoomTombstone() {
|
||||
return this.props.room.currentState.getStateEvents('m.room.tombstone', '');
|
||||
}
|
||||
|
||||
_onRoomViewStoreUpdate() {
|
||||
const isQuoting = Boolean(RoomViewStore.getQuotingEvent());
|
||||
if (this.state.isQuoting === isQuoting) return;
|
||||
|
@ -224,6 +242,17 @@ export default class MessageComposer extends React.Component {
|
|||
this.messageComposerInput.enableRichtext(!this.state.inputState.isRichTextEnabled);
|
||||
}
|
||||
|
||||
_onTombstoneClick(ev) {
|
||||
ev.preventDefault();
|
||||
|
||||
const replacementRoomId = this.state.tombstone.getContent()['replacement_room'];
|
||||
dis.dispatch({
|
||||
action: 'view_room',
|
||||
highlighted: true,
|
||||
room_id: replacementRoomId,
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const uploadInputStyle = {display: 'none'};
|
||||
const MemberAvatar = sdk.getComponent('avatars.MemberAvatar');
|
||||
|
@ -280,7 +309,7 @@ export default class MessageComposer extends React.Component {
|
|||
</div>;
|
||||
}
|
||||
|
||||
const canSendMessages = this.props.room.currentState.maySendMessage(
|
||||
const canSendMessages = !this.state.tombstone && this.props.room.currentState.maySendMessage(
|
||||
MatrixClientPeg.get().credentials.userId);
|
||||
|
||||
if (canSendMessages) {
|
||||
|
@ -340,6 +369,24 @@ export default class MessageComposer extends React.Component {
|
|||
callButton,
|
||||
videoCallButton,
|
||||
);
|
||||
} else if (this.state.tombstone) {
|
||||
const replacementRoomId = this.state.tombstone.getContent()['replacement_room'];
|
||||
|
||||
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
|
||||
controls.push(<div className="mx_MessageComposer_replaced_wrapper">
|
||||
<div className="mx_MessageComposer_replaced_valign">
|
||||
<img className="mx_MessageComposer_roomReplaced_icon" src="img/room_replaced.svg" />
|
||||
<span className="mx_MessageComposer_roomReplaced_header">
|
||||
{_t("This room has been replaced and is no longer active.")}
|
||||
</span><br />
|
||||
<a href={makeRoomPermalink(replacementRoomId)}
|
||||
className="mx_MessageComposer_roomReplaced_link"
|
||||
onClick={this._onTombstoneClick}
|
||||
>
|
||||
{_t("The conversation continues here.")}
|
||||
</a>
|
||||
</div>
|
||||
</div>);
|
||||
} else {
|
||||
controls.push(
|
||||
<div key="controls_error" className="mx_MessageComposer_noperm_error">
|
||||
|
|
|
@ -396,6 +396,8 @@
|
|||
"At this time it is not possible to reply with a file so this will be sent without being a reply.": "At this time it is not possible to reply with a file so this will be sent without being a reply.",
|
||||
"Upload Files": "Upload Files",
|
||||
"Are you sure you want to upload the following files?": "Are you sure you want to upload the following files?",
|
||||
"This room has been replaced and is no longer active.": "This room has been replaced and is no longer active.",
|
||||
"The conversation continues here.": "The conversation continues here.",
|
||||
"Encrypted room": "Encrypted room",
|
||||
"Unencrypted room": "Unencrypted room",
|
||||
"Hangup": "Hangup",
|
||||
|
|
Loading…
Reference in a new issue