Merge branch 'develop' into luke/UDE-file-upload
This commit is contained in:
commit
17c9fcbb85
22 changed files with 200 additions and 113 deletions
|
@ -310,9 +310,10 @@ function _onAction(payload) {
|
||||||
placeCall(call);
|
placeCall(call);
|
||||||
}, function(err) {
|
}, function(err) {
|
||||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
|
console.error("Conference call failed: " + err);
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createDialog(ErrorDialog, {
|
||||||
title: "Failed to set up conference call",
|
title: "Failed to set up conference call",
|
||||||
description: "Conference call failed: " + err,
|
description: "Conference call failed.",
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -276,7 +276,7 @@ class ContentMessages {
|
||||||
|
|
||||||
sendContentToRoom(file, roomId, matrixClient) {
|
sendContentToRoom(file, roomId, matrixClient) {
|
||||||
const content = {
|
const content = {
|
||||||
body: file.name,
|
body: file.name || 'Attachment',
|
||||||
info: {
|
info: {
|
||||||
size: file.size,
|
size: file.size,
|
||||||
}
|
}
|
||||||
|
@ -316,7 +316,7 @@ class ContentMessages {
|
||||||
}
|
}
|
||||||
|
|
||||||
const upload = {
|
const upload = {
|
||||||
fileName: file.name,
|
fileName: file.name || 'Attachment',
|
||||||
roomId: roomId,
|
roomId: roomId,
|
||||||
total: 0,
|
total: 0,
|
||||||
loaded: 0,
|
loaded: 0,
|
||||||
|
|
|
@ -116,7 +116,6 @@ function textForRoomNameEvent(ev) {
|
||||||
|
|
||||||
function textForMessageEvent(ev) {
|
function textForMessageEvent(ev) {
|
||||||
var senderDisplayName = ev.sender && ev.sender.name ? ev.sender.name : ev.getSender();
|
var senderDisplayName = ev.sender && ev.sender.name ? ev.sender.name : ev.getSender();
|
||||||
|
|
||||||
var message = senderDisplayName + ': ' + ev.getContent().body;
|
var message = senderDisplayName + ': ' + ev.getContent().body;
|
||||||
if (ev.getContent().msgtype === "m.emote") {
|
if (ev.getContent().msgtype === "m.emote") {
|
||||||
message = "* " + senderDisplayName + " " + message;
|
message = "* " + senderDisplayName + " " + message;
|
||||||
|
|
|
@ -1,3 +1,19 @@
|
||||||
|
/*
|
||||||
|
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 dis from './dispatcher';
|
import dis from './dispatcher';
|
||||||
import sdk from './index';
|
import sdk from './index';
|
||||||
import Modal from './Modal';
|
import Modal from './Modal';
|
||||||
|
|
|
@ -63,6 +63,13 @@ module.exports = React.createClass({
|
||||||
// called when the session load completes
|
// called when the session load completes
|
||||||
onLoadCompleted: React.PropTypes.func,
|
onLoadCompleted: React.PropTypes.func,
|
||||||
|
|
||||||
|
// Represents the screen to display as a result of parsing the initial
|
||||||
|
// window.location
|
||||||
|
initialScreenAfterLogin: React.PropTypes.shape({
|
||||||
|
screen: React.PropTypes.string.isRequired,
|
||||||
|
params: React.PropTypes.object,
|
||||||
|
}),
|
||||||
|
|
||||||
// displayname, if any, to set on the device when logging
|
// displayname, if any, to set on the device when logging
|
||||||
// in/registering.
|
// in/registering.
|
||||||
defaultDeviceDisplayName: React.PropTypes.string,
|
defaultDeviceDisplayName: React.PropTypes.string,
|
||||||
|
@ -89,6 +96,12 @@ module.exports = React.createClass({
|
||||||
var s = {
|
var s = {
|
||||||
loading: true,
|
loading: true,
|
||||||
screen: undefined,
|
screen: undefined,
|
||||||
|
screenAfterLogin: this.props.initialScreenAfterLogin,
|
||||||
|
|
||||||
|
// Stashed guest credentials if the user logs out
|
||||||
|
// whilst logged in as a guest user (so they can change
|
||||||
|
// their mind & log back in)
|
||||||
|
guestCreds: null,
|
||||||
|
|
||||||
// What the LoggedInView would be showing if visible
|
// What the LoggedInView would be showing if visible
|
||||||
page_type: null,
|
page_type: null,
|
||||||
|
@ -184,11 +197,6 @@ module.exports = React.createClass({
|
||||||
componentWillMount: function() {
|
componentWillMount: function() {
|
||||||
SdkConfig.put(this.props.config);
|
SdkConfig.put(this.props.config);
|
||||||
|
|
||||||
// Stashed guest credentials if the user logs out
|
|
||||||
// whilst logged in as a guest user (so they can change
|
|
||||||
// their mind & log back in)
|
|
||||||
this.guestCreds = null;
|
|
||||||
|
|
||||||
// if the automatic session load failed, the error
|
// if the automatic session load failed, the error
|
||||||
this.sessionLoadError = null;
|
this.sessionLoadError = null;
|
||||||
|
|
||||||
|
@ -322,9 +330,6 @@ module.exports = React.createClass({
|
||||||
var self = this;
|
var self = this;
|
||||||
switch (payload.action) {
|
switch (payload.action) {
|
||||||
case 'logout':
|
case 'logout':
|
||||||
if (MatrixClientPeg.get().isGuest()) {
|
|
||||||
this.guestCreds = MatrixClientPeg.getCredentials();
|
|
||||||
}
|
|
||||||
Lifecycle.logout();
|
Lifecycle.logout();
|
||||||
break;
|
break;
|
||||||
case 'start_registration':
|
case 'start_registration':
|
||||||
|
@ -344,7 +349,11 @@ module.exports = React.createClass({
|
||||||
this.notifyNewScreen('register');
|
this.notifyNewScreen('register');
|
||||||
break;
|
break;
|
||||||
case 'start_login':
|
case 'start_login':
|
||||||
if (this.state.logged_in) return;
|
if (MatrixClientPeg.get().isGuest()) {
|
||||||
|
this.setState({
|
||||||
|
guestCreds: MatrixClientPeg.getCredentials(),
|
||||||
|
});
|
||||||
|
}
|
||||||
this.setStateForNewScreen({
|
this.setStateForNewScreen({
|
||||||
screen: 'login',
|
screen: 'login',
|
||||||
});
|
});
|
||||||
|
@ -359,8 +368,8 @@ module.exports = React.createClass({
|
||||||
// also stash our credentials, then if we restore the session,
|
// also stash our credentials, then if we restore the session,
|
||||||
// we can just do it the same way whether we started upgrade
|
// we can just do it the same way whether we started upgrade
|
||||||
// registration or explicitly logged out
|
// registration or explicitly logged out
|
||||||
this.guestCreds = MatrixClientPeg.getCredentials();
|
|
||||||
this.setStateForNewScreen({
|
this.setStateForNewScreen({
|
||||||
|
guestCreds: MatrixClientPeg.getCredentials(),
|
||||||
screen: "register",
|
screen: "register",
|
||||||
upgradeUsername: MatrixClientPeg.get().getUserIdLocalpart(),
|
upgradeUsername: MatrixClientPeg.get().getUserIdLocalpart(),
|
||||||
guestAccessToken: MatrixClientPeg.get().getAccessToken(),
|
guestAccessToken: MatrixClientPeg.get().getAccessToken(),
|
||||||
|
@ -402,9 +411,10 @@ module.exports = React.createClass({
|
||||||
dis.dispatch({action: 'view_next_room'});
|
dis.dispatch({action: 'view_next_room'});
|
||||||
}, function(err) {
|
}, function(err) {
|
||||||
modal.close();
|
modal.close();
|
||||||
|
console.error("Failed to leave room " + payload.room_id + " " + err);
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createDialog(ErrorDialog, {
|
||||||
title: "Failed to leave room",
|
title: "Failed to leave room",
|
||||||
description: err.toString()
|
description: "Server may be unavailable, overloaded, or you hit a bug."
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -708,18 +718,31 @@ module.exports = React.createClass({
|
||||||
* Called when a new logged in session has started
|
* Called when a new logged in session has started
|
||||||
*/
|
*/
|
||||||
_onLoggedIn: function(teamToken) {
|
_onLoggedIn: function(teamToken) {
|
||||||
this.guestCreds = null;
|
|
||||||
this.notifyNewScreen('');
|
|
||||||
this.setState({
|
this.setState({
|
||||||
screen: undefined,
|
guestCreds: null,
|
||||||
logged_in: true,
|
logged_in: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// If screenAfterLogin is set, use that, then null it so that a second login will
|
||||||
|
// result in view_home_page, _user_settings or _room_directory
|
||||||
|
if (this.state.screenAfterLogin && this.state.screenAfterLogin.screen) {
|
||||||
|
this.showScreen(
|
||||||
|
this.state.screenAfterLogin.screen,
|
||||||
|
this.state.screenAfterLogin.params
|
||||||
|
);
|
||||||
|
this.setState({screenAfterLogin: null});
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
this.setState({screen: undefined});
|
||||||
|
}
|
||||||
|
|
||||||
if (teamToken) {
|
if (teamToken) {
|
||||||
this._teamToken = teamToken;
|
this._teamToken = teamToken;
|
||||||
this._setPage(PageTypes.HomePage);
|
dis.dispatch({action: 'view_home_page'});
|
||||||
} else if (this._is_registered) {
|
} else if (this._is_registered) {
|
||||||
this._setPage(PageTypes.UserSettings);
|
dis.dispatch({action: 'view_user_settings'});
|
||||||
|
} else {
|
||||||
|
dis.dispatch({action: 'view_room_directory'});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -768,12 +791,6 @@ module.exports = React.createClass({
|
||||||
cli.getRooms()
|
cli.getRooms()
|
||||||
)[0].roomId;
|
)[0].roomId;
|
||||||
self.setState({ready: true, currentRoomId: firstRoom, page_type: PageTypes.RoomView});
|
self.setState({ready: true, currentRoomId: firstRoom, page_type: PageTypes.RoomView});
|
||||||
} else {
|
|
||||||
if (self._teamToken) {
|
|
||||||
self.setState({ready: true, page_type: PageTypes.HomePage});
|
|
||||||
} else {
|
|
||||||
self.setState({ready: true, page_type: PageTypes.RoomDirectory});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.setState({ready: true, page_type: PageTypes.RoomView});
|
self.setState({ready: true, page_type: PageTypes.RoomView});
|
||||||
|
@ -790,16 +807,7 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
if (presentedId != undefined) {
|
if (presentedId != undefined) {
|
||||||
self.notifyNewScreen('room/'+presentedId);
|
self.notifyNewScreen('room/'+presentedId);
|
||||||
} else {
|
|
||||||
// There is no information on presentedId
|
|
||||||
// so point user to fallback like /directory
|
|
||||||
if (self._teamToken) {
|
|
||||||
self.notifyNewScreen('home');
|
|
||||||
} else {
|
|
||||||
self.notifyNewScreen('directory');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dis.dispatch({action: 'focus_composer'});
|
dis.dispatch({action: 'focus_composer'});
|
||||||
} else {
|
} else {
|
||||||
self.setState({ready: true});
|
self.setState({ready: true});
|
||||||
|
@ -1002,9 +1010,9 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
onReturnToGuestClick: function() {
|
onReturnToGuestClick: function() {
|
||||||
// reanimate our guest login
|
// reanimate our guest login
|
||||||
if (this.guestCreds) {
|
if (this.state.guestCreds) {
|
||||||
Lifecycle.setLoggedIn(this.guestCreds);
|
Lifecycle.setLoggedIn(this.state.guestCreds);
|
||||||
this.guestCreds = null;
|
this.setState({guestCreds: null});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1153,7 +1161,7 @@ module.exports = React.createClass({
|
||||||
onLoggedIn={this.onRegistered}
|
onLoggedIn={this.onRegistered}
|
||||||
onLoginClick={this.onLoginClick}
|
onLoginClick={this.onLoginClick}
|
||||||
onRegisterClick={this.onRegisterClick}
|
onRegisterClick={this.onRegisterClick}
|
||||||
onCancelClick={this.guestCreds ? this.onReturnToGuestClick : null}
|
onCancelClick={this.state.guestCreds ? this.onReturnToGuestClick : null}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
} else if (this.state.screen == 'forgot_password') {
|
} else if (this.state.screen == 'forgot_password') {
|
||||||
|
@ -1180,7 +1188,7 @@ module.exports = React.createClass({
|
||||||
defaultDeviceDisplayName={this.props.defaultDeviceDisplayName}
|
defaultDeviceDisplayName={this.props.defaultDeviceDisplayName}
|
||||||
onForgotPasswordClick={this.onForgotPasswordClick}
|
onForgotPasswordClick={this.onForgotPasswordClick}
|
||||||
enableGuest={this.props.enableGuest}
|
enableGuest={this.props.enableGuest}
|
||||||
onCancelClick={this.guestCreds ? this.onReturnToGuestClick : null}
|
onCancelClick={this.state.guestCreds ? this.onReturnToGuestClick : null}
|
||||||
initialErrorText={this.sessionLoadError}
|
initialErrorText={this.sessionLoadError}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
|
@ -295,7 +295,10 @@ module.exports = React.createClass({
|
||||||
var last = (i == lastShownEventIndex);
|
var last = (i == lastShownEventIndex);
|
||||||
|
|
||||||
// Wrap consecutive member events in a ListSummary, ignore if redacted
|
// Wrap consecutive member events in a ListSummary, ignore if redacted
|
||||||
if (isMembershipChange(mxEv) && EventTile.haveTileForEvent(mxEv)) {
|
if (isMembershipChange(mxEv) &&
|
||||||
|
EventTile.haveTileForEvent(mxEv) &&
|
||||||
|
!mxEv.isRedacted()
|
||||||
|
) {
|
||||||
let ts1 = mxEv.getTs();
|
let ts1 = mxEv.getTs();
|
||||||
// Ensure that the key of the MemberEventListSummary does not change with new
|
// Ensure that the key of the MemberEventListSummary does not change with new
|
||||||
// member events. This will prevent it from being re-created unnecessarily, and
|
// member events. This will prevent it from being re-created unnecessarily, and
|
||||||
|
@ -408,7 +411,9 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
// is this a continuation of the previous message?
|
// is this a continuation of the previous message?
|
||||||
var continuation = false;
|
var continuation = false;
|
||||||
if (prevEvent !== null && prevEvent.sender && mxEv.sender
|
|
||||||
|
if (prevEvent !== null
|
||||||
|
&& !prevEvent.isRedacted() && prevEvent.sender && mxEv.sender
|
||||||
&& mxEv.sender.userId === prevEvent.sender.userId
|
&& mxEv.sender.userId === prevEvent.sender.userId
|
||||||
&& mxEv.getType() == prevEvent.getType()) {
|
&& mxEv.getType() == prevEvent.getType()) {
|
||||||
continuation = true;
|
continuation = true;
|
||||||
|
@ -461,6 +466,7 @@ module.exports = React.createClass({
|
||||||
ref={this._collectEventNode.bind(this, eventId)}
|
ref={this._collectEventNode.bind(this, eventId)}
|
||||||
data-scroll-token={scrollToken}>
|
data-scroll-token={scrollToken}>
|
||||||
<EventTile mxEvent={mxEv} continuation={continuation}
|
<EventTile mxEvent={mxEv} continuation={continuation}
|
||||||
|
isRedacted={mxEv.isRedacted()}
|
||||||
onWidgetLoad={this._onWidgetLoad}
|
onWidgetLoad={this._onWidgetLoad}
|
||||||
readReceipts={readReceipts}
|
readReceipts={readReceipts}
|
||||||
readReceiptMap={this._readReceiptMap}
|
readReceiptMap={this._readReceiptMap}
|
||||||
|
@ -481,13 +487,17 @@ module.exports = React.createClass({
|
||||||
// here.
|
// here.
|
||||||
return !this.props.suppressFirstDateSeparator;
|
return !this.props.suppressFirstDateSeparator;
|
||||||
}
|
}
|
||||||
|
const prevEventDate = prevEvent.getDate();
|
||||||
|
if (!nextEventDate || !prevEventDate) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
// Return early for events that are > 24h apart
|
// Return early for events that are > 24h apart
|
||||||
if (Math.abs(prevEvent.getTs() - nextEventDate.getTime()) > MILLIS_IN_DAY) {
|
if (Math.abs(prevEvent.getTs() - nextEventDate.getTime()) > MILLIS_IN_DAY) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compare weekdays
|
// Compare weekdays
|
||||||
return prevEvent.getDate().getDay() !== nextEventDate.getDay();
|
return prevEventDate.getDay() !== nextEventDate.getDay();
|
||||||
},
|
},
|
||||||
|
|
||||||
// get a list of read receipts that should be shown next to this event
|
// get a list of read receipts that should be shown next to this event
|
||||||
|
|
|
@ -936,9 +936,10 @@ module.exports = React.createClass({
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
|
console.error("Failed to upload file " + file + " " + error);
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createDialog(ErrorDialog, {
|
||||||
title: "Failed to upload file",
|
title: "Failed to upload file",
|
||||||
description: error.toString()
|
description: "Server may be unavailable, overloaded, or the file too big",
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -1022,9 +1023,10 @@ module.exports = React.createClass({
|
||||||
});
|
});
|
||||||
}, function(error) {
|
}, function(error) {
|
||||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
|
console.error("Search failed: " + error);
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createDialog(ErrorDialog, {
|
||||||
title: "Search failed",
|
title: "Search failed",
|
||||||
description: error.toString()
|
description: "Server may be unavailable, overloaded, or search timed out :("
|
||||||
});
|
});
|
||||||
}).finally(function() {
|
}).finally(function() {
|
||||||
self.setState({
|
self.setState({
|
||||||
|
|
|
@ -206,9 +206,10 @@ module.exports = React.createClass({
|
||||||
});
|
});
|
||||||
}, function(error) {
|
}, function(error) {
|
||||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
|
console.error("Failed to load user settings: " + error);
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createDialog(ErrorDialog, {
|
||||||
title: "Can't load user settings",
|
title: "Can't load user settings",
|
||||||
description: error.toString()
|
description: "Server may be unavailable or overloaded",
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -246,10 +247,11 @@ module.exports = React.createClass({
|
||||||
self._refreshFromServer();
|
self._refreshFromServer();
|
||||||
}, function(err) {
|
}, function(err) {
|
||||||
var errMsg = (typeof err === "string") ? err : (err.error || "");
|
var errMsg = (typeof err === "string") ? err : (err.error || "");
|
||||||
|
console.error("Failed to set avatar: " + err);
|
||||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createDialog(ErrorDialog, {
|
||||||
title: "Error",
|
title: "Error",
|
||||||
description: "Failed to set avatar. " + errMsg
|
description: "Failed to set avatar."
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -286,6 +288,7 @@ module.exports = React.createClass({
|
||||||
errMsg += ` (HTTP status ${err.httpStatus})`;
|
errMsg += ` (HTTP status ${err.httpStatus})`;
|
||||||
}
|
}
|
||||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
|
console.error("Failed to change password: " + errMsg);
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createDialog(ErrorDialog, {
|
||||||
title: "Error",
|
title: "Error",
|
||||||
description: errMsg
|
description: errMsg
|
||||||
|
@ -337,9 +340,10 @@ module.exports = React.createClass({
|
||||||
});
|
});
|
||||||
}, (err) => {
|
}, (err) => {
|
||||||
this.setState({email_add_pending: false});
|
this.setState({email_add_pending: false});
|
||||||
|
console.error("Unable to add email address " + email_address + " " + err);
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createDialog(ErrorDialog, {
|
||||||
title: "Unable to add email address",
|
title: "Error",
|
||||||
description: err.message
|
description: "Unable to add email address"
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
ReactDOM.findDOMNode(this.refs.add_threepid_input).blur();
|
ReactDOM.findDOMNode(this.refs.add_threepid_input).blur();
|
||||||
|
@ -361,9 +365,10 @@ module.exports = React.createClass({
|
||||||
return this._refreshFromServer();
|
return this._refreshFromServer();
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
|
console.error("Unable to remove contact information: " + err);
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createDialog(ErrorDialog, {
|
||||||
title: "Unable to remove contact information",
|
title: "Error",
|
||||||
description: err.toString(),
|
description: "Unable to remove contact information",
|
||||||
});
|
});
|
||||||
}).done();
|
}).done();
|
||||||
}
|
}
|
||||||
|
@ -401,9 +406,10 @@ module.exports = React.createClass({
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
|
console.error("Unable to verify email address: " + err);
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createDialog(ErrorDialog, {
|
||||||
title: "Unable to verify email address",
|
title: "Error",
|
||||||
description: err.toString(),
|
description: "Unable to verify email address",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -185,7 +185,6 @@ module.exports = React.createClass({
|
||||||
const teamToken = data.team_token;
|
const teamToken = data.team_token;
|
||||||
// Store for use /w welcome pages
|
// Store for use /w welcome pages
|
||||||
window.localStorage.setItem('mx_team_token', teamToken);
|
window.localStorage.setItem('mx_team_token', teamToken);
|
||||||
this.props.onTeamMemberRegistered(teamToken);
|
|
||||||
|
|
||||||
this._rtsClient.getTeam(teamToken).then((team) => {
|
this._rtsClient.getTeam(teamToken).then((team) => {
|
||||||
console.log(
|
console.log(
|
||||||
|
|
|
@ -18,6 +18,7 @@ import React from 'react';
|
||||||
|
|
||||||
import * as KeyCode from '../../../KeyCode';
|
import * as KeyCode from '../../../KeyCode';
|
||||||
import AccessibleButton from '../elements/AccessibleButton';
|
import AccessibleButton from '../elements/AccessibleButton';
|
||||||
|
import sdk from '../../../index';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Basic container for modal dialogs.
|
* Basic container for modal dialogs.
|
||||||
|
@ -65,15 +66,14 @@ export default React.createClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
|
const TintableSvg = sdk.getComponent("elements.TintableSvg");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div onKeyDown={this._onKeyDown} className={this.props.className}>
|
<div onKeyDown={this._onKeyDown} className={this.props.className}>
|
||||||
<AccessibleButton onClick={this._onCancelClick}
|
<AccessibleButton onClick={this._onCancelClick}
|
||||||
className="mx_Dialog_cancelButton"
|
className="mx_Dialog_cancelButton"
|
||||||
>
|
>
|
||||||
<img
|
<TintableSvg src="img/icons-close-button.svg" width="35" height="35" />
|
||||||
src="img/cancel.svg" width="18" height="18"
|
|
||||||
alt="Cancel" title="Cancel"
|
|
||||||
/>
|
|
||||||
</AccessibleButton>
|
</AccessibleButton>
|
||||||
<div className='mx_Dialog_title'>
|
<div className='mx_Dialog_title'>
|
||||||
{ this.props.title }
|
{ this.props.title }
|
||||||
|
|
|
@ -24,7 +24,7 @@ import Unread from '../../../Unread';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import createRoom from '../../../createRoom';
|
import createRoom from '../../../createRoom';
|
||||||
|
|
||||||
export default class CreateOrReuseChatDialog extends React.Component {
|
export default class ChatCreateOrReuseDialog extends React.Component {
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
@ -91,21 +91,25 @@ export default class CreateOrReuseChatDialog extends React.Component {
|
||||||
|
|
||||||
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
|
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
|
||||||
return (
|
return (
|
||||||
<BaseDialog className='mx_CreateOrReuseChatDialog'
|
<BaseDialog className='mx_ChatCreateOrReuseDialog'
|
||||||
onFinished={() => {
|
onFinished={() => {
|
||||||
this.props.onFinished(false)
|
this.props.onFinished(false)
|
||||||
}}
|
}}
|
||||||
title='Create a new chat or reuse an existing one'
|
title='Create a new chat or reuse an existing one'
|
||||||
>
|
>
|
||||||
You already have existing direct chats with this user:
|
<div className="mx_Dialog_content">
|
||||||
{tiles}
|
You already have existing direct chats with this user:
|
||||||
{startNewChat}
|
<div className="mx_ChatCreateOrReuseDialog_tiles">
|
||||||
|
{tiles}
|
||||||
|
{startNewChat}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</BaseDialog>
|
</BaseDialog>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CreateOrReuseChatDialog.propTyps = {
|
ChatCreateOrReuseDialog.propTyps = {
|
||||||
userId: React.PropTypes.string.isRequired,
|
userId: React.PropTypes.string.isRequired,
|
||||||
onFinished: React.PropTypes.func.isRequired,
|
onFinished: React.PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
|
@ -318,8 +318,8 @@ module.exports = React.createClass({
|
||||||
console.error(err.stack);
|
console.error(err.stack);
|
||||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createDialog(ErrorDialog, {
|
||||||
title: "Failure to invite",
|
title: "Error",
|
||||||
description: err.toString()
|
description: "Failed to invite",
|
||||||
});
|
});
|
||||||
return null;
|
return null;
|
||||||
})
|
})
|
||||||
|
@ -331,8 +331,8 @@ module.exports = React.createClass({
|
||||||
console.error(err.stack);
|
console.error(err.stack);
|
||||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createDialog(ErrorDialog, {
|
||||||
title: "Failure to invite user",
|
title: "Error",
|
||||||
description: err.toString()
|
description: "Failed to invite user",
|
||||||
});
|
});
|
||||||
return null;
|
return null;
|
||||||
})
|
})
|
||||||
|
@ -352,8 +352,8 @@ module.exports = React.createClass({
|
||||||
console.error(err.stack);
|
console.error(err.stack);
|
||||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createDialog(ErrorDialog, {
|
||||||
title: "Failure to invite",
|
title: "Error",
|
||||||
description: err.toString()
|
description: "Failed to invite",
|
||||||
});
|
});
|
||||||
return null;
|
return null;
|
||||||
})
|
})
|
||||||
|
|
|
@ -97,7 +97,7 @@ export default React.createClass({
|
||||||
>
|
>
|
||||||
<div className="mx_Dialog_content">
|
<div className="mx_Dialog_content">
|
||||||
<div className="mx_ConfirmUserActionDialog_avatar">
|
<div className="mx_ConfirmUserActionDialog_avatar">
|
||||||
<MemberAvatar member={this.props.member} width={72} height={72} />
|
<MemberAvatar member={this.props.member} width={48} height={48} />
|
||||||
</div>
|
</div>
|
||||||
<div className="mx_ConfirmUserActionDialog_name">{this.props.member.name}</div>
|
<div className="mx_ConfirmUserActionDialog_name">{this.props.member.name}</div>
|
||||||
<div className="mx_ConfirmUserActionDialog_userId">{this.props.member.userId}</div>
|
<div className="mx_ConfirmUserActionDialog_userId">{this.props.member.userId}</div>
|
||||||
|
|
|
@ -22,10 +22,10 @@ module.exports = React.createClass({
|
||||||
displayName: 'UnknownBody',
|
displayName: 'UnknownBody',
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
var content = this.props.mxEvent.getContent();
|
const text = this.props.mxEvent.getContent().body;
|
||||||
return (
|
return (
|
||||||
<span className="mx_UnknownBody">
|
<span className="mx_UnknownBody">
|
||||||
{content.body}
|
{text}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
|
@ -25,18 +25,10 @@ var TextForEvent = require('../../../TextForEvent');
|
||||||
import WithMatrixClient from '../../../wrappers/WithMatrixClient';
|
import WithMatrixClient from '../../../wrappers/WithMatrixClient';
|
||||||
|
|
||||||
var ContextualMenu = require('../../structures/ContextualMenu');
|
var ContextualMenu = require('../../structures/ContextualMenu');
|
||||||
var dispatcher = require("../../../dispatcher");
|
import dis from '../../../dispatcher';
|
||||||
|
|
||||||
var ObjectUtils = require('../../../ObjectUtils');
|
var ObjectUtils = require('../../../ObjectUtils');
|
||||||
|
|
||||||
var bounce = false;
|
|
||||||
try {
|
|
||||||
if (global.localStorage) {
|
|
||||||
bounce = global.localStorage.getItem('avatar_bounce') == 'true';
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
}
|
|
||||||
|
|
||||||
var eventTileTypes = {
|
var eventTileTypes = {
|
||||||
'm.room.message': 'messages.MessageEvent',
|
'm.room.message': 'messages.MessageEvent',
|
||||||
'm.room.member' : 'messages.TextualEvent',
|
'm.room.member' : 'messages.TextualEvent',
|
||||||
|
@ -73,6 +65,12 @@ module.exports = WithMatrixClient(React.createClass({
|
||||||
/* the MatrixEvent to show */
|
/* the MatrixEvent to show */
|
||||||
mxEvent: React.PropTypes.object.isRequired,
|
mxEvent: React.PropTypes.object.isRequired,
|
||||||
|
|
||||||
|
/* true if mxEvent is redacted. This is a prop because using mxEvent.isRedacted()
|
||||||
|
* might not be enough when deciding shouldComponentUpdate - prevProps.mxEvent
|
||||||
|
* references the same this.props.mxEvent.
|
||||||
|
*/
|
||||||
|
isRedacted: React.PropTypes.bool,
|
||||||
|
|
||||||
/* true if this is a continuation of the previous event (which has the
|
/* true if this is a continuation of the previous event (which has the
|
||||||
* effect of not showing another avatar/displayname
|
* effect of not showing another avatar/displayname
|
||||||
*/
|
*/
|
||||||
|
@ -356,7 +354,7 @@ module.exports = WithMatrixClient(React.createClass({
|
||||||
|
|
||||||
onSenderProfileClick: function(event) {
|
onSenderProfileClick: function(event) {
|
||||||
var mxEvent = this.props.mxEvent;
|
var mxEvent = this.props.mxEvent;
|
||||||
dispatcher.dispatch({
|
dis.dispatch({
|
||||||
action: 'insert_displayname',
|
action: 'insert_displayname',
|
||||||
displayname: (mxEvent.sender ? mxEvent.sender.name : mxEvent.getSender()).replace(' (IRC)', ''),
|
displayname: (mxEvent.sender ? mxEvent.sender.name : mxEvent.getSender()).replace(' (IRC)', ''),
|
||||||
});
|
});
|
||||||
|
@ -372,6 +370,17 @@ module.exports = WithMatrixClient(React.createClass({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
onPermalinkClicked: function(e) {
|
||||||
|
// This allows the permalink to be opened in a new tab/window or copied as
|
||||||
|
// matrix.to, but also for it to enable routing within Riot when clicked.
|
||||||
|
e.preventDefault();
|
||||||
|
dis.dispatch({
|
||||||
|
action: 'view_room',
|
||||||
|
event_id: this.props.mxEvent.getId(),
|
||||||
|
room_id: this.props.mxEvent.getRoomId(),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
var MessageTimestamp = sdk.getComponent('messages.MessageTimestamp');
|
var MessageTimestamp = sdk.getComponent('messages.MessageTimestamp');
|
||||||
var SenderProfile = sdk.getComponent('messages.SenderProfile');
|
var SenderProfile = sdk.getComponent('messages.SenderProfile');
|
||||||
|
@ -396,6 +405,7 @@ module.exports = WithMatrixClient(React.createClass({
|
||||||
|
|
||||||
var e2eEnabled = this.props.matrixClient.isRoomEncrypted(this.props.mxEvent.getRoomId());
|
var e2eEnabled = this.props.matrixClient.isRoomEncrypted(this.props.mxEvent.getRoomId());
|
||||||
var isSending = (['sending', 'queued', 'encrypting'].indexOf(this.props.eventSendStatus) !== -1);
|
var isSending = (['sending', 'queued', 'encrypting'].indexOf(this.props.eventSendStatus) !== -1);
|
||||||
|
const isRedacted = (eventType === 'm.room.message') && this.props.isRedacted;
|
||||||
|
|
||||||
var classes = classNames({
|
var classes = classNames({
|
||||||
mx_EventTile: true,
|
mx_EventTile: true,
|
||||||
|
@ -412,8 +422,12 @@ module.exports = WithMatrixClient(React.createClass({
|
||||||
mx_EventTile_verified: this.state.verified == true,
|
mx_EventTile_verified: this.state.verified == true,
|
||||||
mx_EventTile_unverified: this.state.verified == false,
|
mx_EventTile_unverified: this.state.verified == false,
|
||||||
mx_EventTile_bad: this.props.mxEvent.getContent().msgtype === 'm.bad.encrypted',
|
mx_EventTile_bad: this.props.mxEvent.getContent().msgtype === 'm.bad.encrypted',
|
||||||
|
mx_EventTile_redacted: isRedacted,
|
||||||
});
|
});
|
||||||
var permalink = "https://matrix.to/#/" + this.props.mxEvent.getRoomId() +"/"+ this.props.mxEvent.getId();
|
|
||||||
|
const permalink = "https://matrix.to/#/" +
|
||||||
|
this.props.mxEvent.getRoomId() + "/" +
|
||||||
|
this.props.mxEvent.getId();
|
||||||
|
|
||||||
var readAvatars = this.getReadAvatars();
|
var readAvatars = this.getReadAvatars();
|
||||||
|
|
||||||
|
@ -421,7 +435,10 @@ module.exports = WithMatrixClient(React.createClass({
|
||||||
let avatarSize;
|
let avatarSize;
|
||||||
let needsSenderProfile;
|
let needsSenderProfile;
|
||||||
|
|
||||||
if (this.props.tileShape === "notif") {
|
if (isRedacted) {
|
||||||
|
avatarSize = 0;
|
||||||
|
needsSenderProfile = false;
|
||||||
|
} else if (this.props.tileShape === "notif") {
|
||||||
avatarSize = 24;
|
avatarSize = 24;
|
||||||
needsSenderProfile = true;
|
needsSenderProfile = true;
|
||||||
} else if (isInfoMessage) {
|
} else if (isInfoMessage) {
|
||||||
|
@ -486,6 +503,8 @@ module.exports = WithMatrixClient(React.createClass({
|
||||||
else if (e2eEnabled) {
|
else if (e2eEnabled) {
|
||||||
e2e = <img onClick={ this.onCryptoClicked } className="mx_EventTile_e2eIcon" src="img/e2e-unencrypted.svg" width="12" height="12"/>;
|
e2e = <img onClick={ this.onCryptoClicked } className="mx_EventTile_e2eIcon" src="img/e2e-unencrypted.svg" width="12" height="12"/>;
|
||||||
}
|
}
|
||||||
|
const timestamp = this.props.mxEvent.isRedacted() ?
|
||||||
|
null : <MessageTimestamp ts={this.props.mxEvent.getTs()} />;
|
||||||
|
|
||||||
if (this.props.tileShape === "notif") {
|
if (this.props.tileShape === "notif") {
|
||||||
var room = this.props.matrixClient.getRoom(this.props.mxEvent.getRoomId());
|
var room = this.props.matrixClient.getRoom(this.props.mxEvent.getRoomId());
|
||||||
|
@ -493,15 +512,15 @@ module.exports = WithMatrixClient(React.createClass({
|
||||||
return (
|
return (
|
||||||
<div className={classes}>
|
<div className={classes}>
|
||||||
<div className="mx_EventTile_roomName">
|
<div className="mx_EventTile_roomName">
|
||||||
<a href={ permalink }>
|
<a href={ permalink } onClick={this.onPermalinkClicked}>
|
||||||
{ room ? room.name : '' }
|
{ room ? room.name : '' }
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div className="mx_EventTile_senderDetails">
|
<div className="mx_EventTile_senderDetails">
|
||||||
{ avatar }
|
{ avatar }
|
||||||
<a href={ permalink }>
|
<a href={ permalink } onClick={this.onPermalinkClicked}>
|
||||||
{ sender }
|
{ sender }
|
||||||
<MessageTimestamp ts={this.props.mxEvent.getTs()} />
|
{ timestamp }
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div className="mx_EventTile_line" >
|
<div className="mx_EventTile_line" >
|
||||||
|
@ -527,10 +546,14 @@ module.exports = WithMatrixClient(React.createClass({
|
||||||
tileShape={this.props.tileShape}
|
tileShape={this.props.tileShape}
|
||||||
onWidgetLoad={this.props.onWidgetLoad} />
|
onWidgetLoad={this.props.onWidgetLoad} />
|
||||||
</div>
|
</div>
|
||||||
<a className="mx_EventTile_senderDetailsLink" href={ permalink }>
|
<a
|
||||||
|
className="mx_EventTile_senderDetailsLink"
|
||||||
|
href={ permalink }
|
||||||
|
onClick={this.onPermalinkClicked}
|
||||||
|
>
|
||||||
<div className="mx_EventTile_senderDetails">
|
<div className="mx_EventTile_senderDetails">
|
||||||
{ sender }
|
{ sender }
|
||||||
<MessageTimestamp ts={this.props.mxEvent.getTs()} />
|
{ timestamp }
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -545,8 +568,8 @@ module.exports = WithMatrixClient(React.createClass({
|
||||||
{ avatar }
|
{ avatar }
|
||||||
{ sender }
|
{ sender }
|
||||||
<div className="mx_EventTile_line">
|
<div className="mx_EventTile_line">
|
||||||
<a href={ permalink }>
|
<a href={ permalink } onClick={this.onPermalinkClicked}>
|
||||||
<MessageTimestamp ts={this.props.mxEvent.getTs()} />
|
{ timestamp }
|
||||||
</a>
|
</a>
|
||||||
{ e2e }
|
{ e2e }
|
||||||
<EventTileType ref="tile"
|
<EventTileType ref="tile"
|
||||||
|
@ -564,7 +587,8 @@ module.exports = WithMatrixClient(React.createClass({
|
||||||
}));
|
}));
|
||||||
|
|
||||||
module.exports.haveTileForEvent = function(e) {
|
module.exports.haveTileForEvent = function(e) {
|
||||||
if (e.isRedacted()) return false;
|
// Only messages have a tile (black-rectangle) if redacted
|
||||||
|
if (e.isRedacted() && e.getType() !== 'm.room.message') return false;
|
||||||
if (eventTileTypes[e.getType()] == undefined) return false;
|
if (eventTileTypes[e.getType()] == undefined) return false;
|
||||||
if (eventTileTypes[e.getType()] == 'messages.TextualEvent') {
|
if (eventTileTypes[e.getType()] == 'messages.TextualEvent') {
|
||||||
return TextForEvent.textForEvent(e) !== '';
|
return TextForEvent.textForEvent(e) !== '';
|
||||||
|
|
|
@ -237,9 +237,10 @@ module.exports = WithMatrixClient(React.createClass({
|
||||||
console.log("Kick success");
|
console.log("Kick success");
|
||||||
}, function(err) {
|
}, function(err) {
|
||||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
|
console.error("Kick error: " + err);
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createDialog(ErrorDialog, {
|
||||||
title: "Kick error",
|
title: "Error",
|
||||||
description: err.message
|
description: "Failed to kick user",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
).finally(()=>{
|
).finally(()=>{
|
||||||
|
@ -278,9 +279,10 @@ module.exports = WithMatrixClient(React.createClass({
|
||||||
console.log("Ban success");
|
console.log("Ban success");
|
||||||
}, function(err) {
|
}, function(err) {
|
||||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
|
console.error("Ban error: " + err);
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createDialog(ErrorDialog, {
|
||||||
title: "Ban error",
|
title: "Error",
|
||||||
description: err.message,
|
description: "Failed to ban user",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
).finally(()=>{
|
).finally(()=>{
|
||||||
|
@ -327,9 +329,10 @@ module.exports = WithMatrixClient(React.createClass({
|
||||||
// get out of sync if we force setState here!
|
// get out of sync if we force setState here!
|
||||||
console.log("Mute toggle success");
|
console.log("Mute toggle success");
|
||||||
}, function(err) {
|
}, function(err) {
|
||||||
|
console.error("Mute error: " + err);
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createDialog(ErrorDialog, {
|
||||||
title: "Mute error",
|
title: "Error",
|
||||||
description: err.message
|
description: "Failed to mute user",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
).finally(()=>{
|
).finally(()=>{
|
||||||
|
@ -375,9 +378,10 @@ module.exports = WithMatrixClient(React.createClass({
|
||||||
description: "This action cannot be performed by a guest user. Please register to be able to do this."
|
description: "This action cannot be performed by a guest user. Please register to be able to do this."
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
console.error("Toggle moderator error:" + err);
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createDialog(ErrorDialog, {
|
||||||
title: "Moderator toggle error",
|
title: "Error",
|
||||||
description: err.message
|
description: "Failed to toggle moderator status",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -395,9 +399,10 @@ module.exports = WithMatrixClient(React.createClass({
|
||||||
console.log("Power change success");
|
console.log("Power change success");
|
||||||
}, function(err) {
|
}, function(err) {
|
||||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
|
console.error("Failed to change power level " + err);
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createDialog(ErrorDialog, {
|
||||||
title: "Failure to change power level",
|
title: "Error",
|
||||||
description: err.message
|
description: "Failed to change power level",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
).finally(()=>{
|
).finally(()=>{
|
||||||
|
|
|
@ -91,8 +91,9 @@ export default class MessageComposer extends React.Component {
|
||||||
this.refs.uploadInput.click();
|
this.refs.uploadInput.click();
|
||||||
}
|
}
|
||||||
|
|
||||||
onUploadFileSelected(ev) {
|
onUploadFileSelected(files, isPasted) {
|
||||||
let files = ev.target.files;
|
if (!isPasted)
|
||||||
|
files = files.target.files;
|
||||||
|
|
||||||
let QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
let QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||||
let TintableSvg = sdk.getComponent("elements.TintableSvg");
|
let TintableSvg = sdk.getComponent("elements.TintableSvg");
|
||||||
|
@ -100,7 +101,7 @@ export default class MessageComposer extends React.Component {
|
||||||
let fileList = [];
|
let fileList = [];
|
||||||
for (let i=0; i<files.length; i++) {
|
for (let i=0; i<files.length; i++) {
|
||||||
fileList.push(<li key={i}>
|
fileList.push(<li key={i}>
|
||||||
<TintableSvg key={i} src="img/files.svg" width="16" height="16" /> {files[i].name}
|
<TintableSvg key={i} src="img/files.svg" width="16" height="16" /> {files[i].name || 'Attachment'}
|
||||||
</li>);
|
</li>);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,7 +172,7 @@ export default class MessageComposer extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
onUpArrow() {
|
onUpArrow() {
|
||||||
return this.refs.autocomplete.onUpArrow();
|
return this.refs.autocomplete.onUpArrow();
|
||||||
}
|
}
|
||||||
|
|
||||||
onDownArrow() {
|
onDownArrow() {
|
||||||
|
@ -299,6 +300,7 @@ export default class MessageComposer extends React.Component {
|
||||||
tryComplete={this._tryComplete}
|
tryComplete={this._tryComplete}
|
||||||
onUpArrow={this.onUpArrow}
|
onUpArrow={this.onUpArrow}
|
||||||
onDownArrow={this.onDownArrow}
|
onDownArrow={this.onDownArrow}
|
||||||
|
onUploadFileSelected={this.onUploadFileSelected}
|
||||||
tabComplete={this.props.tabComplete} // used for old messagecomposerinput/tabcomplete
|
tabComplete={this.props.tabComplete} // used for old messagecomposerinput/tabcomplete
|
||||||
onContentChanged={this.onInputContentChanged}
|
onContentChanged={this.onInputContentChanged}
|
||||||
onInputStateChanged={this.onInputStateChanged} />,
|
onInputStateChanged={this.onInputStateChanged} />,
|
||||||
|
|
|
@ -84,6 +84,7 @@ export default class MessageComposerInput extends React.Component {
|
||||||
this.onAction = this.onAction.bind(this);
|
this.onAction = this.onAction.bind(this);
|
||||||
this.handleReturn = this.handleReturn.bind(this);
|
this.handleReturn = this.handleReturn.bind(this);
|
||||||
this.handleKeyCommand = this.handleKeyCommand.bind(this);
|
this.handleKeyCommand = this.handleKeyCommand.bind(this);
|
||||||
|
this.handlePastedFiles = this.handlePastedFiles.bind(this);
|
||||||
this.onEditorContentChanged = this.onEditorContentChanged.bind(this);
|
this.onEditorContentChanged = this.onEditorContentChanged.bind(this);
|
||||||
this.setEditorState = this.setEditorState.bind(this);
|
this.setEditorState = this.setEditorState.bind(this);
|
||||||
this.onUpArrow = this.onUpArrow.bind(this);
|
this.onUpArrow = this.onUpArrow.bind(this);
|
||||||
|
@ -475,6 +476,10 @@ export default class MessageComposerInput extends React.Component {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handlePastedFiles(files) {
|
||||||
|
this.props.onUploadFileSelected(files, true);
|
||||||
|
}
|
||||||
|
|
||||||
handleReturn(ev) {
|
handleReturn(ev) {
|
||||||
if (ev.shiftKey) {
|
if (ev.shiftKey) {
|
||||||
this.onEditorContentChanged(RichUtils.insertSoftNewline(this.state.editorState));
|
this.onEditorContentChanged(RichUtils.insertSoftNewline(this.state.editorState));
|
||||||
|
@ -504,7 +509,7 @@ export default class MessageComposerInput extends React.Component {
|
||||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createDialog(ErrorDialog, {
|
||||||
title: "Server error",
|
title: "Server error",
|
||||||
description: err.message
|
description: "Server unavailable, overloaded, or something else went wrong.",
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -728,6 +733,7 @@ export default class MessageComposerInput extends React.Component {
|
||||||
keyBindingFn={MessageComposerInput.getKeyBinding}
|
keyBindingFn={MessageComposerInput.getKeyBinding}
|
||||||
handleKeyCommand={this.handleKeyCommand}
|
handleKeyCommand={this.handleKeyCommand}
|
||||||
handleReturn={this.handleReturn}
|
handleReturn={this.handleReturn}
|
||||||
|
handlePastedFiles={this.handlePastedFiles}
|
||||||
stripPastedStyles={!this.state.isRichtextEnabled}
|
stripPastedStyles={!this.state.isRichtextEnabled}
|
||||||
onTab={this.onTab}
|
onTab={this.onTab}
|
||||||
onUpArrow={this.onUpArrow}
|
onUpArrow={this.onUpArrow}
|
||||||
|
@ -757,6 +763,8 @@ MessageComposerInput.propTypes = {
|
||||||
|
|
||||||
onDownArrow: React.PropTypes.func,
|
onDownArrow: React.PropTypes.func,
|
||||||
|
|
||||||
|
onUploadFileSelected: React.PropTypes.func,
|
||||||
|
|
||||||
// attempts to confirm currently selected completion, returns whether actually confirmed
|
// attempts to confirm currently selected completion, returns whether actually confirmed
|
||||||
tryComplete: React.PropTypes.func,
|
tryComplete: React.PropTypes.func,
|
||||||
|
|
||||||
|
|
|
@ -311,7 +311,7 @@ export default React.createClass({
|
||||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createDialog(ErrorDialog, {
|
||||||
title: "Server error",
|
title: "Server error",
|
||||||
description: err.message
|
description: "Server unavailable, overloaded, or something else went wrong.",
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,9 +115,10 @@ module.exports = React.createClass({
|
||||||
changeAvatar.onFileSelected(ev).catch(function(err) {
|
changeAvatar.onFileSelected(ev).catch(function(err) {
|
||||||
var errMsg = (typeof err === "string") ? err : (err.error || "");
|
var errMsg = (typeof err === "string") ? err : (err.error || "");
|
||||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
|
console.error("Failed to set avatar: " + errMsg);
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createDialog(ErrorDialog, {
|
||||||
title: "Error",
|
title: "Error",
|
||||||
description: "Failed to set avatar. " + errMsg
|
description: "Failed to set avatar.",
|
||||||
});
|
});
|
||||||
}).done();
|
}).done();
|
||||||
},
|
},
|
||||||
|
|
|
@ -54,9 +54,10 @@ const BannedUser = React.createClass({
|
||||||
this.props.member.roomId, this.props.member.userId,
|
this.props.member.roomId, this.props.member.userId,
|
||||||
).catch((err) => {
|
).catch((err) => {
|
||||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
|
console.error("Failed to unban: " + err);
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createDialog(ErrorDialog, {
|
||||||
title: "Failed to unban",
|
title: "Error",
|
||||||
description: err.message,
|
description: "Failed to unban",
|
||||||
});
|
});
|
||||||
}).done();
|
}).done();
|
||||||
},
|
},
|
||||||
|
|
|
@ -102,9 +102,10 @@ function createRoom(opts) {
|
||||||
});
|
});
|
||||||
return roomId;
|
return roomId;
|
||||||
}, function(err) {
|
}, function(err) {
|
||||||
|
console.error("Failed to create room " + roomId + " " + err);
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createDialog(ErrorDialog, {
|
||||||
title: "Failure to create room",
|
title: "Failure to create room",
|
||||||
description: err.toString()
|
description: "Server may be unavailable, overloaded, or you hit a bug.",
|
||||||
});
|
});
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue