diff --git a/reskindex.js b/reskindex.js index 66dfc39f73..37b3345e36 100755 --- a/reskindex.js +++ b/reskindex.js @@ -26,6 +26,9 @@ strm.write(" * THIS FILE IS AUTO-GENERATED\n"); strm.write(" * You can edit it you like, but your changes will be overwritten,\n"); strm.write(" * so you'd just be trying to swim upstream like a salmon.\n"); strm.write(" * You are not a salmon.\n"); +strm.write(" *\n"); +strm.write(" * To update it, run:\n"); +strm.write(" * ./reskindex.js -h header\n"); strm.write(" */\n\n"); if (packageJson['matrix-react-parent']) { diff --git a/src/component-index.js b/src/component-index.js index b4452c7902..5a37a98913 100644 --- a/src/component-index.js +++ b/src/component-index.js @@ -19,6 +19,9 @@ limitations under the License. * You can edit it you like, but your changes will be overwritten, * so you'd just be trying to swim upstream like a salmon. * You are not a salmon. + * + * To update it, run: + * ./reskindex.js -h header */ module.exports.components = {}; @@ -28,6 +31,7 @@ module.exports.components['structures.login.Login'] = require('./components/stru module.exports.components['structures.login.PostRegistration'] = require('./components/structures/login/PostRegistration'); module.exports.components['structures.login.Registration'] = require('./components/structures/login/Registration'); module.exports.components['structures.MatrixChat'] = require('./components/structures/MatrixChat'); +module.exports.components['structures.RoomStatusBar'] = require('./components/structures/RoomStatusBar'); module.exports.components['structures.RoomView'] = require('./components/structures/RoomView'); module.exports.components['structures.ScrollPanel'] = require('./components/structures/ScrollPanel'); module.exports.components['structures.UploadBar'] = require('./components/structures/UploadBar'); diff --git a/src/components/structures/RoomStatusBar.js b/src/components/structures/RoomStatusBar.js new file mode 100644 index 0000000000..c15a33d777 --- /dev/null +++ b/src/components/structures/RoomStatusBar.js @@ -0,0 +1,180 @@ +/* +Copyright 2015, 2016 OpenMarket 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. +*/ + +var React = require('react'); +var sdk = require('../../index'); +var dis = require("../../dispatcher"); +var WhoIsTyping = require("../../WhoIsTyping"); +var MatrixClientPeg = require("../../MatrixClientPeg"); + +module.exports = React.createClass({ + displayName: 'RoomStatusBar', + + propTypes: { + // the room this statusbar is representing. + room: React.PropTypes.object.isRequired, + + // a list of TabCompleteEntries.Entry objects + tabCompleteEntries: React.PropTypes.array, + + // the number of messages which have arrived since we've been scrolled up + numUnreadMessages: React.PropTypes.number, + + // true if there are messages in the room which had errors on send + hasUnsentMessages: React.PropTypes.bool, + + // this is true if we are fully scrolled-down, and are looking at + // the end of the live timeline. + atEndOfLiveTimeline: React.PropTypes.bool, + + // true if there is an active call in this room (means we show + // the 'Active Call' text in the status bar if there is nothing + // more interesting) + hasActiveCall: React.PropTypes.bool, + + // callback for when the user clicks on the 'resend all' button in the + // 'unsent messages' bar + onResendAllClick: React.PropTypes.func, + + // callback for when the user clicks on the 'scroll to bottom' button + onScrollToBottomClick: React.PropTypes.func, + }, + + getInitialState: function() { + return { + syncState: MatrixClientPeg.get().getSyncState(), + }; + }, + + componentWillMount: function() { + MatrixClientPeg.get().on("sync", this.onSyncStateChange); + }, + + componentWillUnmount: function() { + MatrixClientPeg.get().removeListener("sync", this.onSyncStateChange); + }, + + onSyncStateChange: function(state, prevState) { + if (state === "SYNCING" && prevState === "SYNCING") { + return; + } + this.setState({ + syncState: state + }); + }, + + render: function() { + var TabCompleteBar = sdk.getComponent('rooms.TabCompleteBar'); + var TintableSvg = sdk.getComponent("elements.TintableSvg"); + + // no conn bar trumps unread count since you can't get unread messages + // without a connection! (technically may already have some but meh) + // It also trumps the "some not sent" msg since you can't resend without + // a connection! + if (this.state.syncState === "ERROR") { + return ( +
+ /!\ +
+
+ Connectivity to the server has been lost. +
+
+ Sent messages will be stored until your connection has returned. +
+
+
+ ); + } + + if (this.props.tabCompleteEntries) { + return ( +
+
...
+
+ +
+ + Auto-complete +
+
+
+ ); + } + + if (this.props.hasUnsentMessages) { + return ( +
+ /!\ +
+
+ Some of your messages have not been sent. +
+
+ + Resend all now + or select individual messages to re-send. +
+
+
+ ); + } + + // unread count trumps who is typing since the unread count is only + // set when you've scrolled up + if (this.props.numUnreadMsgs) { + var unreadMsgs = this.props.numUnreadMessages + " new message" + + (this.props.numUnreadMessages > 1 ? "s" : ""); + + return ( +
+ + {unreadMsgs} +
+ ); + } + + var typingString = WhoIsTyping.whoIsTypingString(this.props.room); + if (typingString) { + return ( +
+
...
+ {typingString} +
+ ); + } + + if (!this.props.atEndOfLiveTimeline) { + return ( +
+ Scroll to bottom of page +
+ ); + } + + if (this.props.hasActiveCall) { + return ( +
+ + Active call +
+ ); + } + + return
; + }, +}); diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 78c206a28a..820aaf407a 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -30,7 +30,6 @@ var EventTimeline = Matrix.EventTimeline; var MatrixClientPeg = require("../../MatrixClientPeg"); var ContentMessages = require("../../ContentMessages"); -var WhoIsTyping = require("../../WhoIsTyping"); var Modal = require("../../Modal"); var sdk = require('../../index'); var CallHandler = require('../../CallHandler'); @@ -104,7 +103,6 @@ module.exports = React.createClass({ draggingFile: false, searching: false, searchResults: null, - syncState: MatrixClientPeg.get().getSyncState(), hasUnsentMessages: this._hasUnsentMessages(room), callState: null, timelineLoading: true, // track whether our room timeline is loading @@ -130,7 +128,6 @@ module.exports = React.createClass({ MatrixClientPeg.get().on("Room.receipt", this.onRoomReceipt); MatrixClientPeg.get().on("RoomMember.typing", this.onRoomMemberTyping); MatrixClientPeg.get().on("RoomState.members", this.onRoomStateMember); - MatrixClientPeg.get().on("sync", this.onSyncStateChange); // xchat-style tab complete, add a colon if tab // completing at the start of the text this.tabComplete = new TabComplete({ @@ -286,7 +283,6 @@ module.exports = React.createClass({ MatrixClientPeg.get().removeListener("Room.receipt", this.onRoomReceipt); MatrixClientPeg.get().removeListener("RoomMember.typing", this.onRoomMemberTyping); MatrixClientPeg.get().removeListener("RoomState.members", this.onRoomStateMember); - MatrixClientPeg.get().removeListener("sync", this.onSyncStateChange); } window.removeEventListener('resize', this.onResize); @@ -352,15 +348,6 @@ module.exports = React.createClass({ } }, - onSyncStateChange: function(state, prevState) { - if (state === "SYNCING" && prevState === "SYNCING") { - return; - } - this.setState({ - syncState: state - }); - }, - componentWillReceiveProps: function(newProps) { if (newProps.roomId != this.props.roomId) { throw new Error("changing room on a RoomView is not supported"); @@ -833,10 +820,6 @@ module.exports = React.createClass({ }); }, - getWhoIsTypingString: function() { - return WhoIsTyping.whoIsTypingString(this.state.room); - }, - onSearch: function(term, scope) { this.setState({ searchTerm: term, @@ -1320,13 +1303,6 @@ module.exports = React.createClass({ }); }, - getUnreadMessagesString: function() { - if (!this.state.numUnreadMessages) { - return ""; - } - return this.state.numUnreadMessages + " new message" + (this.state.numUnreadMessages > 1 ? "s" : ""); - }, - // jump down to the bottom of this room, where new events are arriving jumpToLiveTimeline: function() { // if we can't forward-paginate the existing timeline, then there @@ -1559,6 +1535,12 @@ module.exports = React.createClass({ // We have successfully loaded this room, and are not previewing. // Display the "normal" room view. + var call = CallHandler.getCallForRoom(this.props.roomId); + var inCall = false; + if (call && (this.state.callState !== 'ended' && this.state.callState !== 'ringing')) { + inCall = true; + } + var scrollheader_classes = classNames({ mx_RoomView_scrollheader: true, loading: this.state.paginating @@ -1577,86 +1559,20 @@ module.exports = React.createClass({ var UploadBar = sdk.getComponent('structures.UploadBar'); statusBar = } else if (!this.state.searchResults) { - var typingString = this.getWhoIsTypingString(); - // typingString = "S͚͍̭̪̤͙̱͙̖̥͙̥̤̻̙͕͓͂̌ͬ͐̂k̜̝͎̰̥̻̼̂̌͛͗͊̅̒͂̊̍̍͌̈̈́͌̋̊ͬa͉̯͚̺̗̳̩ͪ̋̑͌̓̆̍̂̉̏̅̆ͧ̌̑v̲̲̪̝ͥ̌ͨͮͭ̊͆̾ͮ̍ͮ͑̚e̮̙͈̱̘͕̼̮͒ͩͨͫ̃͗̇ͩ͒ͣͦ͒̄̍͐ͣ̿ͥṘ̗̺͇̺̺͔̄́̊̓͊̍̃ͨ̚ā̼͎̘̟̼͎̜̪̪͚̋ͨͨͧ̓ͦͯͤ̄͆̋͂ͩ͌ͧͅt̙̙̹̗̦͖̞ͫͪ͑̑̅ͪ̃̚ͅ is typing..."; - var unreadMsgs = this.getUnreadMessagesString(); - // no conn bar trumps unread count since you can't get unread messages - // without a connection! (technically may already have some but meh) - // It also trumps the "some not sent" msg since you can't resend without - // a connection! - if (this.state.syncState === "ERROR") { - statusBar = ( -
- /!\ -
-
- Connectivity to the server has been lost. -
-
- Sent messages will be stored until your connection has returned. -
-
-
- ); - } - else if (this.tabComplete.isTabCompleting()) { - var TabCompleteBar = sdk.getComponent('rooms.TabCompleteBar'); - statusBar = ( -
-
...
-
- -
- - Auto-complete -
-
-
- ); - } - else if (this.state.hasUnsentMessages) { - statusBar = ( -
- /!\ -
-
- Some of your messages have not been sent. -
-
- - Resend all now - or select individual messages to re-send. -
-
-
- ); - } - // unread count trumps who is typing since the unread count is only - // set when you've scrolled up - else if (unreadMsgs) { - statusBar = ( -
- - {unreadMsgs} -
- ); - } - else if (typingString) { - statusBar = ( -
-
...
- {typingString} -
- ); - } - else if (!this.state.atEndOfLiveTimeline) { - statusBar = ( -
- Scroll to bottom of page -
- ); - } + var RoomStatusBar = sdk.getComponent('structures.RoomStatusBar'); + var tabEntries = this.tabComplete.isTabCompleting() ? + this.tabComplete.peek(6) : null; + + statusBar = } var aux = null; @@ -1727,11 +1643,7 @@ module.exports = React.createClass({ }; } - var call = CallHandler.getCallForRoom(this.props.roomId); - //var call = CallHandler.getAnyActiveCall(); - var inCall = false; - if (call && (this.state.callState !== 'ended' && this.state.callState !== 'ringing')) { - inCall = true; + if (inCall) { var zoomButton, voiceMuteButton, videoMuteButton; if (call.type === "video") { @@ -1755,14 +1667,7 @@ module.exports = React.createClass({ width="21" height="26"/>
- if (!statusBar) { - statusBar = -
- - Active call -
; - } - + // wrap the existing status bar into a 'callStatusBar' which adds more knobs. statusBar =
{ voiceMuteButton }