diff --git a/src/Unread.js b/src/Unread.js index 2b33fec829..d7490c8632 100644 --- a/src/Unread.js +++ b/src/Unread.js @@ -23,7 +23,9 @@ module.exports = { * count of unread messages */ eventTriggersUnreadCount: function(ev) { - if (ev.getType() == "m.room.member") { + if (ev.sender && ev.sender.userId == MatrixClientPeg.get().credentials.userId) { + return false; + } else if (ev.getType() == "m.room.member") { return false; } else if (ev.getType == 'm.room.message' && ev.getContent().msgtype == 'm.notify') { return false; diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index f8db14b854..7713782252 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -96,6 +96,14 @@ module.exports = React.createClass({ if (!this.props.config || !this.props.config.default_hs_url) { console.error("Cannot enable guest access: No supplied config prop for HS/IS URLs"); } + else if (this.props.startingQueryParams.email) { + console.log("Not registering as guest; email invite."); + this._autoRegisterAsGuest = false; + } + else if (this.props.startingQueryParams.client_secret && this.props.startingQueryParams.sid) { + console.log("Not registering as guest; registration."); + this._autoRegisterAsGuest = false; + } else { this._autoRegisterAsGuest = true; } @@ -200,7 +208,6 @@ module.exports = React.createClass({ }); break; case 'start_registration': - if (this.state.logged_in) return; var newState = payload.params || {}; newState.screen = 'register'; if ( @@ -635,6 +642,14 @@ module.exports = React.createClass({ action: 'start_post_registration', }); } else if (screen.indexOf('room/') == 0) { + + if (!this.state.logged_in && this.props.startingQueryParams.email) { + console.log("Redirecting to email registration"); + this.showScreen("register"); + this.notifyNewScreen('register'); // this doesn't call showScreen, just updates the hash + return; + } + var roomString = screen.split('/')[1]; if (roomString[0] == '#') { if (this.state.logged_in) { @@ -656,7 +671,7 @@ module.exports = React.createClass({ } } else { - if (screen) console.error("Unknown screen : %s", screen); + console.error("Unknown screen : %s", screen); } }, @@ -809,6 +824,7 @@ module.exports = React.createClass({ var CreateRoom = sdk.getComponent('structures.CreateRoom'); var RoomDirectory = sdk.getComponent('structures.RoomDirectory'); var MatrixToolbar = sdk.getComponent('globals.MatrixToolbar'); + var GuestWarningBar = sdk.getComponent('globals.GuestWarningBar'); var ForgotPassword = sdk.getComponent('structures.login.ForgotPassword'); // needs to be before normal PageTypes as you are logged in technically @@ -849,7 +865,20 @@ module.exports = React.createClass({ } // TODO: Fix duplication here and do conditionals like we do above - if (Notifier.supportsDesktopNotifications() && !Notifier.isEnabled() && !Notifier.isToolbarHidden()) { + if (MatrixClientPeg.get().isGuest()) { + return ( +
+ +
+ +
+ {page_element} +
+ {right_panel} +
+
+ ); + } else if (Notifier.supportsDesktopNotifications() && !Notifier.isEnabled() && !Notifier.isToolbarHidden()) { return (
diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 6cc90bfc7d..5dbdb1c56d 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -933,7 +933,7 @@ module.exports = React.createClass({ var hr; hr = (
); ret.splice(ghostIndex, 0, ( diff --git a/src/components/structures/ScrollPanel.js b/src/components/structures/ScrollPanel.js index 8d26b2e365..e19b041219 100644 --- a/src/components/structures/ScrollPanel.js +++ b/src/components/structures/ScrollPanel.js @@ -160,8 +160,8 @@ module.exports = React.createClass({ // content. So don't call it in render() cycles. isAtBottom: function() { var sn = this._getScrollNode(); - // + 1 here to avoid fractional pixel rounding errors - return sn.scrollHeight - sn.scrollTop <= sn.clientHeight + 1; + // + 2 here to avoid fractional pixel rounding errors + return sn.scrollHeight - sn.scrollTop <= sn.clientHeight + 2; }, // check the scroll state and send out backfill requests if necessary. diff --git a/src/components/structures/UserSettings.js b/src/components/structures/UserSettings.js index cadea6e220..9bf0793fc3 100644 --- a/src/components/structures/UserSettings.js +++ b/src/components/structures/UserSettings.js @@ -148,7 +148,8 @@ module.exports = React.createClass({ onUpgradeClicked: function() { dis.dispatch({ - action: "start_upgrade_registration" + //action: "start_upgrade_registration" + action: "start_registration" // temporary (https://github.com/vector-im/vector-web/issues/818) }); }, diff --git a/src/components/views/login/ServerConfig.js b/src/components/views/login/ServerConfig.js index 741f0ebc69..fe80a0d61b 100644 --- a/src/components/views/login/ServerConfig.js +++ b/src/components/views/login/ServerConfig.js @@ -58,7 +58,7 @@ module.exports = React.createClass({ onHomeserverChanged: function(ev) { this.setState({hs_url: ev.target.value}, function() { this._hsTimeoutId = this._waitThenInvoke(this._hsTimeoutId, function() { - this.props.onHsUrlChanged(this.state.hs_url); + this.props.onHsUrlChanged(this.state.hs_url.replace(/\/$/, "")); }); }); }, @@ -66,7 +66,7 @@ module.exports = React.createClass({ onIdentityServerChanged: function(ev) { this.setState({is_url: ev.target.value}, function() { this._isTimeoutId = this._waitThenInvoke(this._isTimeoutId, function() { - this.props.onIsUrlChanged(this.state.is_url); + this.props.onIsUrlChanged(this.state.is_url.replace(/\/$/, "")); }); }); }, diff --git a/src/components/views/rooms/MemberList.js b/src/components/views/rooms/MemberList.js index 2d4fd39205..f2f0b03234 100644 --- a/src/components/views/rooms/MemberList.js +++ b/src/components/views/rooms/MemberList.js @@ -29,6 +29,8 @@ var SHARE_HISTORY_WARNING = "Newly invited users will see the history of this ro "turn off, 'Share message history with new users' in the settings for this room."; var shown_invite_warning_this_session = false; +// global promise so people can bulk invite and they all get resolved +var invite_defer = q.defer(); module.exports = React.createClass({ displayName: 'MemberList', @@ -158,6 +160,20 @@ module.exports = React.createClass({ var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); var self = this; inputText = inputText.trim(); // react requires es5-shim so we know trim() exists + + // email addresses and user IDs do not allow space, comma, semicolon so split + // on them for bulk inviting. + var separators =[ ";", " ", "," ]; + for (var i = 0; i < separators.length; i++) { + if (inputText.indexOf(separators[i]) >= 0) { + var inputs = inputText.split(separators[i]); + inputs.forEach(function(input) { + self.onInvite(input); + }); + return; + } + } + var isEmailAddress = /^\S+@\S+\.\S+$/.test(inputText); // sanity check the input for user IDs @@ -170,13 +186,14 @@ module.exports = React.createClass({ return; } - var invite_defer = q.defer(); + var inviteWarningDefer = q.defer(); var room = MatrixClientPeg.get().getRoom(this.props.roomId); var history_visibility = room.currentState.getStateEvents('m.room.history_visibility', ''); if (history_visibility) history_visibility = history_visibility.getContent().history_visibility; if (history_visibility == 'shared' && !shown_invite_warning_this_session) { + inviteWarningDefer = invite_defer; // whether we continue depends on this defer var QuestionDialog = sdk.getComponent("dialogs.QuestionDialog"); Modal.createDialog(QuestionDialog, { title: "Warning", @@ -188,14 +205,17 @@ module.exports = React.createClass({ invite_defer.resolve(); } else { invite_defer.reject(null); + // reset the promise so we don't auto-reject all invites from + // now on. + invite_defer = q.defer(); } } }); } else { - invite_defer.resolve(); + inviteWarningDefer.resolve(); } - var promise = invite_defer.promise;; + var promise = inviteWarningDefer.promise; if (isEmailAddress) { promise = promise.then(function() { MatrixClientPeg.get().inviteByEmail(self.props.roomId, inputText); @@ -214,7 +234,7 @@ module.exports = React.createClass({ "Invite %s to %s - isEmail=%s", inputText, this.props.roomId, isEmailAddress ); promise.done(function(res) { - console.log("Invited"); + console.log("Invited %s", inputText); self.setState({ inviting: false });