Merge branch 'develop' into new-guest-access
This commit is contained in:
commit
5c885922d9
90 changed files with 5814 additions and 831 deletions
|
@ -93,7 +93,7 @@ export default class DirectorySearchBox extends React.Component {
|
|||
className="mx_DirectorySearchBox_input"
|
||||
ref={this._collectInput}
|
||||
onChange={this._onChange} onKeyUp={this._onKeyUp}
|
||||
placeholder={this.props.placeholder}
|
||||
placeholder={this.props.placeholder} autoFocus
|
||||
/>
|
||||
{join_button}
|
||||
<span className="mx_DirectorySearchBox_clear_wrapper">
|
||||
|
|
128
src/components/views/elements/LanguageDropdown.js
Normal file
128
src/components/views/elements/LanguageDropdown.js
Normal file
|
@ -0,0 +1,128 @@
|
|||
/*
|
||||
Copyright 2017 Marcel Radzio (MTRNord)
|
||||
Copyright 2017 Vector Creations Ltd.
|
||||
|
||||
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 sdk from '../../../index';
|
||||
import UserSettingsStore from '../../../UserSettingsStore';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import * as languageHandler from '../../../languageHandler';
|
||||
|
||||
function languageMatchesSearchQuery(query, language) {
|
||||
if (language.label.toUpperCase().indexOf(query.toUpperCase()) == 0) return true;
|
||||
if (language.value.toUpperCase() == query.toUpperCase()) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
export default class LanguageDropdown extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this._onSearchChange = this._onSearchChange.bind(this);
|
||||
|
||||
this.state = {
|
||||
searchQuery: '',
|
||||
langs: null,
|
||||
}
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
languageHandler.getAllLanguageKeysFromJson().then((langKeys) => {
|
||||
const langs = [];
|
||||
langKeys.forEach((languageKey) => {
|
||||
langs.push({
|
||||
value: languageKey,
|
||||
label: _t(languageKey)
|
||||
});
|
||||
});
|
||||
langs.sort(function(a, b){
|
||||
if(a.label < b.label) return -1;
|
||||
if(a.label > b.label) return 1;
|
||||
return 0;
|
||||
});
|
||||
this.setState({langs});
|
||||
}).catch(() => {
|
||||
this.setState({langs: ['en']});
|
||||
}).done();
|
||||
|
||||
if (!this.props.value) {
|
||||
// If no value is given, we start with the first
|
||||
// country selected, but our parent component
|
||||
// doesn't know this, therefore we do this.
|
||||
const _localSettings = UserSettingsStore.getLocalSettings();
|
||||
if (_localSettings.hasOwnProperty('language')) {
|
||||
this.props.onOptionChange(_localSettings.language);
|
||||
}else {
|
||||
const language = languageHandler.normalizeLanguageKey(languageHandler.getLanguageFromBrowser());
|
||||
this.props.onOptionChange(language);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_onSearchChange(search) {
|
||||
this.setState({
|
||||
searchQuery: search,
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.state.langs === null) {
|
||||
const Spinner = sdk.getComponent('elements.Spinner');
|
||||
return <Spinner />;
|
||||
}
|
||||
|
||||
const Dropdown = sdk.getComponent('elements.Dropdown');
|
||||
|
||||
let displayedLanguages;
|
||||
if (this.state.searchQuery) {
|
||||
displayedLanguages = this.state.langs.filter((lang) => {
|
||||
return languageMatchesSearchQuery(this.state.searchQuery, lang);
|
||||
});
|
||||
} else {
|
||||
displayedLanguages = this.state.langs;
|
||||
}
|
||||
|
||||
const options = displayedLanguages.map((language) => {
|
||||
return <div key={language.value}>
|
||||
{language.label}
|
||||
</div>;
|
||||
});
|
||||
|
||||
// default value here too, otherwise we need to handle null / undefined
|
||||
// values between mounting and the initial value propgating
|
||||
let value = null;
|
||||
const _localSettings = UserSettingsStore.getLocalSettings();
|
||||
if (_localSettings.hasOwnProperty('language')) {
|
||||
value = this.props.value || _localSettings.language;
|
||||
} else {
|
||||
const language = navigator.language || navigator.userLanguage;
|
||||
value = this.props.value || language;
|
||||
}
|
||||
|
||||
return <Dropdown className={this.props.className}
|
||||
onOptionChange={this.props.onOptionChange} onSearchChange={this._onSearchChange}
|
||||
searchEnabled={true} value={value}
|
||||
>
|
||||
{options}
|
||||
</Dropdown>
|
||||
}
|
||||
}
|
||||
|
||||
LanguageDropdown.propTypes = {
|
||||
className: React.PropTypes.string,
|
||||
onOptionChange: React.PropTypes.func.isRequired,
|
||||
value: React.PropTypes.string,
|
||||
};
|
|
@ -15,6 +15,7 @@ limitations under the License.
|
|||
*/
|
||||
import React from 'react';
|
||||
const MemberAvatar = require('../avatars/MemberAvatar.js');
|
||||
import { _t } from '../../../languageHandler';
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'MemberEventListSummary',
|
||||
|
@ -203,30 +204,146 @@ module.exports = React.createClass({
|
|||
* @param {boolean} plural whether there were multiple users undergoing the same
|
||||
* transition.
|
||||
* @param {number} repeats the number of times the transition was repeated in a row.
|
||||
* @returns {string} the written English equivalent of the transition.
|
||||
* @returns {string} the written Human Readable equivalent of the transition.
|
||||
*/
|
||||
_getDescriptionForTransition(t, plural, repeats) {
|
||||
const beConjugated = plural ? "were" : "was";
|
||||
const invitation = "their invitation" + (plural || (repeats > 1) ? "s" : "");
|
||||
|
||||
// The empty interpolations 'severalUsers' and 'oneUser'
|
||||
// are there only to show translators to non-English languages
|
||||
// that the verb is conjugated to plural or singular Subject.
|
||||
let res = null;
|
||||
const map = {
|
||||
"joined": "joined",
|
||||
"left": "left",
|
||||
"joined_and_left": "joined and left",
|
||||
"left_and_joined": "left and rejoined",
|
||||
"invite_reject": "rejected " + invitation,
|
||||
"invite_withdrawal": "had " + invitation + " withdrawn",
|
||||
"invited": beConjugated + " invited",
|
||||
"banned": beConjugated + " banned",
|
||||
"unbanned": beConjugated + " unbanned",
|
||||
"kicked": beConjugated + " kicked",
|
||||
"changed_name": "changed name",
|
||||
"changed_avatar": "changed avatar",
|
||||
};
|
||||
switch(t) {
|
||||
case "joined":
|
||||
if (repeats > 1) {
|
||||
res = (plural)
|
||||
? _t("%(severalUsers)sjoined %(repeats)s times", { severalUsers: "", repeats: repeats })
|
||||
: _t("%(oneUser)sjoined %(repeats)s times", { oneUser: "", repeats: repeats });
|
||||
} else {
|
||||
res = (plural)
|
||||
? _t("%(severalUsers)sjoined", { severalUsers: "" })
|
||||
: _t("%(oneUser)sjoined", { oneUser: "" });
|
||||
}
|
||||
|
||||
if (Object.keys(map).includes(t)) {
|
||||
res = map[t] + (repeats > 1 ? " " + repeats + " times" : "" );
|
||||
break;
|
||||
case "left":
|
||||
if (repeats > 1) {
|
||||
res = (plural)
|
||||
? _t("%(severalUsers)sleft %(repeats)s times", { severalUsers: "", repeats: repeats })
|
||||
: _t("%(oneUser)sleft %(repeats)s times", { oneUser: "", repeats: repeats });
|
||||
} else {
|
||||
res = (plural)
|
||||
? _t("%(severalUsers)sleft", { severalUsers: "" })
|
||||
: _t("%(oneUser)sleft", { oneUser: "" });
|
||||
} break;
|
||||
case "joined_and_left":
|
||||
if (repeats > 1) {
|
||||
res = (plural)
|
||||
? _t("%(severalUsers)sjoined and left %(repeats)s times", { severalUsers: "", repeats: repeats })
|
||||
: _t("%(oneUser)sjoined and left %(repeats)s times", { oneUser: "", repeats: repeats });
|
||||
} else {
|
||||
res = (plural)
|
||||
? _t("%(severalUsers)sjoined and left", { severalUsers: "" })
|
||||
: _t("%(oneUser)sjoined and left", { oneUser: "" });
|
||||
}
|
||||
break;
|
||||
case "left_and_joined":
|
||||
if (repeats > 1) {
|
||||
res = (plural)
|
||||
? _t("%(severalUsers)sleft and rejoined %(repeats)s times", { severalUsers: "", repeats: repeats })
|
||||
: _t("%(oneUser)sleft and rejoined %(repeats)s times", { oneUser: "", repeats: repeats });
|
||||
} else {
|
||||
res = (plural)
|
||||
? _t("%(severalUsers)sleft and rejoined", { severalUsers: "" })
|
||||
: _t("%(oneUser)sleft and rejoined", { oneUser: "" });
|
||||
} break;
|
||||
break;
|
||||
case "invite_reject":
|
||||
if (repeats > 1) {
|
||||
res = (plural)
|
||||
? _t("%(severalUsers)srejected their invitations %(repeats)s times", { severalUsers: "", repeats: repeats })
|
||||
: _t("%(oneUser)srejected their invitation %(repeats)s times", { oneUser: "", repeats: repeats });
|
||||
} else {
|
||||
res = (plural)
|
||||
? _t("%(severalUsers)srejected their invitations", { severalUsers: "" })
|
||||
: _t("%(oneUser)srejected their invitation", { oneUser: "" });
|
||||
}
|
||||
break;
|
||||
case "invite_withdrawal":
|
||||
if (repeats > 1) {
|
||||
res = (plural)
|
||||
? _t("%(severalUsers)shad their invitations withdrawn %(repeats)s times", { severalUsers: "", repeats: repeats })
|
||||
: _t("%(oneUser)shad their invitation withdrawn %(repeats)s times", { oneUser: "", repeats: repeats });
|
||||
} else {
|
||||
res = (plural)
|
||||
? _t("%(severalUsers)shad their invitations withdrawn", { severalUsers: "" })
|
||||
: _t("%(oneUser)shad their invitation withdrawn", { oneUser: "" });
|
||||
}
|
||||
break;
|
||||
case "invited":
|
||||
if (repeats > 1) {
|
||||
res = (plural)
|
||||
? _t("were invited %(repeats)s times", { repeats: repeats })
|
||||
: _t("was invited %(repeats)s times", { repeats: repeats });
|
||||
} else {
|
||||
res = (plural)
|
||||
? _t("were invited")
|
||||
: _t("was invited");
|
||||
}
|
||||
break;
|
||||
case "banned":
|
||||
if (repeats > 1) {
|
||||
res = (plural)
|
||||
? _t("were banned %(repeats)s times", { repeats: repeats })
|
||||
: _t("was banned %(repeats)s times", { repeats: repeats });
|
||||
} else {
|
||||
res = (plural)
|
||||
? _t("were banned")
|
||||
: _t("was banned");
|
||||
}
|
||||
break;
|
||||
case "unbanned":
|
||||
if (repeats > 1) {
|
||||
res = (plural)
|
||||
? _t("were unbanned %(repeats)s times", { repeats: repeats })
|
||||
: _t("was unbanned %(repeats)s times", { repeats: repeats });
|
||||
} else {
|
||||
res = (plural)
|
||||
? _t("were unbanned")
|
||||
: _t("was unbanned");
|
||||
}
|
||||
break;
|
||||
case "kicked":
|
||||
if (repeats > 1) {
|
||||
res = (plural)
|
||||
? _t("were kicked %(repeats)s times", { repeats: repeats })
|
||||
: _t("was kicked %(repeats)s times", { repeats: repeats });
|
||||
} else {
|
||||
res = (plural)
|
||||
? _t("were kicked")
|
||||
: _t("was kicked");
|
||||
}
|
||||
break;
|
||||
case "changed_name":
|
||||
if (repeats > 1) {
|
||||
res = (plural)
|
||||
? _t("%(severalUsers)schanged their name %(repeats)s times", { severalUsers: "", repeats: repeats })
|
||||
: _t("%(oneUser)schanged their name %(repeats)s times", { oneUser: "", repeats: repeats });
|
||||
} else {
|
||||
res = (plural)
|
||||
? _t("%(severalUsers)schanged their name", { severalUsers: "" })
|
||||
: _t("%(oneUser)schanged their name", { oneUser: "" });
|
||||
}
|
||||
break;
|
||||
case "changed_avatar":
|
||||
if (repeats > 1) {
|
||||
res = (plural)
|
||||
? _t("%(severalUsers)schanged their avatar %(repeats)s times", { severalUsers: "", repeats: repeats })
|
||||
: _t("%(oneUser)schanged their avatar %(repeats)s times", { oneUser: "", repeats: repeats });
|
||||
} else {
|
||||
res = (plural)
|
||||
? _t("%(severalUsers)schanged their avatar", { severalUsers: "" })
|
||||
: _t("%(oneUser)schanged their avatar", { oneUser: "" });
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
|
@ -254,11 +371,12 @@ module.exports = React.createClass({
|
|||
return items[0];
|
||||
} else if (remaining) {
|
||||
items = items.slice(0, itemLimit);
|
||||
const other = " other" + (remaining > 1 ? "s" : "");
|
||||
return items.join(', ') + ' and ' + remaining + other;
|
||||
return (remaining > 1)
|
||||
? _t("%(items)s and %(remaining)s others", { items: items.join(', '), remaining: remaining } )
|
||||
: _t("%(items)s and one other", { items: items.join(', ') });
|
||||
} else {
|
||||
const lastItem = items.pop();
|
||||
return items.join(', ') + ' and ' + lastItem;
|
||||
return _t("%(items)s and %(lastItem)s", { items: items.join(', '), lastItem: lastItem });
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -19,10 +19,8 @@ limitations under the License.
|
|||
import React from 'react';
|
||||
import * as Roles from '../../../Roles';
|
||||
|
||||
var LEVEL_ROLE_MAP = {};
|
||||
var reverseRoles = {};
|
||||
Object.keys(Roles.LEVEL_ROLE_MAP).forEach(function(key) {
|
||||
reverseRoles[Roles.LEVEL_ROLE_MAP[key]] = key;
|
||||
});
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'PowerSelector',
|
||||
|
@ -44,9 +42,16 @@ module.exports = React.createClass({
|
|||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
custom: (Roles.LEVEL_ROLE_MAP[this.props.value] === undefined),
|
||||
custom: (LEVEL_ROLE_MAP[this.props.value] === undefined),
|
||||
};
|
||||
},
|
||||
|
||||
componentWillMount: function() {
|
||||
LEVEL_ROLE_MAP = Roles.levelRoleMap();
|
||||
Object.keys(LEVEL_ROLE_MAP).forEach(function(key) {
|
||||
reverseRoles[LEVEL_ROLE_MAP[key]] = key;
|
||||
});
|
||||
},
|
||||
|
||||
onSelectChange: function(event) {
|
||||
this.setState({ custom: event.target.value === "Custom" });
|
||||
|
@ -94,7 +99,7 @@ module.exports = React.createClass({
|
|||
selectValue = "Custom";
|
||||
}
|
||||
else {
|
||||
selectValue = Roles.LEVEL_ROLE_MAP[this.props.value] || "Custom";
|
||||
selectValue = LEVEL_ROLE_MAP[this.props.value] || "Custom";
|
||||
}
|
||||
var select;
|
||||
if (this.props.disabled) {
|
||||
|
@ -105,7 +110,7 @@ module.exports = React.createClass({
|
|||
const levels = [0, 50, 100];
|
||||
let options = levels.map((level) => {
|
||||
return {
|
||||
value: Roles.LEVEL_ROLE_MAP[level],
|
||||
value: LEVEL_ROLE_MAP[level],
|
||||
// Give a userDefault (users_default in the power event) of 0 but
|
||||
// because level !== undefined, this should never be used.
|
||||
text: Roles.textualPowerLevel(level, 0),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue