diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000000..c4c7fe5067 --- /dev/null +++ b/.eslintignore @@ -0,0 +1 @@ +src/component-index.js diff --git a/src/KeyCode.js b/src/KeyCode.js index bbe1ddcefa..c9cac01239 100644 --- a/src/KeyCode.js +++ b/src/KeyCode.js @@ -20,6 +20,7 @@ module.exports = { TAB: 9, ENTER: 13, SHIFT: 16, + ESCAPE: 27, PAGE_UP: 33, PAGE_DOWN: 34, END: 35, diff --git a/src/WhoIsTyping.js b/src/WhoIsTyping.js index 8c3838d615..96e76d618b 100644 --- a/src/WhoIsTyping.js +++ b/src/WhoIsTyping.js @@ -32,17 +32,24 @@ module.exports = { return whoIsTyping; }, - whoIsTypingString: function(room) { - var whoIsTyping = this.usersTypingApartFromMe(room); + whoIsTypingString: function(room, limit) { + const whoIsTyping = this.usersTypingApartFromMe(room); + const othersCount = limit === undefined ? + 0 : Math.max(whoIsTyping.length - limit, 0); if (whoIsTyping.length == 0) { - return null; + return ''; } else if (whoIsTyping.length == 1) { return whoIsTyping[0].name + ' is typing'; + } + const names = whoIsTyping.map(function(m) { + return m.name; + }); + if (othersCount) { + const other = ' other' + (othersCount > 1 ? 's' : ''); + return names.slice(0, limit).join(', ') + ' and ' + + othersCount + other + ' are typing'; } else { - var names = whoIsTyping.map(function(m) { - return m.name; - }); - var lastPerson = names.shift(); + const lastPerson = names.pop(); return names.join(', ') + ' and ' + lastPerson + ' are typing'; } } diff --git a/src/component-index.js b/src/component-index.js index 3b9cf0a80e..c50ee0dfc8 100644 --- a/src/component-index.js +++ b/src/component-index.js @@ -71,6 +71,8 @@ import views$create_room$Presets from './components/views/create_room/Presets'; views$create_room$Presets && (module.exports.components['views.create_room.Presets'] = views$create_room$Presets); import views$create_room$RoomAlias from './components/views/create_room/RoomAlias'; views$create_room$RoomAlias && (module.exports.components['views.create_room.RoomAlias'] = views$create_room$RoomAlias); +import views$dialogs$BaseDialog from './components/views/dialogs/BaseDialog'; +views$dialogs$BaseDialog && (module.exports.components['views.dialogs.BaseDialog'] = views$dialogs$BaseDialog); import views$dialogs$ChatInviteDialog from './components/views/dialogs/ChatInviteDialog'; views$dialogs$ChatInviteDialog && (module.exports.components['views.dialogs.ChatInviteDialog'] = views$dialogs$ChatInviteDialog); import views$dialogs$DeactivateAccountDialog from './components/views/dialogs/DeactivateAccountDialog'; @@ -79,8 +81,6 @@ import views$dialogs$ErrorDialog from './components/views/dialogs/ErrorDialog'; views$dialogs$ErrorDialog && (module.exports.components['views.dialogs.ErrorDialog'] = views$dialogs$ErrorDialog); import views$dialogs$InteractiveAuthDialog from './components/views/dialogs/InteractiveAuthDialog'; views$dialogs$InteractiveAuthDialog && (module.exports.components['views.dialogs.InteractiveAuthDialog'] = views$dialogs$InteractiveAuthDialog); -import views$dialogs$LogoutPrompt from './components/views/dialogs/LogoutPrompt'; -views$dialogs$LogoutPrompt && (module.exports.components['views.dialogs.LogoutPrompt'] = views$dialogs$LogoutPrompt); import views$dialogs$NeedToRegisterDialog from './components/views/dialogs/NeedToRegisterDialog'; views$dialogs$NeedToRegisterDialog && (module.exports.components['views.dialogs.NeedToRegisterDialog'] = views$dialogs$NeedToRegisterDialog); import views$dialogs$QuestionDialog from './components/views/dialogs/QuestionDialog'; diff --git a/src/components/structures/LoggedInView.js b/src/components/structures/LoggedInView.js index 57a4d4c721..c00bd2c6db 100644 --- a/src/components/structures/LoggedInView.js +++ b/src/components/structures/LoggedInView.js @@ -21,6 +21,7 @@ import KeyCode from '../../KeyCode'; import Notifier from '../../Notifier'; import PageTypes from '../../PageTypes'; import sdk from '../../index'; +import dis from '../../dispatcher'; /** * This is what our MatrixChat shows when we are logged in. The precise view is diff --git a/src/components/structures/RoomStatusBar.js b/src/components/structures/RoomStatusBar.js index c80c4db7cc..3ba73bb181 100644 --- a/src/components/structures/RoomStatusBar.js +++ b/src/components/structures/RoomStatusBar.js @@ -21,8 +21,6 @@ var WhoIsTyping = require("../../WhoIsTyping"); var MatrixClientPeg = require("../../MatrixClientPeg"); const MemberAvatar = require("../views/avatars/MemberAvatar"); -const TYPING_AVATARS_LIMIT = 2; - const HIDE_DEBOUNCE_MS = 10000; const STATUS_BAR_HIDDEN = 0; const STATUS_BAR_EXPANDED = 1; @@ -53,6 +51,10 @@ module.exports = React.createClass({ // more interesting) hasActiveCall: React.PropTypes.bool, + // Number of names to display in typing indication. E.g. set to 3, will + // result in "X, Y, Z and 100 others are typing." + whoIsTypingLimit: React.PropTypes.number, + // callback for when the user clicks on the 'resend all' button in the // 'unsent messages' bar onResendAllClick: React.PropTypes.func, @@ -77,10 +79,19 @@ module.exports = React.createClass({ onVisible: React.PropTypes.func, }, + getDefaultProps: function() { + return { + whoIsTypingLimit: 2, + }; + }, + getInitialState: function() { return { syncState: MatrixClientPeg.get().getSyncState(), - whoisTypingString: WhoIsTyping.whoIsTypingString(this.props.room), + whoisTypingString: WhoIsTyping.whoIsTypingString( + this.props.room, + this.props.whoIsTypingLimit + ), }; }, @@ -127,7 +138,10 @@ module.exports = React.createClass({ onRoomMemberTyping: function(ev, member) { this.setState({ - whoisTypingString: WhoIsTyping.whoIsTypingString(this.props.room), + whoisTypingString: WhoIsTyping.whoIsTypingString( + this.props.room, + this.props.whoIsTypingLimit + ), }); }, @@ -194,7 +208,7 @@ module.exports = React.createClass({ if (wantPlaceholder) { return (
This operation requires additional authentication.
{this._renderCurrentStage()} @@ -213,7 +204,7 @@ export default React.createClass({ {submitButton} {cancelButton}