Merge branch 'develop' into new-guest-access
This commit is contained in:
commit
5c885922d9
90 changed files with 5814 additions and 831 deletions
|
@ -16,8 +16,10 @@ limitations under the License.
|
|||
|
||||
'use strict';
|
||||
|
||||
|
||||
var React = require('react');
|
||||
var classNames = require("classnames");
|
||||
import { _t } from '../../../languageHandler';
|
||||
var Modal = require('../../../Modal');
|
||||
|
||||
var sdk = require('../../../index');
|
||||
|
@ -129,6 +131,9 @@ module.exports = WithMatrixClient(React.createClass({
|
|||
* for now.
|
||||
*/
|
||||
tileShape: React.PropTypes.string,
|
||||
|
||||
// show twelve hour timestamps
|
||||
isTwelveHour: React.PropTypes.bool,
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
|
@ -404,9 +409,10 @@ module.exports = WithMatrixClient(React.createClass({
|
|||
var isSending = (['sending', 'queued', 'encrypting'].indexOf(this.props.eventSendStatus) !== -1);
|
||||
const isRedacted = (eventType === 'm.room.message') && this.props.isRedacted;
|
||||
|
||||
var classes = classNames({
|
||||
const classes = classNames({
|
||||
mx_EventTile: true,
|
||||
mx_EventTile_info: isInfoMessage,
|
||||
mx_EventTile_12hr: this.props.isTwelveHour,
|
||||
mx_EventTile_encrypting: this.props.eventSendStatus == 'encrypting',
|
||||
mx_EventTile_sending: isSending,
|
||||
mx_EventTile_notSent: this.props.eventSendStatus == 'not_sent',
|
||||
|
@ -464,9 +470,9 @@ module.exports = WithMatrixClient(React.createClass({
|
|||
if (needsSenderProfile) {
|
||||
let aux = null;
|
||||
if (!this.props.tileShape) {
|
||||
if (msgtype === 'm.image') aux = "sent an image";
|
||||
else if (msgtype === 'm.video') aux = "sent a video";
|
||||
else if (msgtype === 'm.file') aux = "uploaded a file";
|
||||
if (msgtype === 'm.image') aux = _t('sent an image');
|
||||
else if (msgtype === 'm.video') aux = _t('sent a video');
|
||||
else if (msgtype === 'm.file') aux = _t('uploaded a file');
|
||||
sender = <SenderProfile onClick={ this.onSenderProfileClick } mxEvent={this.props.mxEvent} aux={aux} />;
|
||||
}
|
||||
else {
|
||||
|
@ -474,11 +480,10 @@ module.exports = WithMatrixClient(React.createClass({
|
|||
}
|
||||
}
|
||||
|
||||
var editButton = (
|
||||
const editButton = (
|
||||
<span className="mx_EventTile_editButton" title="Options" onClick={this.onEditClicked} />
|
||||
);
|
||||
|
||||
var e2e;
|
||||
let e2e;
|
||||
// cosmetic padlocks:
|
||||
if ((e2eEnabled && this.props.eventSendStatus) || this.props.mxEvent.getType() === 'm.room.encryption') {
|
||||
e2e = <img style={{ cursor: 'initial', marginLeft: '-1px' }} className="mx_EventTile_e2eIcon" alt="Encrypted by verified device" src="img/e2e-verified.svg" width="10" height="12" />;
|
||||
|
@ -489,7 +494,7 @@ module.exports = WithMatrixClient(React.createClass({
|
|||
e2e = <img onClick={ this.onCryptoClicked } className="mx_EventTile_e2eIcon" alt="Undecryptable" src="img/e2e-blocked.svg" width="12" height="12" style={{ marginLeft: "-1px" }} />;
|
||||
}
|
||||
else if (this.state.verified == true || (e2eEnabled && this.props.eventSendStatus)) {
|
||||
e2e = <img onClick={ this.onCryptoClicked } className="mx_EventTile_e2eIcon" alt="Encrypted by verified device" src="img/e2e-verified.svg" width="10" height="12"/>;
|
||||
e2e = <img onClick={ this.onCryptoClicked } className="mx_EventTile_e2eIcon" alt="Encrypted by verified device" src="img/e2e-verified.svg" width="10" height="12"/>;
|
||||
}
|
||||
else {
|
||||
e2e = <img onClick={ this.onCryptoClicked } className="mx_EventTile_e2eIcon" alt="Encrypted by unverified device" src="img/e2e-warning.svg" width="15" height="12" style={{ marginLeft: "-2px" }}/>;
|
||||
|
@ -499,11 +504,10 @@ module.exports = WithMatrixClient(React.createClass({
|
|||
e2e = <img onClick={ this.onCryptoClicked } className="mx_EventTile_e2eIcon" alt="Unencrypted message" src="img/e2e-unencrypted.svg" width="12" height="12"/>;
|
||||
}
|
||||
const timestamp = this.props.mxEvent.getTs() ?
|
||||
<MessageTimestamp ts={this.props.mxEvent.getTs()} /> : null;
|
||||
<MessageTimestamp showTwelveHour={this.props.isTwelveHour} ts={this.props.mxEvent.getTs()} /> : null;
|
||||
|
||||
if (this.props.tileShape === "notif") {
|
||||
var room = this.props.matrixClient.getRoom(this.props.mxEvent.getRoomId());
|
||||
|
||||
const room = this.props.matrixClient.getRoom(this.props.mxEvent.getRoomId());
|
||||
return (
|
||||
<div className={classes}>
|
||||
<div className="mx_EventTile_roomName">
|
||||
|
|
96
src/components/views/rooms/ForwardMessage.js
Normal file
96
src/components/views/rooms/ForwardMessage.js
Normal file
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
Copyright 2017 Vector Creations Ltd
|
||||
Copyright 2017 Michael Telatynski
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import MatrixClientPeg from '../../../MatrixClientPeg';
|
||||
import dis from '../../../dispatcher';
|
||||
import KeyCode from '../../../KeyCode';
|
||||
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'ForwardMessage',
|
||||
|
||||
propTypes: {
|
||||
currentRoomId: React.PropTypes.string.isRequired,
|
||||
|
||||
/* the MatrixEvent to be forwarded */
|
||||
mxEvent: React.PropTypes.object.isRequired,
|
||||
|
||||
onCancelClick: React.PropTypes.func.isRequired,
|
||||
},
|
||||
|
||||
componentWillMount: function() {
|
||||
dis.dispatch({
|
||||
action: 'ui_opacity',
|
||||
leftOpacity: 1.0,
|
||||
rightOpacity: 0.3,
|
||||
middleOpacity: 0.5,
|
||||
});
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
this.dispatcherRef = dis.register(this.onAction);
|
||||
document.addEventListener('keydown', this._onKeyDown);
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
dis.dispatch({
|
||||
action: 'ui_opacity',
|
||||
sideOpacity: 1.0,
|
||||
middleOpacity: 1.0,
|
||||
});
|
||||
dis.unregister(this.dispatcherRef);
|
||||
document.removeEventListener('keydown', this._onKeyDown);
|
||||
},
|
||||
|
||||
onAction: function(payload) {
|
||||
if (payload.action === 'view_room') {
|
||||
const event = this.props.mxEvent;
|
||||
const Client = MatrixClientPeg.get();
|
||||
Client.sendEvent(payload.room_id, event.getType(), event.getContent()).done(() => {
|
||||
dis.dispatch({action: 'message_sent'});
|
||||
}, (err) => {
|
||||
if (err.name === "UnknownDeviceError") {
|
||||
dis.dispatch({
|
||||
action: 'unknown_device_error',
|
||||
err: err,
|
||||
room: Client.getRoom(payload.room_id),
|
||||
});
|
||||
}
|
||||
dis.dispatch({action: 'message_send_failed'});
|
||||
});
|
||||
if (this.props.currentRoomId === payload.room_id) this.props.onCancelClick();
|
||||
}
|
||||
},
|
||||
|
||||
_onKeyDown: function(ev) {
|
||||
switch (ev.keyCode) {
|
||||
case KeyCode.ESCAPE:
|
||||
this.props.onCancelClick();
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<div className="mx_ForwardMessage">
|
||||
<h1>{_t('Please select the destination room for this message')}</h1>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
});
|
|
@ -31,6 +31,7 @@ import classNames from 'classnames';
|
|||
import dis from '../../../dispatcher';
|
||||
import Modal from '../../../Modal';
|
||||
import sdk from '../../../index';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import createRoom from '../../../createRoom';
|
||||
import DMRoomMap from '../../../utils/DMRoomMap';
|
||||
import Unread from '../../../Unread';
|
||||
|
@ -219,7 +220,7 @@ module.exports = WithMatrixClient(React.createClass({
|
|||
|
||||
onKick: function() {
|
||||
const membership = this.props.member.membership;
|
||||
const kickLabel = membership === "invite" ? "Disinvite" : "Kick";
|
||||
const kickLabel = membership === "invite" ? _t("Disinvite") : _t("Kick");
|
||||
const ConfirmUserActionDialog = sdk.getComponent("dialogs.ConfirmUserActionDialog");
|
||||
Modal.createDialog(ConfirmUserActionDialog, {
|
||||
member: this.props.member,
|
||||
|
@ -241,7 +242,7 @@ module.exports = WithMatrixClient(React.createClass({
|
|||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
console.error("Kick error: " + err);
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: "Failed to kick",
|
||||
title: _t("Failed to kick"),
|
||||
description: ((err && err.message) ? err.message : "Operation failed"),
|
||||
});
|
||||
}
|
||||
|
@ -256,7 +257,7 @@ module.exports = WithMatrixClient(React.createClass({
|
|||
const ConfirmUserActionDialog = sdk.getComponent("dialogs.ConfirmUserActionDialog");
|
||||
Modal.createDialog(ConfirmUserActionDialog, {
|
||||
member: this.props.member,
|
||||
action: this.props.member.membership == 'ban' ? 'Unban' : 'Ban',
|
||||
action: this.props.member.membership == 'ban' ? _t("Unban") : _t("Ban"),
|
||||
askReason: this.props.member.membership != 'ban',
|
||||
danger: this.props.member.membership != 'ban',
|
||||
onFinished: (proceed, reason) => {
|
||||
|
@ -283,8 +284,8 @@ module.exports = WithMatrixClient(React.createClass({
|
|||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
console.error("Ban error: " + err);
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: "Error",
|
||||
description: "Failed to ban user",
|
||||
title: _t("Error"),
|
||||
description: _t("Failed to ban user"),
|
||||
});
|
||||
}
|
||||
).finally(()=>{
|
||||
|
@ -333,8 +334,8 @@ module.exports = WithMatrixClient(React.createClass({
|
|||
}, function(err) {
|
||||
console.error("Mute error: " + err);
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: "Error",
|
||||
description: "Failed to mute user",
|
||||
title: _t("Error"),
|
||||
description: _t("Failed to mute user"),
|
||||
});
|
||||
}
|
||||
).finally(()=>{
|
||||
|
@ -378,8 +379,8 @@ module.exports = WithMatrixClient(React.createClass({
|
|||
} else {
|
||||
console.error("Toggle moderator error:" + err);
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: "Error",
|
||||
description: "Failed to toggle moderator status",
|
||||
title: _t("Error"),
|
||||
description: _t("Failed to toggle moderator status"),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -399,8 +400,8 @@ module.exports = WithMatrixClient(React.createClass({
|
|||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
console.error("Failed to change power level " + err);
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: "Error",
|
||||
description: "Failed to change power level",
|
||||
title: _t("Error"),
|
||||
description: _t("Failed to change power level"),
|
||||
});
|
||||
}
|
||||
).finally(()=>{
|
||||
|
@ -428,13 +429,13 @@ module.exports = WithMatrixClient(React.createClass({
|
|||
if (parseInt(myPower) === parseInt(powerLevel)) {
|
||||
var QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||
Modal.createDialog(QuestionDialog, {
|
||||
title: "Warning",
|
||||
title: _t("Warning!"),
|
||||
description:
|
||||
<div>
|
||||
You will not be able to undo this change as you are promoting the user to have the same power level as yourself.<br/>
|
||||
Are you sure?
|
||||
{ _t("You will not be able to undo this change as you are promoting the user to have the same power level as yourself") }.<br/>
|
||||
{ _t("Are you sure?") }
|
||||
</div>,
|
||||
button: "Continue",
|
||||
button: _t("Continue"),
|
||||
onFinished: function(confirmed) {
|
||||
if (confirmed) {
|
||||
self._applyPowerChange(roomId, target, powerLevel, powerLevelEvent);
|
||||
|
@ -577,9 +578,9 @@ module.exports = WithMatrixClient(React.createClass({
|
|||
// still loading
|
||||
devComponents = <Spinner />;
|
||||
} else if (devices === null) {
|
||||
devComponents = "Unable to load device list";
|
||||
devComponents = _t("Unable to load device list");
|
||||
} else if (devices.length === 0) {
|
||||
devComponents = "No devices with registered encryption keys";
|
||||
devComponents = _t("No devices with registered encryption keys");
|
||||
} else {
|
||||
devComponents = [];
|
||||
for (var i = 0; i < devices.length; i++) {
|
||||
|
@ -591,7 +592,7 @@ module.exports = WithMatrixClient(React.createClass({
|
|||
|
||||
return (
|
||||
<div>
|
||||
<h3>Devices</h3>
|
||||
<h3>{ _t("Devices") }</h3>
|
||||
<div className="mx_MemberInfo_devices">
|
||||
{devComponents}
|
||||
</div>
|
||||
|
@ -640,11 +641,11 @@ module.exports = WithMatrixClient(React.createClass({
|
|||
<div className="mx_RoomTile_avatar">
|
||||
<img src="img/create-big.svg" width="26" height="26" />
|
||||
</div>
|
||||
<div className={labelClasses}><i>Start new chat</i></div>
|
||||
<div className={labelClasses}><i>{ _t("Start a chat") }</i></div>
|
||||
</AccessibleButton>;
|
||||
|
||||
startChat = <div>
|
||||
<h3>Direct chats</h3>
|
||||
<h3>{ _t("Direct chats") }</h3>
|
||||
{tiles}
|
||||
{startNewChat}
|
||||
</div>;
|
||||
|
@ -657,7 +658,7 @@ module.exports = WithMatrixClient(React.createClass({
|
|||
|
||||
if (this.state.can.kick) {
|
||||
const membership = this.props.member.membership;
|
||||
const kickLabel = membership === "invite" ? "Disinvite" : "Kick";
|
||||
const kickLabel = membership === "invite" ? _t("Disinvite") : _t("Kick");
|
||||
kickButton = (
|
||||
<AccessibleButton className="mx_MemberInfo_field"
|
||||
onClick={this.onKick}>
|
||||
|
@ -666,9 +667,9 @@ module.exports = WithMatrixClient(React.createClass({
|
|||
);
|
||||
}
|
||||
if (this.state.can.ban) {
|
||||
let label = 'Ban';
|
||||
let label = _t("Ban");
|
||||
if (this.props.member.membership == 'ban') {
|
||||
label = 'Unban';
|
||||
label = _t("Unban");
|
||||
}
|
||||
banButton = (
|
||||
<AccessibleButton className="mx_MemberInfo_field"
|
||||
|
@ -678,7 +679,7 @@ module.exports = WithMatrixClient(React.createClass({
|
|||
);
|
||||
}
|
||||
if (this.state.can.mute) {
|
||||
const muteLabel = this.state.muted ? "Unmute" : "Mute";
|
||||
const muteLabel = this.state.muted ? _t("Unmute") : _t("Mute");
|
||||
muteButton = (
|
||||
<AccessibleButton className="mx_MemberInfo_field"
|
||||
onClick={this.onMuteToggle}>
|
||||
|
@ -687,7 +688,7 @@ module.exports = WithMatrixClient(React.createClass({
|
|||
);
|
||||
}
|
||||
if (this.state.can.toggleMod) {
|
||||
var giveOpLabel = this.state.isTargetMod ? "Revoke Moderator" : "Make Moderator";
|
||||
var giveOpLabel = this.state.isTargetMod ? _t("Revoke Moderator") : _t("Make Moderator");
|
||||
giveModButton = <AccessibleButton className="mx_MemberInfo_field" onClick={this.onModToggle}>
|
||||
{giveOpLabel}
|
||||
</AccessibleButton>;
|
||||
|
@ -738,7 +739,7 @@ module.exports = WithMatrixClient(React.createClass({
|
|||
{ this.props.member.userId }
|
||||
</div>
|
||||
<div className="mx_MemberInfo_profileField">
|
||||
Level: <b><PowerSelector controlled={true} value={ parseInt(this.props.member.powerLevel) } disabled={ !this.state.can.modifyLevel } onChange={ this.onPowerChange }/></b>
|
||||
{ _t("Level") }: <b><PowerSelector controlled={true} value={ parseInt(this.props.member.powerLevel) } disabled={ !this.state.can.modifyLevel } onChange={ this.onPowerChange }/></b>
|
||||
</div>
|
||||
<div className="mx_MemberInfo_profileField">
|
||||
<PresenceLabel activeAgo={ presenceLastActiveAgo }
|
||||
|
|
|
@ -14,6 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
var React = require('react');
|
||||
import { _t } from '../../../languageHandler';
|
||||
var classNames = require('classnames');
|
||||
var Matrix = require("matrix-js-sdk");
|
||||
var q = require('q');
|
||||
|
@ -207,7 +208,9 @@ module.exports = React.createClass({
|
|||
// For now we'll pretend this is any entity. It should probably be a separate tile.
|
||||
var EntityTile = sdk.getComponent("rooms.EntityTile");
|
||||
var BaseAvatar = sdk.getComponent("avatars.BaseAvatar");
|
||||
var text = "and " + overflowCount + " other" + (overflowCount > 1 ? "s" : "") + "...";
|
||||
var text = (overflowCount > 1)
|
||||
? _t("and %(overflowCount)s others...", { overflowCount: overflowCount })
|
||||
: _t("and one other...");
|
||||
return (
|
||||
<EntityTile className="mx_EntityTile_ellipsis" avatarJsx={
|
||||
<BaseAvatar url="img/ellipsis.svg" name="..." width={36} height={36} />
|
||||
|
@ -363,8 +366,8 @@ module.exports = React.createClass({
|
|||
var inputBox = (
|
||||
<form autoComplete="off">
|
||||
<input className="mx_MemberList_query" id="mx_MemberList_query" type="text"
|
||||
onChange={this.onSearchQueryChanged} value={this.state.searchQuery}
|
||||
placeholder="Filter room members" />
|
||||
onChange={this.onSearchQueryChanged} value={this.state.searchQuery}
|
||||
placeholder={ _t('Filter room members') } />
|
||||
</form>
|
||||
);
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
var React = require('react');
|
||||
|
||||
import { _t } from '../../../languageHandler';
|
||||
var CallHandler = require('../../../CallHandler');
|
||||
var MatrixClientPeg = require('../../../MatrixClientPeg');
|
||||
var Modal = require('../../../Modal');
|
||||
|
@ -114,10 +114,10 @@ export default class MessageComposer extends React.Component {
|
|||
}
|
||||
|
||||
Modal.createDialog(QuestionDialog, {
|
||||
title: "Upload Files",
|
||||
title: _t('Upload Files'),
|
||||
description: (
|
||||
<div>
|
||||
<p>Are you sure you want upload the following files?</p>
|
||||
<p>{ _t('Are you sure you want upload the following files?') }</p>
|
||||
<ul style={{listStyle: 'none', textAlign: 'left'}}>
|
||||
{fileList}
|
||||
</ul>
|
||||
|
@ -236,11 +236,11 @@ export default class MessageComposer extends React.Component {
|
|||
if (roomIsEncrypted) {
|
||||
// FIXME: show a /!\ if there are untrusted devices in the room...
|
||||
e2eImg = 'img/e2e-verified.svg';
|
||||
e2eTitle = 'Encrypted room';
|
||||
e2eTitle = _t('Encrypted room');
|
||||
e2eClass = 'mx_MessageComposer_e2eIcon';
|
||||
} else {
|
||||
e2eImg = 'img/e2e-unencrypted.svg';
|
||||
e2eTitle = 'Unencrypted room';
|
||||
e2eTitle = _t('Unencrypted room');
|
||||
e2eClass = 'mx_MessageComposer_e2eIcon mx_filterFlipColor';
|
||||
}
|
||||
|
||||
|
@ -253,16 +253,16 @@ export default class MessageComposer extends React.Component {
|
|||
if (this.props.callState && this.props.callState !== 'ended') {
|
||||
hangupButton =
|
||||
<div key="controls_hangup" className="mx_MessageComposer_hangup" onClick={this.onHangupClick}>
|
||||
<img src="img/hangup.svg" alt="Hangup" title="Hangup" width="25" height="26"/>
|
||||
<img src="img/hangup.svg" alt={ _t('Hangup') } title={ _t('Hangup') } width="25" height="26"/>
|
||||
</div>;
|
||||
}
|
||||
else {
|
||||
callButton =
|
||||
<div key="controls_call" className="mx_MessageComposer_voicecall" onClick={this.onVoiceCallClick} title="Voice call">
|
||||
<div key="controls_call" className="mx_MessageComposer_voicecall" onClick={this.onVoiceCallClick} title={ _t('Voice call') }>
|
||||
<TintableSvg src="img/icon-call.svg" width="35" height="35"/>
|
||||
</div>;
|
||||
videoCallButton =
|
||||
<div key="controls_videocall" className="mx_MessageComposer_videocall" onClick={this.onCallClick} title="Video call">
|
||||
<div key="controls_videocall" className="mx_MessageComposer_videocall" onClick={this.onCallClick} title={ _t('Video call') }>
|
||||
<TintableSvg src="img/icons-video.svg" width="35" height="35"/>
|
||||
</div>;
|
||||
}
|
||||
|
@ -276,7 +276,7 @@ export default class MessageComposer extends React.Component {
|
|||
// complex because of conference calls.
|
||||
var uploadButton = (
|
||||
<div key="controls_upload" className="mx_MessageComposer_upload"
|
||||
onClick={this.onUploadClick} title="Upload file">
|
||||
onClick={this.onUploadClick} title={ _t('Upload file') }>
|
||||
<TintableSvg src="img/icons-upload.svg" width="35" height="35"/>
|
||||
<input ref="uploadInput" type="file"
|
||||
style={uploadInputStyle}
|
||||
|
@ -296,7 +296,7 @@ export default class MessageComposer extends React.Component {
|
|||
);
|
||||
|
||||
const placeholderText = roomIsEncrypted ?
|
||||
"Send an encrypted message…" : "Send a message (unencrypted)…";
|
||||
_t('Send an encrypted message') + '…' : _t('Send a message (unencrypted)') + '…';
|
||||
|
||||
controls.push(
|
||||
<MessageComposerInput
|
||||
|
@ -321,7 +321,7 @@ export default class MessageComposer extends React.Component {
|
|||
} else {
|
||||
controls.push(
|
||||
<div key="controls_error" className="mx_MessageComposer_noperm_error">
|
||||
You do not have permission to post to this room
|
||||
{ _t('You do not have permission to post to this room') }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -350,7 +350,7 @@ export default class MessageComposer extends React.Component {
|
|||
mx_filterFlipColor: true,
|
||||
});
|
||||
return <img className={className}
|
||||
title={name}
|
||||
title={ _t(name) }
|
||||
onMouseDown={disabled ? null : onFormatButtonClicked}
|
||||
key={name}
|
||||
src={`img/button-text-${name}${suffix}.svg`}
|
||||
|
@ -370,11 +370,11 @@ export default class MessageComposer extends React.Component {
|
|||
<div className="mx_MessageComposer_formatbar" style={this.state.showFormatting ? {} : {display: 'none'}}>
|
||||
{formatButtons}
|
||||
<div style={{flex: 1}}></div>
|
||||
<img title={`Turn Markdown ${this.state.inputState.isRichtextEnabled ? 'on' : 'off'}`}
|
||||
<img title={ this.state.inputState.isRichtextEnabled ? _t("Turn Markdown on") : _t("Turn Markdown off") }
|
||||
onMouseDown={this.onToggleMarkdownClicked}
|
||||
className="mx_MessageComposer_formatbar_markdown mx_filterFlipColor"
|
||||
src={`img/button-md-${!this.state.inputState.isRichtextEnabled}.png`} />
|
||||
<img title="Hide Text Formatting Toolbar"
|
||||
<img title={ _t("Hide Text Formatting Toolbar") }
|
||||
onClick={this.onToggleFormattingClicked}
|
||||
className="mx_MessageComposer_formatbar_cancel mx_filterFlipColor"
|
||||
src="img/icon-text-cancel.svg" />
|
||||
|
|
|
@ -30,6 +30,7 @@ import type {MatrixClient} from 'matrix-js-sdk/lib/matrix';
|
|||
import SlashCommands from '../../../SlashCommands';
|
||||
import Modal from '../../../Modal';
|
||||
import sdk from '../../../index';
|
||||
import { _t } from '../../../languageHandler';
|
||||
|
||||
import dis from '../../../dispatcher';
|
||||
import KeyCode from '../../../KeyCode';
|
||||
|
@ -504,8 +505,8 @@ export default class MessageComposerInput extends React.Component {
|
|||
console.error("Command failure: %s", err);
|
||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: "Server error",
|
||||
description: ((err && err.message) ? err.message : "Server unavailable, overloaded, or something else went wrong."),
|
||||
title: _t("Server error"),
|
||||
description: ((err && err.message) ? err.message : _t("Server unavailable, overloaded, or something else went wrong") + "."),
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -513,8 +514,8 @@ export default class MessageComposerInput extends React.Component {
|
|||
console.error(cmd.error);
|
||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: "Command error",
|
||||
description: cmd.error
|
||||
title: _t("Command error"),
|
||||
description: cmd.error,
|
||||
});
|
||||
}
|
||||
return true;
|
||||
|
@ -719,7 +720,7 @@ export default class MessageComposerInput extends React.Component {
|
|||
<div className={className}>
|
||||
<img className="mx_MessageComposer_input_markdownIndicator mx_filterFlipColor"
|
||||
onMouseDown={this.onMarkdownToggleClicked}
|
||||
title={`Markdown is ${this.state.isRichtextEnabled ? 'disabled' : 'enabled'}`}
|
||||
title={ this.state.isRichtextEnabled ? _t("Markdown is disabled") : _t("Markdown is enabled")}
|
||||
src={`img/button-md-${!this.state.isRichtextEnabled}.png`} />
|
||||
<Editor ref="editor"
|
||||
placeholder={this.props.placeholder}
|
||||
|
|
|
@ -20,6 +20,7 @@ var SlashCommands = require("../../../SlashCommands");
|
|||
var Modal = require("../../../Modal");
|
||||
var MemberEntry = require("../../../TabCompleteEntries").MemberEntry;
|
||||
var sdk = require('../../../index');
|
||||
import { _t } from '../../../languageHandler';
|
||||
import UserSettingsStore from "../../../UserSettingsStore";
|
||||
|
||||
var dis = require("../../../dispatcher");
|
||||
|
@ -294,8 +295,8 @@ export default React.createClass({
|
|||
else {
|
||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: "Unknown command",
|
||||
description: "Usage: /markdown on|off"
|
||||
title: _t("Unknown command"),
|
||||
description: _t("Usage") + ": /markdown on|off",
|
||||
});
|
||||
}
|
||||
return;
|
||||
|
@ -314,8 +315,8 @@ export default React.createClass({
|
|||
console.error("Command failure: %s", err);
|
||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: "Server error",
|
||||
description: ((err && err.message) ? err.message : "Server unavailable, overloaded, or something else went wrong."),
|
||||
title: _t("Server error"),
|
||||
description: ((err && err.message) ? err.message : _t("Server unavailable, overloaded, or something else went wrong") + "."),
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -323,8 +324,8 @@ export default React.createClass({
|
|||
console.error(cmd.error);
|
||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: "Command error",
|
||||
description: cmd.error
|
||||
title: _t("Command error"),
|
||||
description: cmd.error,
|
||||
});
|
||||
}
|
||||
return;
|
||||
|
|
|
@ -19,6 +19,7 @@ limitations under the License.
|
|||
var React = require('react');
|
||||
var classNames = require('classnames');
|
||||
var sdk = require('../../../index');
|
||||
import { _t } from '../../../languageHandler';
|
||||
var MatrixClientPeg = require('../../../MatrixClientPeg');
|
||||
var Modal = require("../../../Modal");
|
||||
var dis = require("../../../dispatcher");
|
||||
|
@ -119,8 +120,8 @@ module.exports = React.createClass({
|
|||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
console.error("Failed to set avatar: " + errMsg);
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: "Error",
|
||||
description: "Failed to set avatar.",
|
||||
title: _t("Error"),
|
||||
description: _t("Failed to set avatar."),
|
||||
});
|
||||
}).done();
|
||||
},
|
||||
|
@ -188,6 +189,9 @@ module.exports = React.createClass({
|
|||
);
|
||||
|
||||
save_button = <AccessibleButton className="mx_RoomHeader_textButton" onClick={this.props.onSaveClick}>Save</AccessibleButton>;
|
||||
}
|
||||
|
||||
if (this.props.onCancelClick) {
|
||||
cancel_button = <CancelButton onClick={this.props.onCancelClick}/>;
|
||||
}
|
||||
|
||||
|
@ -205,7 +209,7 @@ module.exports = React.createClass({
|
|||
// don't display the search count until the search completes and
|
||||
// gives us a valid (possibly zero) searchCount.
|
||||
if (this.props.searchInfo && this.props.searchInfo.searchCount !== undefined && this.props.searchInfo.searchCount !== null) {
|
||||
searchStatus = <div className="mx_RoomHeader_searchStatus"> (~{ this.props.searchInfo.searchCount } results)</div>;
|
||||
searchStatus = <div className="mx_RoomHeader_searchStatus"> { _t("(~%(searchCount)s results)", { searchCount: this.props.searchInfo.searchCount }) }</div>;
|
||||
}
|
||||
|
||||
// XXX: this is a bit inefficient - we could just compare room.name for 'Empty room'...
|
||||
|
@ -220,7 +224,7 @@ module.exports = React.createClass({
|
|||
}
|
||||
}
|
||||
|
||||
var roomName = 'Join Room';
|
||||
var roomName = _t("Join Room");
|
||||
if (this.props.oobData && this.props.oobData.name) {
|
||||
roomName = this.props.oobData.name;
|
||||
} else if (this.props.room) {
|
||||
|
@ -261,7 +265,7 @@ module.exports = React.createClass({
|
|||
<div className="mx_RoomHeader_avatarPicker_edit">
|
||||
<label htmlFor="avatarInput" ref="file_label">
|
||||
<img src="img/camera.svg"
|
||||
alt="Upload avatar" title="Upload avatar"
|
||||
alt={ _t("Upload avatar") } title={ _t("Upload avatar") }
|
||||
width="17" height="15" />
|
||||
</label>
|
||||
<input id="avatarInput" type="file" onChange={ this.onAvatarSelected }/>
|
||||
|
@ -296,7 +300,7 @@ module.exports = React.createClass({
|
|||
var forget_button;
|
||||
if (this.props.onForgetClick) {
|
||||
forget_button =
|
||||
<AccessibleButton className="mx_RoomHeader_button" onClick={this.props.onForgetClick} title="Forget room">
|
||||
<AccessibleButton className="mx_RoomHeader_button" onClick={this.props.onForgetClick} title={ _t("Forget room") }>
|
||||
<TintableSvg src="img/leave.svg" width="26" height="20"/>
|
||||
</AccessibleButton>;
|
||||
}
|
||||
|
@ -304,7 +308,7 @@ module.exports = React.createClass({
|
|||
let search_button;
|
||||
if (this.props.onSearchClick && this.props.inRoom) {
|
||||
search_button =
|
||||
<AccessibleButton className="mx_RoomHeader_button" onClick={this.props.onSearchClick} title="Search">
|
||||
<AccessibleButton className="mx_RoomHeader_button" onClick={this.props.onSearchClick} title={ _t("Search") }>
|
||||
<TintableSvg src="img/icons-search.svg" width="35" height="35"/>
|
||||
</AccessibleButton>;
|
||||
}
|
||||
|
@ -312,7 +316,7 @@ module.exports = React.createClass({
|
|||
var rightPanel_buttons;
|
||||
if (this.props.collapsedRhs) {
|
||||
rightPanel_buttons =
|
||||
<AccessibleButton className="mx_RoomHeader_button" onClick={this.onShowRhsClick} title="Show panel">
|
||||
<AccessibleButton className="mx_RoomHeader_button" onClick={this.onShowRhsClick} title={ _t('Show panel') }>
|
||||
<TintableSvg src="img/maximise.svg" width="10" height="16"/>
|
||||
</AccessibleButton>;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ limitations under the License.
|
|||
'use strict';
|
||||
var React = require("react");
|
||||
var ReactDOM = require("react-dom");
|
||||
import { _t } from '../../../languageHandler';
|
||||
var GeminiScrollbar = require('react-gemini-scrollbar');
|
||||
var MatrixClientPeg = require("../../../MatrixClientPeg");
|
||||
var CallHandler = require('../../../CallHandler');
|
||||
|
@ -559,13 +560,12 @@ module.exports = React.createClass({
|
|||
render: function() {
|
||||
var RoomSubList = sdk.getComponent('structures.RoomSubList');
|
||||
var self = this;
|
||||
|
||||
return (
|
||||
<GeminiScrollbar className="mx_RoomList_scrollbar"
|
||||
autoshow={true} onScroll={ self._whenScrolling } ref="gemscroll">
|
||||
<div className="mx_RoomList">
|
||||
<RoomSubList list={ self.state.lists['im.vector.fake.invite'] }
|
||||
label="Invites"
|
||||
label={ _t('Invites') }
|
||||
editable={ false }
|
||||
order="recent"
|
||||
selectedRoom={ self.props.selectedRoom }
|
||||
|
@ -576,7 +576,7 @@ module.exports = React.createClass({
|
|||
onShowMoreRooms={ self.onShowMoreRooms } />
|
||||
|
||||
<RoomSubList list={ self.state.lists['m.favourite'] }
|
||||
label="Favourites"
|
||||
label={ _t('Favourites') }
|
||||
tagName="m.favourite"
|
||||
emptyContent={this._getEmptyContent('m.favourite')}
|
||||
editable={ true }
|
||||
|
@ -589,7 +589,7 @@ module.exports = React.createClass({
|
|||
onShowMoreRooms={ self.onShowMoreRooms } />
|
||||
|
||||
<RoomSubList list={ self.state.lists['im.vector.fake.direct'] }
|
||||
label="People"
|
||||
label={ _t('People') }
|
||||
tagName="im.vector.fake.direct"
|
||||
emptyContent={this._getEmptyContent('im.vector.fake.direct')}
|
||||
headerItems={this._getHeaderItems('im.vector.fake.direct')}
|
||||
|
@ -604,7 +604,7 @@ module.exports = React.createClass({
|
|||
onShowMoreRooms={ self.onShowMoreRooms } />
|
||||
|
||||
<RoomSubList list={ self.state.lists['im.vector.fake.recent'] }
|
||||
label="Rooms"
|
||||
label={ _t('Rooms') }
|
||||
editable={ true }
|
||||
emptyContent={this._getEmptyContent('im.vector.fake.recent')}
|
||||
headerItems={this._getHeaderItems('im.vector.fake.recent')}
|
||||
|
@ -636,7 +636,7 @@ module.exports = React.createClass({
|
|||
}) }
|
||||
|
||||
<RoomSubList list={ self.state.lists['m.lowpriority'] }
|
||||
label="Low priority"
|
||||
label={ _t('Low priority') }
|
||||
tagName="m.lowpriority"
|
||||
emptyContent={this._getEmptyContent('m.lowpriority')}
|
||||
editable={ true }
|
||||
|
@ -649,7 +649,7 @@ module.exports = React.createClass({
|
|||
onShowMoreRooms={ self.onShowMoreRooms } />
|
||||
|
||||
<RoomSubList list={ self.state.lists['im.vector.fake.archived'] }
|
||||
label="Historical"
|
||||
label={ _t('Historical') }
|
||||
editable={ false }
|
||||
order="recent"
|
||||
selectedRoom={ self.props.selectedRoom }
|
||||
|
|
|
@ -21,6 +21,8 @@ var React = require('react');
|
|||
var sdk = require('../../../index');
|
||||
var MatrixClientPeg = require('../../../MatrixClientPeg');
|
||||
|
||||
import { _t } from '../../../languageHandler';
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'RoomPreviewBar',
|
||||
|
||||
|
@ -84,7 +86,7 @@ module.exports = React.createClass({
|
|||
_roomNameElement: function(fallback) {
|
||||
fallback = fallback || 'a room';
|
||||
const name = this.props.room ? this.props.room.name : (this.props.room_alias || "");
|
||||
return name ? <b>{ name }</b> : fallback;
|
||||
return name ? name : fallback;
|
||||
},
|
||||
|
||||
render: function() {
|
||||
|
@ -128,13 +130,14 @@ module.exports = React.createClass({
|
|||
</div>;
|
||||
}
|
||||
}
|
||||
// TODO: find a way to respect HTML in counterpart!
|
||||
joinBlock = (
|
||||
<div>
|
||||
<div className="mx_RoomPreviewBar_invite_text">
|
||||
You have been invited to join this room by <b>{ this.props.inviterName }</b>
|
||||
{ _t('You have been invited to join this room by %(inviterName)s', {inviterName: this.props.inviterName}) }
|
||||
</div>
|
||||
<div className="mx_RoomPreviewBar_join_text">
|
||||
Would you like to <a onClick={ this.props.onJoinClick }>accept</a> or <a onClick={ this.props.onRejectClick }>decline</a> this invitation?
|
||||
{ _t('Would you like to') } <a onClick={ this.props.onJoinClick }>{ _t('accept') }</a> { _t('or') } <a onClick={ this.props.onRejectClick }>{ _t('decline') }</a> { _t('this invitation?') }
|
||||
</div>
|
||||
{emailMatchBlock}
|
||||
</div>
|
||||
|
@ -186,8 +189,8 @@ module.exports = React.createClass({
|
|||
joinBlock = (
|
||||
<div>
|
||||
<div className="mx_RoomPreviewBar_join_text">
|
||||
You are trying to access { name }.<br/>
|
||||
<a onClick={ this.props.onJoinClick }><b>Click here</b></a> to join the discussion!
|
||||
{ _t('You are trying to access %(roomName)s', {roomName: name}) }.<br/>
|
||||
<a onClick={ this.props.onJoinClick }><b>{ _t('Click here') }</b></a> { _t('to join the discussion') }!
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -196,7 +199,7 @@ module.exports = React.createClass({
|
|||
if (this.props.canPreview) {
|
||||
previewBlock = (
|
||||
<div className="mx_RoomPreviewBar_preview_text">
|
||||
This is a preview of this room. Room interactions have been disabled.
|
||||
{ _t('This is a preview of this room. Room interactions have been disabled') }.
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||
|
||||
import q from 'q';
|
||||
import React from 'react';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import MatrixClientPeg from '../../../MatrixClientPeg';
|
||||
import SdkConfig from '../../../SdkConfig';
|
||||
import sdk from '../../../index';
|
||||
|
@ -56,8 +57,8 @@ const BannedUser = React.createClass({
|
|||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
console.error("Failed to unban: " + err);
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: "Error",
|
||||
description: "Failed to unban",
|
||||
title: _t('Error'),
|
||||
description: _t('Failed to unban'),
|
||||
});
|
||||
}).done();
|
||||
},
|
||||
|
@ -70,7 +71,7 @@ const BannedUser = React.createClass({
|
|||
<AccessibleButton className="mx_RoomSettings_unbanButton"
|
||||
onClick={this._onUnbanClick}
|
||||
>
|
||||
Unban
|
||||
{ _t('Unban') }
|
||||
</AccessibleButton>
|
||||
{this.props.member.userId}
|
||||
</li>
|
||||
|
@ -400,13 +401,13 @@ module.exports = React.createClass({
|
|||
var value = ev.target.value;
|
||||
|
||||
Modal.createDialog(QuestionDialog, {
|
||||
title: "Privacy warning",
|
||||
title: _t('Privacy warning'),
|
||||
description:
|
||||
<div>
|
||||
Changes to who can read history will only apply to future messages in this room.<br/>
|
||||
The visibility of existing history will be unchanged.
|
||||
{ _t('Changes to who can read history will only apply to future messages in this room') }.<br/>
|
||||
{ _t('The visibility of existing history will be unchanged') }.
|
||||
</div>,
|
||||
button: "Continue",
|
||||
button: _t('Continue'),
|
||||
onFinished: function(confirmed) {
|
||||
if (confirmed) {
|
||||
self.setState({
|
||||
|
@ -523,11 +524,11 @@ module.exports = React.createClass({
|
|||
MatrixClientPeg.get().forget(this.props.room.roomId).done(function() {
|
||||
dis.dispatch({ action: 'view_next_room' });
|
||||
}, function(err) {
|
||||
var errCode = err.errcode || "unknown error code";
|
||||
var errCode = err.errcode || _t('unknown error code');
|
||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: "Error",
|
||||
description: `Failed to forget room (${errCode})`
|
||||
title: _t('Error'),
|
||||
description: _t("Failed to forget room %(errCode)s", { errCode: errCode }),
|
||||
});
|
||||
});
|
||||
},
|
||||
|
@ -537,14 +538,14 @@ module.exports = React.createClass({
|
|||
|
||||
var QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||
Modal.createDialog(QuestionDialog, {
|
||||
title: "Warning!",
|
||||
title: _t('Warning!'),
|
||||
description: (
|
||||
<div>
|
||||
<p>End-to-end encryption is in beta and may not be reliable.</p>
|
||||
<p>You should <b>not</b> yet trust it to secure data.</p>
|
||||
<p>Devices will <b>not</b> yet be able to decrypt history from before they joined the room.</p>
|
||||
<p>Once encryption is enabled for a room it <b>cannot</b> be turned off again (for now).</p>
|
||||
<p>Encrypted messages will not be visible on clients that do not yet implement encryption.</p>
|
||||
<p>{ _t('End-to-end encryption is in beta and may not be reliable') }.</p>
|
||||
<p>{ _t('You should not yet trust it to secure data') }.</p>
|
||||
<p>{ _t('Devices will not yet be able to decrypt history from before they joined the room') }.</p>
|
||||
<p>{ _t('Once encryption is enabled for a room it cannot be turned off again (for now)') }.</p>
|
||||
<p>{ _t('Encrypted messages will not be visible on clients that do not yet implement encryption') }.</p>
|
||||
</div>
|
||||
),
|
||||
onFinished: confirm=>{
|
||||
|
@ -572,7 +573,7 @@ module.exports = React.createClass({
|
|||
<input type="checkbox" ref="blacklistUnverified"
|
||||
defaultChecked={ isGlobalBlacklistUnverified || isRoomBlacklistUnverified }
|
||||
disabled={ isGlobalBlacklistUnverified || (this.refs.encrypt && !this.refs.encrypt.checked) }/>
|
||||
Never send encrypted messages to unverified devices in this room from this device.
|
||||
{ _t('Never send encrypted messages to unverified devices in this room from this device') }.
|
||||
</label>;
|
||||
|
||||
if (!isEncrypted &&
|
||||
|
@ -582,7 +583,7 @@ module.exports = React.createClass({
|
|||
<label>
|
||||
<input type="checkbox" ref="encrypt" onClick={ this.onEnableEncryptionClick }/>
|
||||
<img className="mx_RoomSettings_e2eIcon" src="img/e2e-unencrypted.svg" width="12" height="12" />
|
||||
Enable encryption (warning: cannot be disabled again!)
|
||||
{ _t('Enable encryption') } { _t('(warning: cannot be disabled again!)') }
|
||||
</label>
|
||||
{ settings }
|
||||
</div>
|
||||
|
@ -596,7 +597,7 @@ module.exports = React.createClass({
|
|||
? <img className="mx_RoomSettings_e2eIcon" src="img/e2e-verified.svg" width="10" height="12" />
|
||||
: <img className="mx_RoomSettings_e2eIcon" src="img/e2e-unencrypted.svg" width="12" height="12" />
|
||||
}
|
||||
Encryption is { isEncrypted ? "" : "not " } enabled in this room.
|
||||
{ isEncrypted ? "Encryption is enabled in this room" : "Encryption is not enabled in this room" }.
|
||||
</label>
|
||||
{ settings }
|
||||
</div>
|
||||
|
@ -647,12 +648,12 @@ module.exports = React.createClass({
|
|||
if (Object.keys(user_levels).length) {
|
||||
userLevelsSection =
|
||||
<div>
|
||||
<h3>Privileged Users</h3>
|
||||
<h3>{ _t('Privileged Users') }</h3>
|
||||
<ul className="mx_RoomSettings_userLevels">
|
||||
{Object.keys(user_levels).map(function(user, i) {
|
||||
return (
|
||||
<li className="mx_RoomSettings_userLevel" key={user}>
|
||||
{ user } is a <PowerSelector value={ user_levels[user] } disabled={true}/>
|
||||
{ user } { _t('is a') } <PowerSelector value={ user_levels[user] } disabled={true}/>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
|
@ -660,7 +661,7 @@ module.exports = React.createClass({
|
|||
</div>;
|
||||
}
|
||||
else {
|
||||
userLevelsSection = <div>No users have specific privileges in this room.</div>;
|
||||
userLevelsSection = <div>{ _t('No users have specific privileges in this room') }.</div>;
|
||||
}
|
||||
|
||||
var banned = this.props.room.getMembersWithMembership("ban");
|
||||
|
@ -668,7 +669,7 @@ module.exports = React.createClass({
|
|||
if (banned.length) {
|
||||
bannedUsersSection =
|
||||
<div>
|
||||
<h3>Banned users</h3>
|
||||
<h3>{ _t('Banned users') }</h3>
|
||||
<ul className="mx_RoomSettings_banned">
|
||||
{banned.map(function(member) {
|
||||
return (
|
||||
|
@ -683,7 +684,7 @@ module.exports = React.createClass({
|
|||
if (this._yankValueFromEvent("m.room.create", "m.federate") === false) {
|
||||
unfederatableSection = (
|
||||
<div className="mx_RoomSettings_powerLevel">
|
||||
Ths room is not accessible by remote Matrix servers.
|
||||
{ _t('This room is not accessible by remote Matrix servers') }.
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -694,14 +695,14 @@ module.exports = React.createClass({
|
|||
if (myMember.membership === "join") {
|
||||
leaveButton = (
|
||||
<AccessibleButton className="mx_RoomSettings_leaveButton" onClick={ this.onLeaveClick }>
|
||||
Leave room
|
||||
{ _t('Leave room') }
|
||||
</AccessibleButton>
|
||||
);
|
||||
}
|
||||
else if (myMember.membership === "leave") {
|
||||
leaveButton = (
|
||||
<AccessibleButton className="mx_RoomSettings_leaveButton" onClick={ this.onForgetClick }>
|
||||
Forget room
|
||||
{ _t('Forget room') }
|
||||
</AccessibleButton>
|
||||
);
|
||||
}
|
||||
|
@ -711,8 +712,8 @@ module.exports = React.createClass({
|
|||
// TODO: support editing custom user_levels
|
||||
|
||||
var tags = [
|
||||
{ name: "m.favourite", label: "Favourite", ref: "tag_favourite" },
|
||||
{ name: "m.lowpriority", label: "Low priority", ref: "tag_lowpriority" },
|
||||
{ name: "m.favourite", label: _t('Favourite'), ref: "tag_favourite" },
|
||||
{ name: "m.lowpriority", label: _t('Low priority'), ref: "tag_lowpriority" },
|
||||
];
|
||||
|
||||
Object.keys(this.state.tags).sort().forEach(function(tagName) {
|
||||
|
@ -753,7 +754,7 @@ module.exports = React.createClass({
|
|||
if (this.state.join_rule === "public" && aliasCount == 0) {
|
||||
addressWarning =
|
||||
<div className="mx_RoomSettings_warning">
|
||||
To link to a room it must have <a href="#addresses">an address</a>.
|
||||
{ _t('To link to a room it must have') } <a href="#addresses"> { _t('an address') }</a>.
|
||||
</div>;
|
||||
}
|
||||
|
||||
|
@ -761,10 +762,10 @@ module.exports = React.createClass({
|
|||
if (this.state.join_rule !== "public" && this.state.guest_access === "forbidden") {
|
||||
inviteGuestWarning =
|
||||
<div className="mx_RoomSettings_warning">
|
||||
Guests cannot join this room even if explicitly invited. <a href="#" onClick={ (e) => {
|
||||
{ _t('Guests cannot join this room even if explicitly invited.') } <a href="#" onClick={ (e) => {
|
||||
this.setState({ join_rule: "invite", guest_access: "can_join" });
|
||||
e.preventDefault();
|
||||
}}>Click here to fix</a>.
|
||||
}}>{ _t('Click here to fix') }</a>.
|
||||
</div>;
|
||||
}
|
||||
|
||||
|
@ -776,7 +777,7 @@ module.exports = React.createClass({
|
|||
console.error(this.state.scalar_error);
|
||||
integrationsError = (
|
||||
<span className="mx_RoomSettings_integrationsButton_errorPopup">
|
||||
Could not connect to the integration server
|
||||
{ _t('Could not connect to the integration server') }
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
@ -784,7 +785,7 @@ module.exports = React.createClass({
|
|||
if (this.scalarClient.hasCredentials()) {
|
||||
integrationsButton = (
|
||||
<div className="mx_RoomSettings_integrationsButton" onClick={ this.onManageIntegrations }>
|
||||
Manage Integrations
|
||||
{ _t('Manage Integrations') }
|
||||
</div>
|
||||
);
|
||||
} else if (this.state.scalar_error) {
|
||||
|
@ -797,7 +798,7 @@ module.exports = React.createClass({
|
|||
} else {
|
||||
integrationsButton = (
|
||||
<div className="mx_RoomSettings_integrationsButton" style={{opacity: 0.5}}>
|
||||
Manage Integrations
|
||||
{ _t('Manage Integrations') }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -813,28 +814,28 @@ module.exports = React.createClass({
|
|||
|
||||
<div className="mx_RoomSettings_toggles">
|
||||
<div className="mx_RoomSettings_settings">
|
||||
<h3>Who can access this room?</h3>
|
||||
<h3>{ _t('Who can access this room?') }</h3>
|
||||
{ inviteGuestWarning }
|
||||
<label>
|
||||
<input type="radio" name="roomVis" value="invite_only"
|
||||
disabled={ !this.mayChangeRoomAccess() }
|
||||
onChange={this._onRoomAccessRadioToggle}
|
||||
checked={this.state.join_rule !== "public"}/>
|
||||
Only people who have been invited
|
||||
{ _t('Only people who have been invited') }
|
||||
</label>
|
||||
<label>
|
||||
<input type="radio" name="roomVis" value="public_no_guests"
|
||||
disabled={ !this.mayChangeRoomAccess() }
|
||||
onChange={this._onRoomAccessRadioToggle}
|
||||
checked={this.state.join_rule === "public" && this.state.guest_access !== "can_join"}/>
|
||||
Anyone who knows the room's link, apart from guests
|
||||
{ _t('Anyone who knows the room\'s link, apart from guests') }
|
||||
</label>
|
||||
<label>
|
||||
<input type="radio" name="roomVis" value="public_with_guests"
|
||||
disabled={ !this.mayChangeRoomAccess() }
|
||||
onChange={this._onRoomAccessRadioToggle}
|
||||
checked={this.state.join_rule === "public" && this.state.guest_access === "can_join"}/>
|
||||
Anyone who knows the room's link, including guests
|
||||
{ _t('Anyone who knows the room\'s link, including guests') }
|
||||
</label>
|
||||
{ addressWarning }
|
||||
<br/>
|
||||
|
@ -847,7 +848,7 @@ module.exports = React.createClass({
|
|||
</label>
|
||||
</div>
|
||||
<div className="mx_RoomSettings_settings">
|
||||
<h3>Who can read history?</h3>
|
||||
<h3>{ _t('Who can read history?') }</h3>
|
||||
<label>
|
||||
<input type="radio" name="historyVis" value="world_readable"
|
||||
disabled={ !roomState.mayClientSendStateEvent("m.room.history_visibility", cli) }
|
||||
|
@ -860,28 +861,28 @@ module.exports = React.createClass({
|
|||
disabled={ !roomState.mayClientSendStateEvent("m.room.history_visibility", cli) }
|
||||
checked={historyVisibility === "shared"}
|
||||
onChange={this._onHistoryRadioToggle} />
|
||||
Members only (since the point in time of selecting this option)
|
||||
{ _t('Members only') } ({ _t('since the point in time of selecting this option') })
|
||||
</label>
|
||||
<label>
|
||||
<input type="radio" name="historyVis" value="invited"
|
||||
disabled={ !roomState.mayClientSendStateEvent("m.room.history_visibility", cli) }
|
||||
checked={historyVisibility === "invited"}
|
||||
onChange={this._onHistoryRadioToggle} />
|
||||
Members only (since they were invited)
|
||||
{ _t('Members only') } ({ _t('since they were invited') })
|
||||
</label>
|
||||
<label >
|
||||
<input type="radio" name="historyVis" value="joined"
|
||||
disabled={ !roomState.mayClientSendStateEvent("m.room.history_visibility", cli) }
|
||||
checked={historyVisibility === "joined"}
|
||||
onChange={this._onHistoryRadioToggle} />
|
||||
Members only (since they joined)
|
||||
{ _t('Members only') } ({ _t('since they joined') })
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div>
|
||||
<h3>Room Colour</h3>
|
||||
<h3>{ _t('Room Colour') }</h3>
|
||||
<ColorSettings ref="color_settings" room={this.props.room} />
|
||||
</div>
|
||||
|
||||
|
@ -899,41 +900,41 @@ module.exports = React.createClass({
|
|||
|
||||
<UrlPreviewSettings ref="url_preview_settings" room={this.props.room} />
|
||||
|
||||
<h3>Permissions</h3>
|
||||
<h3>{ _t('Permissions') }</h3>
|
||||
<div className="mx_RoomSettings_powerLevels mx_RoomSettings_settings">
|
||||
<div className="mx_RoomSettings_powerLevel">
|
||||
<span className="mx_RoomSettings_powerLevelKey">The default role for new room members is </span>
|
||||
<span className="mx_RoomSettings_powerLevelKey">{ _t('The default role for new room members is') } </span>
|
||||
<PowerSelector ref="users_default" value={default_user_level} controlled={false} disabled={!can_change_levels || current_user_level < default_user_level} onChange={this.onPowerLevelsChanged}/>
|
||||
</div>
|
||||
<div className="mx_RoomSettings_powerLevel">
|
||||
<span className="mx_RoomSettings_powerLevelKey">To send messages, you must be a </span>
|
||||
<span className="mx_RoomSettings_powerLevelKey">{ _t('To send messages') }, { _t('you must be a') } </span>
|
||||
<PowerSelector ref="events_default" value={send_level} controlled={false} disabled={!can_change_levels || current_user_level < send_level} onChange={this.onPowerLevelsChanged}/>
|
||||
</div>
|
||||
<div className="mx_RoomSettings_powerLevel">
|
||||
<span className="mx_RoomSettings_powerLevelKey">To invite users into the room, you must be a </span>
|
||||
<span className="mx_RoomSettings_powerLevelKey">{ _t('To invite users into the room') }, { _t('you must be a') } </span>
|
||||
<PowerSelector ref="invite" value={invite_level} controlled={false} disabled={!can_change_levels || current_user_level < invite_level} onChange={this.onPowerLevelsChanged}/>
|
||||
</div>
|
||||
<div className="mx_RoomSettings_powerLevel">
|
||||
<span className="mx_RoomSettings_powerLevelKey">To configure the room, you must be a </span>
|
||||
<span className="mx_RoomSettings_powerLevelKey">{ _t('To configure the room') }, { _t('you must be a') } </span>
|
||||
<PowerSelector ref="state_default" value={state_level} controlled={false} disabled={!can_change_levels || current_user_level < state_level} onChange={this.onPowerLevelsChanged}/>
|
||||
</div>
|
||||
<div className="mx_RoomSettings_powerLevel">
|
||||
<span className="mx_RoomSettings_powerLevelKey">To kick users, you must be a </span>
|
||||
<span className="mx_RoomSettings_powerLevelKey">{ _t('To kick users') }, { _t('you must be a') } </span>
|
||||
<PowerSelector ref="kick" value={kick_level} controlled={false} disabled={!can_change_levels || current_user_level < kick_level} onChange={this.onPowerLevelsChanged}/>
|
||||
</div>
|
||||
<div className="mx_RoomSettings_powerLevel">
|
||||
<span className="mx_RoomSettings_powerLevelKey">To ban users, you must be a </span>
|
||||
<span className="mx_RoomSettings_powerLevelKey">{ _t('To ban users') }, { _t('you must be a') } </span>
|
||||
<PowerSelector ref="ban" value={ban_level} controlled={false} disabled={!can_change_levels || current_user_level < ban_level} onChange={this.onPowerLevelsChanged}/>
|
||||
</div>
|
||||
<div className="mx_RoomSettings_powerLevel">
|
||||
<span className="mx_RoomSettings_powerLevelKey">To redact other users' messages, you must be a </span>
|
||||
<span className="mx_RoomSettings_powerLevelKey">{ _t('To redact other users\' messages') }, { _t('you must be a') } </span>
|
||||
<PowerSelector ref="redact" value={redact_level} controlled={false} disabled={!can_change_levels || current_user_level < redact_level} onChange={this.onPowerLevelsChanged}/>
|
||||
</div>
|
||||
|
||||
{Object.keys(events_levels).map(function(event_type, i) {
|
||||
return (
|
||||
<div className="mx_RoomSettings_powerLevel" key={event_type}>
|
||||
<span className="mx_RoomSettings_powerLevelKey">To send events of type <code>{ event_type }</code>, you must be a </span>
|
||||
<span className="mx_RoomSettings_powerLevelKey">{ _t('To send events of type') } <code>{ event_type }</code>, { _t('you must be a') } </span>
|
||||
<PowerSelector value={ events_levels[event_type] } controlled={false} disabled={true} onChange={self.onPowerLevelsChanged}/>
|
||||
</div>
|
||||
);
|
||||
|
@ -946,9 +947,9 @@ module.exports = React.createClass({
|
|||
|
||||
{ bannedUsersSection }
|
||||
|
||||
<h3>Advanced</h3>
|
||||
<h3>{ _t('Advanced') }</h3>
|
||||
<div className="mx_RoomSettings_settings">
|
||||
This room's internal ID is <code>{ this.props.room.roomId }</code>
|
||||
{ _t('This room\'s internal ID is') } <code>{ this.props.room.roomId }</code>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -17,6 +17,7 @@ var React = require('react');
|
|||
var MatrixClientPeg = require("../../../MatrixClientPeg");
|
||||
var Modal = require("../../../Modal");
|
||||
var sdk = require("../../../index");
|
||||
import { _t } from '../../../languageHandler';
|
||||
var GeminiScrollbar = require('react-gemini-scrollbar');
|
||||
|
||||
// A list capable of displaying entities which conform to the SearchableEntity
|
||||
|
@ -25,7 +26,6 @@ var SearchableEntityList = React.createClass({
|
|||
displayName: 'SearchableEntityList',
|
||||
|
||||
propTypes: {
|
||||
searchPlaceholderText: React.PropTypes.string,
|
||||
emptyQueryShowsAll: React.PropTypes.bool,
|
||||
showInputBox: React.PropTypes.bool,
|
||||
onQueryChanged: React.PropTypes.func, // fn(inputText)
|
||||
|
@ -37,7 +37,6 @@ var SearchableEntityList = React.createClass({
|
|||
getDefaultProps: function() {
|
||||
return {
|
||||
showInputBox: true,
|
||||
searchPlaceholderText: "Search",
|
||||
entities: [],
|
||||
emptyQueryShowsAll: false,
|
||||
onSubmit: function() {},
|
||||
|
@ -118,7 +117,9 @@ var SearchableEntityList = React.createClass({
|
|||
_createOverflowEntity: function(overflowCount, totalCount) {
|
||||
var EntityTile = sdk.getComponent("rooms.EntityTile");
|
||||
var BaseAvatar = sdk.getComponent("avatars.BaseAvatar");
|
||||
var text = "and " + overflowCount + " other" + (overflowCount > 1 ? "s" : "") + "...";
|
||||
var text = (overflowCount > 1)
|
||||
? _t("and %(overflowCount)s others...", { overflowCount: overflowCount })
|
||||
: _t("and one other...");
|
||||
return (
|
||||
<EntityTile className="mx_EntityTile_ellipsis" avatarJsx={
|
||||
<BaseAvatar url="img/ellipsis.svg" name="..." width={36} height={36} />
|
||||
|
@ -137,7 +138,7 @@ var SearchableEntityList = React.createClass({
|
|||
onChange={this.onQueryChanged} value={this.state.query}
|
||||
onFocus= {() => { this.setState({ focused: true }); }}
|
||||
onBlur= {() => { this.setState({ focused: false }); }}
|
||||
placeholder={this.props.searchPlaceholderText} />
|
||||
placeholder={ _t("Search") } />
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ limitations under the License.
|
|||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
import { _t } from '../../../languageHandler';
|
||||
var sdk = require('../../../index');
|
||||
|
||||
module.exports = React.createClass({
|
||||
|
@ -34,8 +35,8 @@ module.exports = React.createClass({
|
|||
<div className="mx_TopUnreadMessagesBar_scrollUp"
|
||||
onClick={this.props.onScrollUpClick}>
|
||||
<img src="img/scrollto.svg" width="24" height="24"
|
||||
alt="Scroll to unread messages"
|
||||
title="Scroll to unread messages"/>
|
||||
alt={ _t('Scroll to unread messages') }
|
||||
title={ _t('Scroll to unread messages') }/>
|
||||
Jump to first unread message.
|
||||
</div>
|
||||
<img className="mx_TopUnreadMessagesBar_close mx_filterFlipColor"
|
||||
|
@ -46,4 +47,3 @@ module.exports = React.createClass({
|
|||
);
|
||||
},
|
||||
});
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue