Factor out a separate auxpanel, and cleanup the maxHeight management
Basically two changes here: 1. Factor out auxpanel from RoomView 2. Rather than setting maxHeight attributes by poking directly into the DOM, pass them down as properties.
This commit is contained in:
parent
bb6a36b911
commit
7a20fda7e7
6 changed files with 169 additions and 90 deletions
|
@ -70,6 +70,7 @@ module.exports.components['views.messages.TextualEvent'] = require('./components
|
||||||
module.exports.components['views.messages.UnknownBody'] = require('./components/views/messages/UnknownBody');
|
module.exports.components['views.messages.UnknownBody'] = require('./components/views/messages/UnknownBody');
|
||||||
module.exports.components['views.room_settings.AliasSettings'] = require('./components/views/room_settings/AliasSettings');
|
module.exports.components['views.room_settings.AliasSettings'] = require('./components/views/room_settings/AliasSettings');
|
||||||
module.exports.components['views.room_settings.ColorSettings'] = require('./components/views/room_settings/ColorSettings');
|
module.exports.components['views.room_settings.ColorSettings'] = require('./components/views/room_settings/ColorSettings');
|
||||||
|
module.exports.components['views.rooms.AuxPanel'] = require('./components/views/rooms/AuxPanel');
|
||||||
module.exports.components['views.rooms.EntityTile'] = require('./components/views/rooms/EntityTile');
|
module.exports.components['views.rooms.EntityTile'] = require('./components/views/rooms/EntityTile');
|
||||||
module.exports.components['views.rooms.EventTile'] = require('./components/views/rooms/EventTile');
|
module.exports.components['views.rooms.EventTile'] = require('./components/views/rooms/EventTile');
|
||||||
module.exports.components['views.rooms.InviteMemberList'] = require('./components/views/rooms/InviteMemberList');
|
module.exports.components['views.rooms.InviteMemberList'] = require('./components/views/rooms/InviteMemberList');
|
||||||
|
|
|
@ -15,7 +15,6 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// TODO: This component is enormous! There's several things which could stand-alone:
|
// TODO: This component is enormous! There's several things which could stand-alone:
|
||||||
// - Aux component
|
|
||||||
// - Search results component
|
// - Search results component
|
||||||
// - Drag and drop
|
// - Drag and drop
|
||||||
// - File uploading - uploadFile()
|
// - File uploading - uploadFile()
|
||||||
|
@ -106,6 +105,8 @@ module.exports = React.createClass({
|
||||||
// the end of the live timeline. It has the effect of hiding the
|
// the end of the live timeline. It has the effect of hiding the
|
||||||
// 'scroll to bottom' knob, among a couple of other things.
|
// 'scroll to bottom' knob, among a couple of other things.
|
||||||
atEndOfLiveTimeline: true,
|
atEndOfLiveTimeline: true,
|
||||||
|
|
||||||
|
auxPanelMaxHeight: undefined,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1294,14 +1295,6 @@ module.exports = React.createClass({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
onConferenceNotificationClick: function() {
|
|
||||||
dis.dispatch({
|
|
||||||
action: 'place_call',
|
|
||||||
type: "video",
|
|
||||||
room_id: this.props.roomId
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
// jump down to the bottom of this room, where new events are arriving
|
// jump down to the bottom of this room, where new events are arriving
|
||||||
jumpToLiveTimeline: function() {
|
jumpToLiveTimeline: function() {
|
||||||
// if we can't forward-paginate the existing timeline, then there
|
// if we can't forward-paginate the existing timeline, then there
|
||||||
|
@ -1386,25 +1379,10 @@ module.exports = React.createClass({
|
||||||
// but it's better than the video going missing entirely
|
// but it's better than the video going missing entirely
|
||||||
if (auxPanelMaxHeight < 50) auxPanelMaxHeight = 50;
|
if (auxPanelMaxHeight < 50) auxPanelMaxHeight = 50;
|
||||||
|
|
||||||
if (this.refs.callView) {
|
// we may need to resize the gemini panel after changing the aux panel
|
||||||
var fullscreenElement =
|
// size, so add a callback to onChildResize.
|
||||||
(document.fullscreenElement ||
|
this.setState({auxPanelMaxHeight: auxPanelMaxHeight},
|
||||||
document.mozFullScreenElement ||
|
this.onChildResize);
|
||||||
document.webkitFullscreenElement);
|
|
||||||
if (!fullscreenElement) {
|
|
||||||
var video = this.refs.callView.getVideoView().getRemoteVideoElement();
|
|
||||||
video.style.maxHeight = auxPanelMaxHeight + "px";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// we need to do this for general auxPanels too
|
|
||||||
if (this.refs.auxPanel) {
|
|
||||||
this.refs.auxPanel.style.maxHeight = auxPanelMaxHeight + "px";
|
|
||||||
}
|
|
||||||
|
|
||||||
// the above might have made the aux panel resize itself, so now
|
|
||||||
// we need to tell the gemini panel to adapt.
|
|
||||||
this.onChildResize();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
onFullscreenClick: function() {
|
onFullscreenClick: function() {
|
||||||
|
@ -1438,11 +1416,6 @@ module.exports = React.createClass({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
onCallViewResize: function() {
|
|
||||||
this.onChildResize();
|
|
||||||
this.onResize();
|
|
||||||
},
|
|
||||||
|
|
||||||
onChildResize: function() {
|
onChildResize: function() {
|
||||||
// When the video or the message composer resizes, the scroll panel
|
// When the video or the message composer resizes, the scroll panel
|
||||||
// also changes size. Work around GeminiScrollBar fail by telling it
|
// also changes size. Work around GeminiScrollBar fail by telling it
|
||||||
|
@ -1464,8 +1437,8 @@ module.exports = React.createClass({
|
||||||
render: function() {
|
render: function() {
|
||||||
var RoomHeader = sdk.getComponent('rooms.RoomHeader');
|
var RoomHeader = sdk.getComponent('rooms.RoomHeader');
|
||||||
var MessageComposer = sdk.getComponent('rooms.MessageComposer');
|
var MessageComposer = sdk.getComponent('rooms.MessageComposer');
|
||||||
var CallView = sdk.getComponent("voip.CallView");
|
|
||||||
var RoomSettings = sdk.getComponent("rooms.RoomSettings");
|
var RoomSettings = sdk.getComponent("rooms.RoomSettings");
|
||||||
|
var AuxPanel = sdk.getComponent("rooms.AuxPanel");
|
||||||
var SearchBar = sdk.getComponent("rooms.SearchBar");
|
var SearchBar = sdk.getComponent("rooms.SearchBar");
|
||||||
var ScrollPanel = sdk.getComponent("structures.ScrollPanel");
|
var ScrollPanel = sdk.getComponent("structures.ScrollPanel");
|
||||||
var TintableSvg = sdk.getComponent("elements.TintableSvg");
|
var TintableSvg = sdk.getComponent("elements.TintableSvg");
|
||||||
|
@ -1607,28 +1580,16 @@ module.exports = React.createClass({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
var conferenceCallNotification = null;
|
var auxPanel = (
|
||||||
if (this.state.displayConfCallNotification) {
|
<AuxPanel ref="auxPanel" room={this.state.room}
|
||||||
var supportedText;
|
conferenceHandler={this.props.ConferenceHandler}
|
||||||
if (!MatrixClientPeg.get().supportsVoip()) {
|
draggingFile={this.state.draggingFile}
|
||||||
supportedText = " (unsupported)";
|
displayConfCallNotification={this.state.displayConfCallNotification}
|
||||||
}
|
maxHeight={this.state.auxPanelMaxHeight}
|
||||||
conferenceCallNotification = (
|
onCallViewVideoRezize={this.onChildResize} >
|
||||||
<div className="mx_RoomView_ongoingConfCallNotification" onClick={this.onConferenceNotificationClick}>
|
{ aux }
|
||||||
Ongoing conference call {supportedText}
|
</AuxPanel>
|
||||||
</div>
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
var fileDropTarget = null;
|
|
||||||
if (this.state.draggingFile) {
|
|
||||||
fileDropTarget = <div className="mx_RoomView_fileDropTarget">
|
|
||||||
<div className="mx_RoomView_fileDropTargetLabel" title="Drop File Here">
|
|
||||||
<TintableSvg src="img/upload-big.svg" width="45" height="59"/><br/>
|
|
||||||
Drop file here to upload
|
|
||||||
</div>
|
|
||||||
</div>;
|
|
||||||
}
|
|
||||||
|
|
||||||
var messageComposer, searchInfo;
|
var messageComposer, searchInfo;
|
||||||
var canSpeak = (
|
var canSpeak = (
|
||||||
|
@ -1759,13 +1720,7 @@ module.exports = React.createClass({
|
||||||
onLeaveClick={
|
onLeaveClick={
|
||||||
(myMember && myMember.membership === "join") ? this.onLeaveClick : null
|
(myMember && myMember.membership === "join") ? this.onLeaveClick : null
|
||||||
} />
|
} />
|
||||||
<div className="mx_RoomView_auxPanel" ref="auxPanel">
|
{ auxPanel }
|
||||||
{ fileDropTarget }
|
|
||||||
<CallView ref="callView" room={this.state.room} ConferenceHandler={this.props.ConferenceHandler}
|
|
||||||
onResize={this.onCallViewResize} />
|
|
||||||
{ conferenceCallNotification }
|
|
||||||
{ aux }
|
|
||||||
</div>
|
|
||||||
{ messagePanel }
|
{ messagePanel }
|
||||||
{ searchResultsPanel }
|
{ searchResultsPanel }
|
||||||
<div className="mx_RoomView_statusArea">
|
<div className="mx_RoomView_statusArea">
|
||||||
|
|
104
src/components/views/rooms/AuxPanel.js
Normal file
104
src/components/views/rooms/AuxPanel.js
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
/*
|
||||||
|
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 MatrixClientPeg = require("../../../MatrixClientPeg");
|
||||||
|
var sdk = require('../../../index');
|
||||||
|
var dis = require("../../../dispatcher");
|
||||||
|
|
||||||
|
module.exports = React.createClass({
|
||||||
|
displayName: 'AuxPanel',
|
||||||
|
|
||||||
|
propTypes: {
|
||||||
|
// js-sdk room object
|
||||||
|
room: React.PropTypes.object.isRequired,
|
||||||
|
|
||||||
|
// Conference Handler implementation
|
||||||
|
conferenceHandler: React.PropTypes.object,
|
||||||
|
|
||||||
|
// set to true to show the file drop target
|
||||||
|
draggingFile: React.PropTypes.bool,
|
||||||
|
|
||||||
|
// set to true to show the 'active conf call' banner
|
||||||
|
displayConfCallNotification: React.PropTypes.bool,
|
||||||
|
|
||||||
|
// maxHeight attribute for the aux panel and the video
|
||||||
|
// therein
|
||||||
|
maxHeight: React.PropTypes.number,
|
||||||
|
|
||||||
|
// a callback which is called when the video element in a voip call is
|
||||||
|
// resized due to a change in video metadata
|
||||||
|
onCallViewVideoResize: React.PropTypes.func,
|
||||||
|
},
|
||||||
|
|
||||||
|
onConferenceNotificationClick: function() {
|
||||||
|
dis.dispatch({
|
||||||
|
action: 'place_call',
|
||||||
|
type: "video",
|
||||||
|
room_id: this.props.room.roomId,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
render: function() {
|
||||||
|
var CallView = sdk.getComponent("voip.CallView");
|
||||||
|
var TintableSvg = sdk.getComponent("elements.TintableSvg");
|
||||||
|
|
||||||
|
var fileDropTarget = null;
|
||||||
|
if (this.props.draggingFile) {
|
||||||
|
fileDropTarget = (
|
||||||
|
<div className="mx_RoomView_fileDropTarget">
|
||||||
|
<div className="mx_RoomView_fileDropTargetLabel"
|
||||||
|
title="Drop File Here">
|
||||||
|
<TintableSvg src="img/upload-big.svg" width="45" height="59"/>
|
||||||
|
<br/>
|
||||||
|
Drop file here to upload
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
var conferenceCallNotification = null;
|
||||||
|
if (this.props.displayConfCallNotification) {
|
||||||
|
var supportedText;
|
||||||
|
if (!MatrixClientPeg.get().supportsVoip()) {
|
||||||
|
supportedText = " (unsupported)";
|
||||||
|
}
|
||||||
|
conferenceCallNotification = (
|
||||||
|
<div className="mx_RoomView_ongoingConfCallNotification"
|
||||||
|
onClick={this.onConferenceNotificationClick}>
|
||||||
|
Ongoing conference call {supportedText}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
var callView = (
|
||||||
|
<CallView ref="callView" room={this.props.room}
|
||||||
|
ConferenceHandler={this.props.conferenceHandler}
|
||||||
|
onResize={this.props.onCallViewVideoResize}
|
||||||
|
maxVideoHeight={this.props.maxHeight}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="mx_RoomView_auxPanel" style={{maxHeight: this.props.maxHeight}} >
|
||||||
|
{ fileDropTarget }
|
||||||
|
{ callView }
|
||||||
|
{ conferenceCallNotification }
|
||||||
|
{ this.props.children }
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
|
@ -19,38 +19,32 @@ var CallHandler = require("../../../CallHandler");
|
||||||
var sdk = require('../../../index');
|
var sdk = require('../../../index');
|
||||||
var MatrixClientPeg = require("../../../MatrixClientPeg");
|
var MatrixClientPeg = require("../../../MatrixClientPeg");
|
||||||
|
|
||||||
/*
|
|
||||||
* State vars:
|
|
||||||
* this.state.call = MatrixCall|null
|
|
||||||
*
|
|
||||||
* Props:
|
|
||||||
* this.props.room = Room (JS SDK)
|
|
||||||
* this.props.ConferenceHandler = A Conference Handler implementation
|
|
||||||
* Must have a function signature:
|
|
||||||
* getConferenceCallForRoom(roomId: string): MatrixCall
|
|
||||||
*/
|
|
||||||
|
|
||||||
module.exports = React.createClass({
|
module.exports = React.createClass({
|
||||||
displayName: 'CallView',
|
displayName: 'CallView',
|
||||||
|
|
||||||
propTypes: {
|
propTypes: {
|
||||||
// a callback which is called when the video within the callview
|
// js-sdk room object
|
||||||
// due to a change in video metadata
|
room: React.PropTypes.object.isRequired,
|
||||||
|
|
||||||
|
// A Conference Handler implementation
|
||||||
|
// Must have a function signature:
|
||||||
|
// getConferenceCallForRoom(roomId: string): MatrixCall
|
||||||
|
ConferenceHandler: React.PropTypes.object,
|
||||||
|
|
||||||
|
// maxHeight style attribute for the video panel
|
||||||
|
maxVideoHeight: React.PropTypes.number,
|
||||||
|
|
||||||
|
// a callback which is called when the user clicks on the video div
|
||||||
|
onClick: React.PropTypes.func,
|
||||||
|
|
||||||
|
// a callback which is called when the video within the callview is
|
||||||
|
// resized due to a change in video metadata
|
||||||
onResize: React.PropTypes.func,
|
onResize: React.PropTypes.func,
|
||||||
},
|
},
|
||||||
|
|
||||||
componentDidMount: function() {
|
componentDidMount: function() {
|
||||||
this.dispatcherRef = dis.register(this.onAction);
|
this.dispatcherRef = dis.register(this.onAction);
|
||||||
if (this.props.room) {
|
this.showCall(this.props.room.roomId);
|
||||||
this.showCall(this.props.room.roomId);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// XXX: why would we ever not have a this.props.room?
|
|
||||||
var call = CallHandler.getAnyActiveCall();
|
|
||||||
if (call) {
|
|
||||||
this.showCall(call.roomId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
componentWillUnmount: function() {
|
componentWillUnmount: function() {
|
||||||
|
@ -103,7 +97,10 @@ module.exports = React.createClass({
|
||||||
render: function(){
|
render: function(){
|
||||||
var VideoView = sdk.getComponent('voip.VideoView');
|
var VideoView = sdk.getComponent('voip.VideoView');
|
||||||
return (
|
return (
|
||||||
<VideoView ref="video" onClick={ this.props.onClick } onResize={ this.props.onResize }/>
|
<VideoView ref="video" onClick={ this.props.onClick }
|
||||||
|
onResize={ this.props.onResize }
|
||||||
|
maxHeight={ this.props.maxVideoHeight }
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -22,6 +22,9 @@ module.exports = React.createClass({
|
||||||
displayName: 'VideoFeed',
|
displayName: 'VideoFeed',
|
||||||
|
|
||||||
propTypes: {
|
propTypes: {
|
||||||
|
// maxHeight style attribute for the video element
|
||||||
|
maxHeight: React.PropTypes.number,
|
||||||
|
|
||||||
// a callback which is called when the video element is resized
|
// a callback which is called when the video element is resized
|
||||||
// due to a change in video metadata
|
// due to a change in video metadata
|
||||||
onResize: React.PropTypes.func,
|
onResize: React.PropTypes.func,
|
||||||
|
@ -43,7 +46,7 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
return (
|
return (
|
||||||
<video ref="vid">
|
<video ref="vid" style={{maxHeight: this.props.maxHeight}}>
|
||||||
</video>
|
</video>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
|
@ -25,6 +25,18 @@ var dis = require('../../../dispatcher');
|
||||||
module.exports = React.createClass({
|
module.exports = React.createClass({
|
||||||
displayName: 'VideoView',
|
displayName: 'VideoView',
|
||||||
|
|
||||||
|
propTypes: {
|
||||||
|
// maxHeight style attribute for the video element
|
||||||
|
maxHeight: React.PropTypes.number,
|
||||||
|
|
||||||
|
// a callback which is called when the user clicks on the video div
|
||||||
|
onClick: React.PropTypes.func,
|
||||||
|
|
||||||
|
// a callback which is called when the video element is resized due to
|
||||||
|
// a change in video metadata
|
||||||
|
onResize: React.PropTypes.func,
|
||||||
|
},
|
||||||
|
|
||||||
componentDidMount: function() {
|
componentDidMount: function() {
|
||||||
this.dispatcherRef = dis.register(this.onAction);
|
this.dispatcherRef = dis.register(this.onAction);
|
||||||
},
|
},
|
||||||
|
@ -64,7 +76,6 @@ module.exports = React.createClass({
|
||||||
element.msRequestFullscreen
|
element.msRequestFullscreen
|
||||||
);
|
);
|
||||||
requestMethod.call(element);
|
requestMethod.call(element);
|
||||||
this.getRemoteVideoElement().style.maxHeight = "inherit";
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
var exitMethod = (
|
var exitMethod = (
|
||||||
|
@ -83,10 +94,18 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
var VideoFeed = sdk.getComponent('voip.VideoFeed');
|
var VideoFeed = sdk.getComponent('voip.VideoFeed');
|
||||||
|
|
||||||
|
// if we're fullscreen, we don't want to set a maxHeight on the video element.
|
||||||
|
var fullscreenElement = (document.fullscreenElement ||
|
||||||
|
document.mozFullScreenElement ||
|
||||||
|
document.webkitFullscreenElement);
|
||||||
|
var maxVideoHeight = fullscreenElement ? null : this.props.maxHeight;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mx_VideoView" ref={this.setContainer} onClick={ this.props.onClick }>
|
<div className="mx_VideoView" ref={this.setContainer} onClick={ this.props.onClick }>
|
||||||
<div className="mx_VideoView_remoteVideoFeed">
|
<div className="mx_VideoView_remoteVideoFeed">
|
||||||
<VideoFeed ref="remote" onResize={this.props.onResize}/>
|
<VideoFeed ref="remote" onResize={this.props.onResize}
|
||||||
|
maxHeight={maxVideoHeight} />
|
||||||
<audio ref="remoteAudio"/>
|
<audio ref="remoteAudio"/>
|
||||||
</div>
|
</div>
|
||||||
<div className="mx_VideoView_localVideoFeed">
|
<div className="mx_VideoView_localVideoFeed">
|
||||||
|
|
Loading…
Reference in a new issue