Merge remote-tracking branch 'upstream/develop' into hs/upload-limits
This commit is contained in:
commit
2b077b4f5d
142 changed files with 5235 additions and 671 deletions
|
@ -33,7 +33,6 @@ import Autocompleter from '../../../autocomplete/Autocompleter';
|
|||
const COMPOSER_SELECTED = 0;
|
||||
|
||||
export default class Autocomplete extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
|
|
|
@ -416,11 +416,10 @@ module.exports = withMatrixClient(React.createClass({
|
|||
onCryptoClicked: function(e) {
|
||||
const event = this.props.mxEvent;
|
||||
|
||||
Modal.createTrackedDialogAsync('Encrypted Event Dialog', '', (cb) => {
|
||||
require(['../../../async-components/views/dialogs/EncryptedEventDialog'], cb);
|
||||
}, {
|
||||
event: event,
|
||||
});
|
||||
Modal.createTrackedDialogAsync('Encrypted Event Dialog', '',
|
||||
import('../../../async-components/views/dialogs/EncryptedEventDialog'),
|
||||
{event},
|
||||
);
|
||||
},
|
||||
|
||||
onRequestKeysClick: function() {
|
||||
|
|
|
@ -107,7 +107,7 @@ module.exports = React.createClass({
|
|||
|
||||
// FIXME: do we want to factor out all image displaying between this and MImageBody - especially for lightboxing?
|
||||
let image = p["og:image"];
|
||||
let imageMaxWidth = 100, imageMaxHeight = 100;
|
||||
const imageMaxWidth = 100; const imageMaxHeight = 100;
|
||||
if (image && image.startsWith("mxc://")) {
|
||||
image = MatrixClientPeg.get().mxcUrlToHttp(image, imageMaxWidth, imageMaxHeight);
|
||||
}
|
||||
|
|
|
@ -712,7 +712,7 @@ module.exports = withMatrixClient(React.createClass({
|
|||
|
||||
if (!member || !member.membership || member.membership === 'leave') {
|
||||
const roomId = member && member.roomId ? member.roomId : RoomViewStore.getRoomId();
|
||||
const onInviteUserButton = async () => {
|
||||
const onInviteUserButton = async() => {
|
||||
try {
|
||||
await cli.invite(roomId, member.userId);
|
||||
} catch (err) {
|
||||
|
|
|
@ -447,7 +447,7 @@ module.exports = React.createClass({
|
|||
return (
|
||||
<div className="mx_MemberList">
|
||||
{ inputBox }
|
||||
<GeminiScrollbarWrapper autoshow={true} className="mx_MemberList_joined mx_MemberList_outerWrapper">
|
||||
<GeminiScrollbarWrapper autoshow={true} className="mx_MemberList_joined">
|
||||
<TruncatedList className="mx_MemberList_wrapper" truncateAt={this.state.truncateAtJoined}
|
||||
createOverflowElement={this._createOverflowTileJoined}
|
||||
getChildren={this._getChildrenJoined}
|
||||
|
|
|
@ -305,7 +305,7 @@ export default class MessageComposer extends React.Component {
|
|||
);
|
||||
}
|
||||
|
||||
let e2eImg, e2eTitle, e2eClass;
|
||||
let e2eImg; let e2eTitle; let e2eClass;
|
||||
const roomIsEncrypted = MatrixClientPeg.get().isRoomEncrypted(this.props.room.roomId);
|
||||
if (roomIsEncrypted) {
|
||||
// FIXME: show a /!\ if there are untrusted devices in the room...
|
||||
|
@ -465,7 +465,7 @@ export default class MessageComposer extends React.Component {
|
|||
className="mx_MessageComposer_formatbar_cancel mx_filterFlipColor"
|
||||
src="img/icon-text-cancel.svg" />
|
||||
</div>
|
||||
</div>
|
||||
</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
|
@ -67,7 +67,7 @@ const EMOJI_UNICODE_TO_SHORTNAME = mapUnicodeToShort();
|
|||
const REGEX_EMOJI_WHITESPACE = new RegExp('(?:^|\\s)(' + asciiRegexp + ')\\s$');
|
||||
const EMOJI_REGEX = new RegExp(unicodeRegexp, 'g');
|
||||
|
||||
const TYPING_USER_TIMEOUT = 10000, TYPING_SERVER_TIMEOUT = 30000;
|
||||
const TYPING_USER_TIMEOUT = 10000; const TYPING_SERVER_TIMEOUT = 30000;
|
||||
|
||||
const ENTITY_TYPES = {
|
||||
AT_ROOM_PILL: 'ATROOMPILL',
|
||||
|
@ -175,8 +175,8 @@ export default class MessageComposerInput extends React.Component {
|
|||
// see https://github.com/ianstormtaylor/slate/issues/762#issuecomment-304855095
|
||||
this.direction = '';
|
||||
|
||||
this.plainWithMdPills = new PlainWithPillsSerializer({ pillFormat: 'md' });
|
||||
this.plainWithIdPills = new PlainWithPillsSerializer({ pillFormat: 'id' });
|
||||
this.plainWithMdPills = new PlainWithPillsSerializer({ pillFormat: 'md' });
|
||||
this.plainWithIdPills = new PlainWithPillsSerializer({ pillFormat: 'id' });
|
||||
this.plainWithPlainPills = new PlainWithPillsSerializer({ pillFormat: 'plain' });
|
||||
|
||||
this.md = new Md({
|
||||
|
@ -544,7 +544,7 @@ export default class MessageComposerInput extends React.Component {
|
|||
|
||||
if (editorState.startText !== null) {
|
||||
const text = editorState.startText.text;
|
||||
const currentStartOffset = editorState.startOffset;
|
||||
const currentStartOffset = editorState.selection.start.offset;
|
||||
|
||||
// Automatic replacement of plaintext emoji to Unicode emoji
|
||||
if (SettingsStore.getValue('MessageComposerInput.autoReplaceEmoji')) {
|
||||
|
@ -558,11 +558,11 @@ export default class MessageComposerInput extends React.Component {
|
|||
|
||||
const range = Range.create({
|
||||
anchor: {
|
||||
key: editorState.selection.startKey,
|
||||
key: editorState.startText.key,
|
||||
offset: currentStartOffset - emojiMatch[1].length - 1,
|
||||
},
|
||||
focus: {
|
||||
key: editorState.selection.startKey,
|
||||
key: editorState.startText.key,
|
||||
offset: currentStartOffset - 1,
|
||||
},
|
||||
});
|
||||
|
@ -573,29 +573,42 @@ export default class MessageComposerInput extends React.Component {
|
|||
}
|
||||
|
||||
// emojioneify any emoji
|
||||
editorState.document.getTexts().forEach(node => {
|
||||
if (node.text !== '' && HtmlUtils.containsEmoji(node.text)) {
|
||||
let match;
|
||||
while ((match = EMOJI_REGEX.exec(node.text)) !== null) {
|
||||
const range = Range.create({
|
||||
anchor: {
|
||||
key: node.key,
|
||||
offset: match.index,
|
||||
},
|
||||
focus: {
|
||||
key: node.key,
|
||||
offset: match.index + match[0].length,
|
||||
},
|
||||
});
|
||||
const inline = Inline.create({
|
||||
type: 'emoji',
|
||||
data: { emojiUnicode: match[0] },
|
||||
});
|
||||
change = change.insertInlineAtRange(range, inline);
|
||||
editorState = change.value;
|
||||
let foundEmoji;
|
||||
do {
|
||||
foundEmoji = false;
|
||||
|
||||
for (const node of editorState.document.getTexts()) {
|
||||
if (node.text !== '' && HtmlUtils.containsEmoji(node.text)) {
|
||||
let match;
|
||||
EMOJI_REGEX.lastIndex = 0;
|
||||
while ((match = EMOJI_REGEX.exec(node.text)) !== null) {
|
||||
const range = Range.create({
|
||||
anchor: {
|
||||
key: node.key,
|
||||
offset: match.index,
|
||||
},
|
||||
focus: {
|
||||
key: node.key,
|
||||
offset: match.index + match[0].length,
|
||||
},
|
||||
});
|
||||
const inline = Inline.create({
|
||||
type: 'emoji',
|
||||
data: { emojiUnicode: match[0] },
|
||||
});
|
||||
change = change.insertInlineAtRange(range, inline);
|
||||
editorState = change.value;
|
||||
|
||||
// if we replaced an emoji, start again looking for more
|
||||
// emoji in the new editor state since doing the replacement
|
||||
// will change the node structure & offsets so we can't compute
|
||||
// insertion ranges from node.key / match.index anymore.
|
||||
foundEmoji = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} while (foundEmoji);
|
||||
|
||||
// work around weird bug where inserting emoji via the macOS
|
||||
// emoji picker can leave the selection stuck in the emoji's
|
||||
|
@ -1065,7 +1078,7 @@ export default class MessageComposerInput extends React.Component {
|
|||
|
||||
// only look for commands if the first block contains simple unformatted text
|
||||
// i.e. no pills or rich-text formatting and begins with a /.
|
||||
let cmd, commandText;
|
||||
let cmd; let commandText;
|
||||
const firstChild = editorState.document.nodes.get(0);
|
||||
const firstGrandChild = firstChild && firstChild.nodes.get(0);
|
||||
if (firstChild && firstGrandChild &&
|
||||
|
@ -1247,7 +1260,7 @@ export default class MessageComposerInput extends React.Component {
|
|||
}
|
||||
};
|
||||
|
||||
selectHistory = async (up) => {
|
||||
selectHistory = async(up) => {
|
||||
const delta = up ? -1 : 1;
|
||||
|
||||
// True if we are not currently selecting history, but composing a message
|
||||
|
@ -1295,7 +1308,7 @@ export default class MessageComposerInput extends React.Component {
|
|||
return true;
|
||||
};
|
||||
|
||||
onTab = async (e) => {
|
||||
onTab = async(e) => {
|
||||
this.setState({
|
||||
someCompletions: null,
|
||||
});
|
||||
|
@ -1317,7 +1330,7 @@ export default class MessageComposerInput extends React.Component {
|
|||
up ? this.autocomplete.onUpArrow() : this.autocomplete.onDownArrow();
|
||||
};
|
||||
|
||||
onEscape = async (e) => {
|
||||
onEscape = async(e) => {
|
||||
e.preventDefault();
|
||||
if (this.autocomplete) {
|
||||
this.autocomplete.onEscape(e);
|
||||
|
@ -1336,7 +1349,7 @@ export default class MessageComposerInput extends React.Component {
|
|||
/* If passed null, restores the original editor content from state.originalEditorState.
|
||||
* If passed a non-null displayedCompletion, modifies state.originalEditorState to compute new state.editorState.
|
||||
*/
|
||||
setDisplayedCompletion = async (displayedCompletion: ?Completion): boolean => {
|
||||
setDisplayedCompletion = async(displayedCompletion: ?Completion): boolean => {
|
||||
const activeEditorState = this.state.originalEditorState || this.state.editorState;
|
||||
|
||||
if (displayedCompletion == null) {
|
||||
|
|
|
@ -44,9 +44,13 @@ module.exports = React.createClass({
|
|||
error: PropTypes.object,
|
||||
|
||||
canPreview: PropTypes.bool,
|
||||
spinner: PropTypes.bool,
|
||||
room: PropTypes.object,
|
||||
|
||||
// When a spinner is present, a spinnerState can be specified to indicate the
|
||||
// purpose of the spinner.
|
||||
spinner: PropTypes.bool,
|
||||
spinnerState: PropTypes.oneOf(["joining"]),
|
||||
|
||||
// The alias that was used to access this room, if appropriate
|
||||
// If given, this will be how the room is referred to (eg.
|
||||
// in error messages).
|
||||
|
@ -89,11 +93,16 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
render: function() {
|
||||
let joinBlock, previewBlock;
|
||||
let joinBlock; let previewBlock;
|
||||
|
||||
if (this.props.spinner || this.state.busy) {
|
||||
const Spinner = sdk.getComponent("elements.Spinner");
|
||||
let spinnerIntro = "";
|
||||
if (this.props.spinnerState === "joining") {
|
||||
spinnerIntro = _t("Joining room...");
|
||||
}
|
||||
return (<div className="mx_RoomPreviewBar">
|
||||
<p className="mx_RoomPreviewBar_spinnerIntro">{ spinnerIntro }</p>
|
||||
<Spinner />
|
||||
</div>);
|
||||
}
|
||||
|
|
|
@ -590,6 +590,11 @@ module.exports = React.createClass({
|
|||
}
|
||||
},
|
||||
|
||||
_openDevtools: function() {
|
||||
const DevtoolsDialog = sdk.getComponent('dialogs.DevtoolsDialog');
|
||||
Modal.createDialog(DevtoolsDialog, {roomId: this.props.room.roomId});
|
||||
},
|
||||
|
||||
_renderEncryptionSection: function() {
|
||||
const SettingsFlag = sdk.getComponent("elements.SettingsFlag");
|
||||
|
||||
|
@ -652,31 +657,31 @@ module.exports = React.createClass({
|
|||
const userLevels = powerLevels.users || {};
|
||||
|
||||
const powerLevelDescriptors = {
|
||||
users_default: {
|
||||
"users_default": {
|
||||
desc: _t('The default role for new room members is'),
|
||||
defaultValue: 0,
|
||||
},
|
||||
events_default: {
|
||||
"events_default": {
|
||||
desc: _t('To send messages, you must be a'),
|
||||
defaultValue: 0,
|
||||
},
|
||||
invite: {
|
||||
"invite": {
|
||||
desc: _t('To invite users into the room, you must be a'),
|
||||
defaultValue: 50,
|
||||
},
|
||||
state_default: {
|
||||
"state_default": {
|
||||
desc: _t('To configure the room, you must be a'),
|
||||
defaultValue: 50,
|
||||
},
|
||||
kick: {
|
||||
"kick": {
|
||||
desc: _t('To kick users, you must be a'),
|
||||
defaultValue: 50,
|
||||
},
|
||||
ban: {
|
||||
"ban": {
|
||||
desc: _t('To ban users, you must be a'),
|
||||
defaultValue: 50,
|
||||
},
|
||||
redact: {
|
||||
"redact": {
|
||||
desc: _t('To remove other users\' messages, you must be a'),
|
||||
defaultValue: 50,
|
||||
},
|
||||
|
@ -942,6 +947,11 @@ module.exports = React.createClass({
|
|||
</AccessibleButton>;
|
||||
}
|
||||
|
||||
const devtoolsButton = SettingsStore.getValue("showDeveloperTools") ?
|
||||
(<AccessibleButton className="mx_RoomSettings_devtoolsButton" onClick={this._openDevtools}>
|
||||
{ _t("Open Devtools") }
|
||||
</AccessibleButton>) : null;
|
||||
|
||||
return (
|
||||
<div className="mx_RoomSettings">
|
||||
|
||||
|
@ -1055,6 +1065,7 @@ module.exports = React.createClass({
|
|||
{ _t('Internal room ID: ') } <code>{ this.props.room.roomId }</code><br />
|
||||
{ _t('Room version number: ') } <code>{ this.props.room.getVersion() }</code><br />
|
||||
{ roomUpgradeButton }
|
||||
{ devtoolsButton }
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue