Merge branch 'develop' of github.com:havfo/multiparty-meeting into feat/file-sharing
* 'develop' of github.com:havfo/multiparty-meeting: Create HOC to handle chat scrolling Support fading elements with a previously set opacity without flicker Add missing keyframe file Fade out fullscreen buttonmaster
commit
d216d9c08a
|
|
@ -1,14 +1,9 @@
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
|
import { compose } from 'redux';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import marked from 'marked';
|
import marked from 'marked';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
import scrollToBottom from './scrollToBottom';
|
||||||
const scrollToBottom = () =>
|
|
||||||
{
|
|
||||||
const messagesDiv = document.getElementById('messages');
|
|
||||||
|
|
||||||
messagesDiv.scrollTop = messagesDiv.scrollHeight;
|
|
||||||
};
|
|
||||||
|
|
||||||
const linkRenderer = new marked.Renderer();
|
const linkRenderer = new marked.Renderer();
|
||||||
|
|
||||||
|
|
@ -22,16 +17,6 @@ linkRenderer.link = (href, title, text) =>
|
||||||
|
|
||||||
class MessageList extends Component
|
class MessageList extends Component
|
||||||
{
|
{
|
||||||
componentDidMount()
|
|
||||||
{
|
|
||||||
scrollToBottom();
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidUpdate()
|
|
||||||
{
|
|
||||||
scrollToBottom();
|
|
||||||
}
|
|
||||||
|
|
||||||
getTimeString(time)
|
getTimeString(time)
|
||||||
{
|
{
|
||||||
return `${(time.getHours() < 10 ? '0' : '')}${time.getHours()}:${(time.getMinutes() < 10 ? '0' : '')}${time.getMinutes()}`;
|
return `${(time.getHours() < 10 ? '0' : '')}${time.getHours()}:${(time.getMinutes() < 10 ? '0' : '')}${time.getMinutes()}`;
|
||||||
|
|
@ -96,8 +81,9 @@ const mapStateToProps = (state) =>
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const MessageListContainer = connect(
|
const MessageListContainer = compose(
|
||||||
mapStateToProps
|
connect(mapStateToProps),
|
||||||
|
scrollToBottom()
|
||||||
)(MessageList);
|
)(MessageList);
|
||||||
|
|
||||||
export default MessageListContainer;
|
export default MessageListContainer;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
import React, { Component } from 'react';
|
||||||
|
import { findDOMNode } from 'react-dom';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A higher order component which scrolls the user to the bottom of the
|
||||||
|
* wrapped component, provided that the user already was at the bottom
|
||||||
|
* of the wrapped component. Useful for chats and similar use cases.
|
||||||
|
* @param {number} treshold The required distance from the bottom required.
|
||||||
|
*/
|
||||||
|
const scrollToBottom = (treshold = 0) => (WrappedComponent) =>
|
||||||
|
{
|
||||||
|
return class AutoScroller extends Component
|
||||||
|
{
|
||||||
|
constructor(props)
|
||||||
|
{
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.ref = React.createRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
getSnapshotBeforeUpdate()
|
||||||
|
{
|
||||||
|
// Check if the user has scrolled close enough to the bottom for
|
||||||
|
// us to scroll to the bottom or not.
|
||||||
|
return this.elem.scrollHeight - this.elem.scrollTop <=
|
||||||
|
this.elem.clientHeight - treshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
scrollToBottom = () =>
|
||||||
|
{
|
||||||
|
// Scroll the user to the bottom of the wrapped element.
|
||||||
|
this.elem.scrollTop = this.elem.scrollHeight;
|
||||||
|
};
|
||||||
|
|
||||||
|
componentDidMount()
|
||||||
|
{
|
||||||
|
// eslint-disable-next-line react/no-find-dom-node
|
||||||
|
this.elem = findDOMNode(this.ref.current);
|
||||||
|
|
||||||
|
this.scrollToBottom();
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate(prevProps, prevState, atBottom)
|
||||||
|
{
|
||||||
|
if (atBottom)
|
||||||
|
{
|
||||||
|
this.scrollToBottom();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render()
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
<WrappedComponent
|
||||||
|
ref={this.ref}
|
||||||
|
{...this.props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default scrollToBottom;
|
||||||
|
|
@ -11,7 +11,8 @@ const FullScreenView = (props) =>
|
||||||
const {
|
const {
|
||||||
advancedMode,
|
advancedMode,
|
||||||
consumer,
|
consumer,
|
||||||
toggleConsumerFullscreen
|
toggleConsumerFullscreen,
|
||||||
|
toolbarsVisible
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
if (!consumer)
|
if (!consumer)
|
||||||
|
|
@ -39,7 +40,9 @@ const FullScreenView = (props) =>
|
||||||
|
|
||||||
<div className='controls'>
|
<div className='controls'>
|
||||||
<div
|
<div
|
||||||
className={classnames('button', 'fullscreen')}
|
className={classnames('button', 'fullscreen', 'room-controls', {
|
||||||
|
visible: toolbarsVisible
|
||||||
|
})}
|
||||||
onClick={(e) =>
|
onClick={(e) =>
|
||||||
{
|
{
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
@ -63,13 +66,15 @@ FullScreenView.propTypes =
|
||||||
{
|
{
|
||||||
advancedMode : PropTypes.bool,
|
advancedMode : PropTypes.bool,
|
||||||
consumer : appPropTypes.Consumer,
|
consumer : appPropTypes.Consumer,
|
||||||
toggleConsumerFullscreen : PropTypes.func.isRequired
|
toggleConsumerFullscreen : PropTypes.func.isRequired,
|
||||||
|
toolbarsVisible : PropTypes.bool
|
||||||
};
|
};
|
||||||
|
|
||||||
const mapStateToProps = (state) =>
|
const mapStateToProps = (state) =>
|
||||||
{
|
{
|
||||||
return {
|
return {
|
||||||
consumer : state.consumers[state.room.fullScreenConsumer]
|
consumer : state.consumers[state.room.fullScreenConsumer],
|
||||||
|
toolbarsVisible : state.room.toolbarsVisible
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -179,13 +179,13 @@
|
||||||
|
|
||||||
.room-controls {
|
.room-controls {
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
animation: fade-out 0.5s;
|
animation: fade-out 0.3s;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
|
||||||
&.visible {
|
&.visible {
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
animation: fade-in 0.5s;
|
animation: fade-in 0.3s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ global-reset();
|
||||||
@import './mixins';
|
@import './mixins';
|
||||||
@import './fonts';
|
@import './fonts';
|
||||||
@import './reset';
|
@import './reset';
|
||||||
|
@import './keyframes';
|
||||||
|
|
||||||
html {
|
html {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
@keyframes fade-in {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fade-out {
|
||||||
|
from {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
opacity: 0;
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue