Merge remote-tracking branch 'origin/develop' into develop

This commit is contained in:
Weblate 2018-08-29 17:38:53 +00:00
commit dae22a753a
4 changed files with 88 additions and 2 deletions

View file

@ -1,5 +1,6 @@
/* /*
Copyright 2015, 2016 OpenMarket Ltd Copyright 2015, 2016 OpenMarket Ltd
Copyright 2018 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -22,6 +23,29 @@ limitations under the License.
position: relative; 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 { .mx_MessageComposer_autocomplete_wrapper {
position: relative; position: relative;
height: 0; height: 0;

13
res/img/room_replaced.svg Normal file
View 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

View file

@ -1,6 +1,6 @@
/* /*
Copyright 2015, 2016 OpenMarket Ltd 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"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with 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 RoomViewStore from '../../../stores/RoomViewStore';
import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore"; import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
import Stickerpicker from './Stickerpicker'; import Stickerpicker from './Stickerpicker';
import { makeRoomPermalink } from '../../../matrix-to';
const formatButtonList = [ const formatButtonList = [
_td("bold"), _td("bold"),
@ -51,7 +52,9 @@ export default class MessageComposer extends React.Component {
this.onToggleMarkdownClicked = this.onToggleMarkdownClicked.bind(this); this.onToggleMarkdownClicked = this.onToggleMarkdownClicked.bind(this);
this.onInputStateChanged = this.onInputStateChanged.bind(this); this.onInputStateChanged = this.onInputStateChanged.bind(this);
this.onEvent = this.onEvent.bind(this); this.onEvent = this.onEvent.bind(this);
this._onRoomStateEvents = this._onRoomStateEvents.bind(this);
this._onRoomViewStoreUpdate = this._onRoomViewStoreUpdate.bind(this); this._onRoomViewStoreUpdate = this._onRoomViewStoreUpdate.bind(this);
this._onTombstoneClick = this._onTombstoneClick.bind(this);
this.state = { this.state = {
inputState: { inputState: {
@ -61,6 +64,7 @@ export default class MessageComposer extends React.Component {
}, },
showFormatting: SettingsStore.getValue('MessageComposer.showFormatting'), showFormatting: SettingsStore.getValue('MessageComposer.showFormatting'),
isQuoting: Boolean(RoomViewStore.getQuotingEvent()), isQuoting: Boolean(RoomViewStore.getQuotingEvent()),
tombstone: this._getRoomTombstone(),
}; };
} }
@ -70,6 +74,7 @@ export default class MessageComposer extends React.Component {
// marked as encrypted. // marked as encrypted.
// XXX: fragile as all hell - fixme somehow, perhaps with a dedicated Room.encryption event or something. // 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("event", this.onEvent);
MatrixClientPeg.get().on("RoomState.events", this._onRoomStateEvents);
this._roomStoreToken = RoomViewStore.addListener(this._onRoomViewStoreUpdate); this._roomStoreToken = RoomViewStore.addListener(this._onRoomViewStoreUpdate);
this._waitForOwnMember(); this._waitForOwnMember();
} }
@ -93,6 +98,7 @@ export default class MessageComposer extends React.Component {
componentWillUnmount() { componentWillUnmount() {
if (MatrixClientPeg.get()) { if (MatrixClientPeg.get()) {
MatrixClientPeg.get().removeListener("event", this.onEvent); MatrixClientPeg.get().removeListener("event", this.onEvent);
MatrixClientPeg.get().removeListener("RoomState.events", this._onRoomStateEvents);
} }
if (this._roomStoreToken) { if (this._roomStoreToken) {
this._roomStoreToken.remove(); this._roomStoreToken.remove();
@ -105,6 +111,18 @@ export default class MessageComposer extends React.Component {
this.forceUpdate(); 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() { _onRoomViewStoreUpdate() {
const isQuoting = Boolean(RoomViewStore.getQuotingEvent()); const isQuoting = Boolean(RoomViewStore.getQuotingEvent());
if (this.state.isQuoting === isQuoting) return; if (this.state.isQuoting === isQuoting) return;
@ -224,6 +242,17 @@ export default class MessageComposer extends React.Component {
this.messageComposerInput.enableRichtext(!this.state.inputState.isRichTextEnabled); 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() { render() {
const uploadInputStyle = {display: 'none'}; const uploadInputStyle = {display: 'none'};
const MemberAvatar = sdk.getComponent('avatars.MemberAvatar'); const MemberAvatar = sdk.getComponent('avatars.MemberAvatar');
@ -280,7 +309,7 @@ export default class MessageComposer extends React.Component {
</div>; </div>;
} }
const canSendMessages = this.props.room.currentState.maySendMessage( const canSendMessages = !this.state.tombstone && this.props.room.currentState.maySendMessage(
MatrixClientPeg.get().credentials.userId); MatrixClientPeg.get().credentials.userId);
if (canSendMessages) { if (canSendMessages) {
@ -340,6 +369,24 @@ export default class MessageComposer extends React.Component {
callButton, callButton,
videoCallButton, 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 { } else {
controls.push( controls.push(
<div key="controls_error" className="mx_MessageComposer_noperm_error"> <div key="controls_error" className="mx_MessageComposer_noperm_error">

View file

@ -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.", "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", "Upload Files": "Upload Files",
"Are you sure you want to upload the following files?": "Are you sure you want to upload the following 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", "Encrypted room": "Encrypted room",
"Unencrypted room": "Unencrypted room", "Unencrypted room": "Unencrypted room",
"Hangup": "Hangup", "Hangup": "Hangup",