[RN] Replace chat modal with SlidingView
This commit is contained in:
parent
2a5adfc601
commit
13212a5980
|
@ -1,178 +0,0 @@
|
|||
// @flow
|
||||
|
||||
import React, { PureComponent, type Node } from 'react';
|
||||
import { Animated, TouchableWithoutFeedback, View } from 'react-native';
|
||||
|
||||
import styles, { SIDEBAR_WIDTH } from './styles';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link SideBar}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* The children of {@code SideBar}.
|
||||
*/
|
||||
children: Node,
|
||||
|
||||
/**
|
||||
* Callback to notify the containing {@code Component} that the sidebar is
|
||||
* closing.
|
||||
*/
|
||||
onHide: Function,
|
||||
|
||||
/**
|
||||
* Whether the menu (of the {@code SideBar}?) is displayed/rendered/shown.
|
||||
*/
|
||||
show: boolean
|
||||
};
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} state of {@link SideBar}.
|
||||
*/
|
||||
type State = {
|
||||
|
||||
/**
|
||||
* Whether the side overlay should be displayed/rendered/shown.
|
||||
*/
|
||||
showOverlay: boolean,
|
||||
|
||||
/**
|
||||
* The native animation object.
|
||||
*/
|
||||
sliderAnimation: Animated.Value
|
||||
};
|
||||
|
||||
/**
|
||||
* A generic animated side bar to be used for left-side, hamburger-style menus.
|
||||
*/
|
||||
export default class SideBar extends PureComponent<Props, State> {
|
||||
/**
|
||||
* Implements React's {@link Component#getDerivedStateFromProps()}.
|
||||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
static getDerivedStateFromProps(props: Props, prevState: State) {
|
||||
return {
|
||||
showOverlay: props.show || prevState.showOverlay
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes a new {@code SideBar} instance.
|
||||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
showOverlay: false,
|
||||
sliderAnimation: new Animated.Value(0)
|
||||
};
|
||||
|
||||
// Bind event handlers so they are only bound once per instance.
|
||||
this._onHideMenu = this._onHideMenu.bind(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements React's {@link Component#componentDidMount()}.
|
||||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
componentDidMount() {
|
||||
this._setShow(this.props.show);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements React's {@link Component#componentDidUpdate()}.
|
||||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
componentDidUpdate() {
|
||||
this._setShow(this.props.show);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements React's {@link Component#render()}.
|
||||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
render() {
|
||||
return (
|
||||
<View
|
||||
pointerEvents = 'box-none'
|
||||
style = { styles.sideMenuContainer } >
|
||||
{
|
||||
this.state.showOverlay
|
||||
&& <TouchableWithoutFeedback
|
||||
onPress = { this._onHideMenu } >
|
||||
<View style = { styles.sideMenuShadow } />
|
||||
</TouchableWithoutFeedback>
|
||||
}
|
||||
<Animated.View style = { this._getContentStyle() }>
|
||||
{ this.props.children }
|
||||
</Animated.View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
_getContentStyle: () => Array<Object>;
|
||||
|
||||
/**
|
||||
* Assembles a style array for the sidebar content.
|
||||
*
|
||||
* @private
|
||||
* @returns {Array<Object>}
|
||||
*/
|
||||
_getContentStyle() {
|
||||
return [
|
||||
styles.sideMenuContent,
|
||||
{ transform: [ { translateX: this.state.sliderAnimation } ] }
|
||||
];
|
||||
}
|
||||
|
||||
_onHideMenu: () => void;
|
||||
|
||||
/**
|
||||
* Hides the side menu.
|
||||
*
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
_onHideMenu() {
|
||||
this._setShow(false);
|
||||
|
||||
const { onHide } = this.props;
|
||||
|
||||
onHide && onHide();
|
||||
}
|
||||
|
||||
_setShow: (boolean) => void;
|
||||
|
||||
/**
|
||||
* Shows/hides the side menu.
|
||||
*
|
||||
* @param {boolean} show - If the side menu is to be made visible,
|
||||
* {@code true}; otherwise, {@code false}.
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
_setShow(show) {
|
||||
Animated
|
||||
.timing(
|
||||
/* value */ this.state.sliderAnimation,
|
||||
/* config */ {
|
||||
toValue: show ? SIDEBAR_WIDTH : 0,
|
||||
useNativeDriver: true
|
||||
})
|
||||
.start(({ finished }) => {
|
||||
finished && !show && this.setState({ showOverlay: false });
|
||||
|
||||
// XXX Technically, the arrow function can further be simplified
|
||||
// by removing the {} and returning the boolean expression
|
||||
// above. Practically and unfortunately though, Flow freaks out
|
||||
// and states that Animated.timing doesn't exist!?
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,265 @@
|
|||
// @flow
|
||||
|
||||
import React, { PureComponent, type Node } from 'react';
|
||||
import {
|
||||
Animated,
|
||||
Dimensions,
|
||||
TouchableWithoutFeedback,
|
||||
View
|
||||
} from 'react-native';
|
||||
|
||||
import { type StyleType } from '../../../styles';
|
||||
|
||||
import styles from './slidingviewstyles';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link SlidingView}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* The children of {@code SlidingView}.
|
||||
*/
|
||||
children: Node,
|
||||
|
||||
/**
|
||||
* Callback to notify the containing {@code Component} that the view is
|
||||
* closing.
|
||||
*/
|
||||
onHide: Function,
|
||||
|
||||
/**
|
||||
* Position of the SlidingView: 'left', 'right', 'top', 'bottom'.
|
||||
* later).
|
||||
*/
|
||||
position: string,
|
||||
|
||||
/**
|
||||
* Whether the {@code SlidingView} is to be displayed/rendered/shown or not.
|
||||
*/
|
||||
show: boolean,
|
||||
|
||||
/**
|
||||
* Style of the animated view.
|
||||
*/
|
||||
style: StyleType
|
||||
};
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} state of {@link SlidingView}.
|
||||
*/
|
||||
type State = {
|
||||
|
||||
/**
|
||||
* Whether the sliding overlay should be displayed/rendered/shown.
|
||||
*/
|
||||
showOverlay: boolean,
|
||||
|
||||
/**
|
||||
* The native animation object.
|
||||
*/
|
||||
sliderAnimation: Animated.Value,
|
||||
|
||||
/**
|
||||
* Offset to move the view out of the screen.
|
||||
*/
|
||||
positionOffset: number
|
||||
};
|
||||
|
||||
/**
|
||||
* A generic animated slider view to be used for animated menus.
|
||||
*/
|
||||
export default class SlidingView extends PureComponent<Props, State> {
|
||||
/**
|
||||
* True if the component is mounted.
|
||||
*/
|
||||
_mounted: boolean;
|
||||
|
||||
/**
|
||||
* Implements React's {@link Component#getDerivedStateFromProps()}.
|
||||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
static getDerivedStateFromProps(props: Props, prevState: State) {
|
||||
return {
|
||||
showOverlay: props.show || prevState.showOverlay
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes a new {@code SlidingView} instance.
|
||||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
const { height, width } = Dimensions.get('window');
|
||||
const { position } = props;
|
||||
|
||||
let positionOffset = height;
|
||||
|
||||
if (position === 'left' || position === 'right') {
|
||||
positionOffset = width;
|
||||
}
|
||||
|
||||
this.state = {
|
||||
showOverlay: false,
|
||||
sliderAnimation: new Animated.Value(0),
|
||||
positionOffset
|
||||
};
|
||||
|
||||
// Bind event handlers so they are only bound once per instance.
|
||||
this._onHideMenu = this._onHideMenu.bind(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements React's {@link Component#componentDidMount()}.
|
||||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
componentDidMount() {
|
||||
this._mounted = true;
|
||||
this._setShow(this.props.show);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements React's {@link Component#componentDidUpdate()}.
|
||||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
componentDidUpdate() {
|
||||
this._setShow(this.props.show);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements React's {@link Component#componentWillUnmount()}.
|
||||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
componentWillUnmount() {
|
||||
this._mounted = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements React's {@link Component#render()}.
|
||||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
render() {
|
||||
const { showOverlay } = this.state;
|
||||
|
||||
if (!showOverlay) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<View
|
||||
pointerEvents = 'box-none'
|
||||
style = { styles.sliderViewContainer } >
|
||||
<TouchableWithoutFeedback
|
||||
onPress = { this._onHideMenu } >
|
||||
<View style = { styles.sliderViewShadow } />
|
||||
</TouchableWithoutFeedback>
|
||||
<Animated.View
|
||||
style = { this._getContentStyle() }>
|
||||
{ this.props.children }
|
||||
</Animated.View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
_getContentStyle: () => Array<Object>;
|
||||
|
||||
/**
|
||||
* Assembles a style array for the SlideView content.
|
||||
*
|
||||
* @private
|
||||
* @returns {Array<Object>}
|
||||
*/
|
||||
_getContentStyle() {
|
||||
const style = {
|
||||
...this.props.style,
|
||||
...styles.sliderViewContent
|
||||
};
|
||||
const { positionOffset } = this.state;
|
||||
|
||||
switch (this.props.position) {
|
||||
case 'bottom':
|
||||
Object.assign(style, {
|
||||
bottom: -positionOffset,
|
||||
left: 0,
|
||||
right: 0,
|
||||
top: positionOffset
|
||||
}, {
|
||||
transform: [ { translateY: this.state.sliderAnimation } ]
|
||||
});
|
||||
break;
|
||||
case 'left':
|
||||
Object.assign(style, {
|
||||
bottom: 0,
|
||||
left: -positionOffset,
|
||||
right: positionOffset,
|
||||
top: 0
|
||||
}, {
|
||||
transform: [ { translateX: this.state.sliderAnimation } ]
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
_onHideMenu: () => void;
|
||||
|
||||
/**
|
||||
* Hides the slider.
|
||||
*
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
_onHideMenu() {
|
||||
this._setShow(false);
|
||||
|
||||
const { onHide } = this.props;
|
||||
|
||||
onHide && onHide();
|
||||
}
|
||||
|
||||
_setShow: (boolean) => void;
|
||||
|
||||
/**
|
||||
* Shows/hides the slider menu.
|
||||
*
|
||||
* @param {boolean} show - If the slider view is to be made visible,
|
||||
* {@code true}; otherwise, {@code false}.
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
_setShow(show) {
|
||||
if (!this._mounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { positionOffset } = this.state;
|
||||
const { position } = this.props;
|
||||
let toValue = positionOffset;
|
||||
|
||||
if (position === 'bottom' || position === 'right') {
|
||||
toValue = -positionOffset;
|
||||
}
|
||||
|
||||
Animated
|
||||
.timing(
|
||||
/* value */ this.state.sliderAnimation,
|
||||
/* config */ {
|
||||
duration: 200,
|
||||
toValue: show ? toValue : 0,
|
||||
useNativeDriver: true
|
||||
})
|
||||
.start(({ finished }) => {
|
||||
finished && this._mounted && !show
|
||||
&& this.setState({ showOverlay: false });
|
||||
});
|
||||
}
|
||||
}
|
|
@ -20,7 +20,7 @@ export { default as NavigateSectionListSectionHeader }
|
|||
export { default as PagedList } from './PagedList';
|
||||
export { default as Pressable } from './Pressable';
|
||||
export { default as SectionList } from './SectionList';
|
||||
export { default as SideBar } from './SideBar';
|
||||
export { default as SlidingView } from './SlidingView';
|
||||
export { default as Switch } from './Switch';
|
||||
export { default as Text } from './Text';
|
||||
export { default as TintedView } from './TintedView';
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
// @flow
|
||||
|
||||
import { StyleSheet } from 'react-native';
|
||||
|
||||
import { OVERLAY_Z_INDEX } from '../../constants';
|
||||
|
||||
export default {
|
||||
/**
|
||||
* The topmost container of the side bar.
|
||||
*/
|
||||
sliderViewContainer: {
|
||||
...StyleSheet.absoluteFillObject,
|
||||
zIndex: OVERLAY_Z_INDEX
|
||||
},
|
||||
|
||||
/**
|
||||
* The container of the actual content of the side menu.
|
||||
*/
|
||||
sliderViewContent: {
|
||||
position: 'absolute'
|
||||
},
|
||||
|
||||
/**
|
||||
* The opaque area that covers the rest of the screen, when the side bar is
|
||||
* open.
|
||||
*/
|
||||
sliderViewShadow: {
|
||||
...StyleSheet.absoluteFillObject,
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.5)'
|
||||
}
|
||||
};
|
|
@ -1,7 +1,5 @@
|
|||
// @flow
|
||||
|
||||
import { StyleSheet } from 'react-native';
|
||||
|
||||
import { BoxModel, ColorPalette, createStyleSheet } from '../../../styles';
|
||||
|
||||
const AVATAR_OPACITY = 0.4;
|
||||
|
@ -9,7 +7,6 @@ const OVERLAY_FONT_COLOR = 'rgba(255, 255, 255, 0.6)';
|
|||
const SECONDARY_ACTION_BUTTON_SIZE = 30;
|
||||
|
||||
export const AVATAR_SIZE = 65;
|
||||
export const SIDEBAR_WIDTH = 250;
|
||||
export const UNDERLAY_COLOR = 'rgba(255, 255, 255, 0.2)';
|
||||
|
||||
/**
|
||||
|
@ -241,35 +238,6 @@ const SECTION_LIST_STYLES = {
|
|||
}
|
||||
};
|
||||
|
||||
const SIDEBAR_STYLES = {
|
||||
/**
|
||||
* The topmost container of the side bar.
|
||||
*/
|
||||
sideMenuContainer: {
|
||||
...StyleSheet.absoluteFillObject
|
||||
},
|
||||
|
||||
/**
|
||||
* The container of the actual content of the side menu.
|
||||
*/
|
||||
sideMenuContent: {
|
||||
bottom: 0,
|
||||
left: -SIDEBAR_WIDTH,
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
width: SIDEBAR_WIDTH
|
||||
},
|
||||
|
||||
/**
|
||||
* The opaque area that covers the rest of the screen, when the side bar is
|
||||
* open.
|
||||
*/
|
||||
sideMenuShadow: {
|
||||
...StyleSheet.absoluteFillObject,
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.5)'
|
||||
}
|
||||
};
|
||||
|
||||
export const TINTED_VIEW_DEFAULT = {
|
||||
backgroundColor: ColorPalette.appBackground,
|
||||
opacity: 0.8
|
||||
|
@ -281,6 +249,5 @@ export const TINTED_VIEW_DEFAULT = {
|
|||
*/
|
||||
export default createStyleSheet({
|
||||
...PAGED_LIST_STYLES,
|
||||
...SECTION_LIST_STYLES,
|
||||
...SIDEBAR_STYLES
|
||||
...SECTION_LIST_STYLES
|
||||
});
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
// @flow
|
||||
|
||||
/**
|
||||
* Z-index for components that are to be rendered like an overlay, to be over
|
||||
* everything, such as modal-type of components, or dialogs.
|
||||
*/
|
||||
export const OVERLAY_Z_INDEX = 1000;
|
|
@ -1,31 +1,28 @@
|
|||
// @flow
|
||||
|
||||
import React from 'react';
|
||||
import { SafeAreaView } from 'react-native';
|
||||
import { SafeAreaView, View } from 'react-native';
|
||||
import { GiftedChat } from 'react-native-gifted-chat';
|
||||
|
||||
import { translate } from '../../../base/i18n';
|
||||
import { BackButton, Header, HeaderLabel, Modal } from '../../../base/react';
|
||||
|
||||
import {
|
||||
BackButton,
|
||||
Header,
|
||||
HeaderLabel,
|
||||
SlidingView
|
||||
} from '../../../base/react';
|
||||
import { connect } from '../../../base/redux';
|
||||
|
||||
import AbstractChat, {
|
||||
_mapDispatchToProps,
|
||||
_mapStateToProps as _abstractMapStateToProps,
|
||||
type Props as AbstractProps
|
||||
_mapStateToProps,
|
||||
type Props
|
||||
} from '../AbstractChat';
|
||||
|
||||
import ChatMessage from './ChatMessage';
|
||||
import styles from './styles';
|
||||
|
||||
type Props = AbstractProps & {
|
||||
|
||||
/**
|
||||
* True if the chat window should have a solid BG render.
|
||||
*/
|
||||
_solidBackground: boolean
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Implements a React native component that renders the chat window (modal) of
|
||||
* the mobile client.
|
||||
|
@ -55,32 +52,24 @@ class Chat extends AbstractChat<Props> {
|
|||
// of messages.
|
||||
const messages
|
||||
= this.props._messages.map(this._transformMessage).reverse();
|
||||
const modalStyle = [
|
||||
styles.modalBackdrop
|
||||
];
|
||||
|
||||
if (this.props._solidBackground) {
|
||||
// We only use a transparent background, when we are in a video
|
||||
// meeting to give a user a glympse of what's happening. Otherwise
|
||||
// we use a non-transparent background.
|
||||
modalStyle.push(styles.solidModalBackdrop);
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal
|
||||
onRequestClose = { this.props._onToggleChat }
|
||||
visible = { this.props._isOpen }>
|
||||
<Header>
|
||||
<BackButton onPress = { this.props._onToggleChat } />
|
||||
<HeaderLabel labelKey = 'chat.title' />
|
||||
</Header>
|
||||
<SafeAreaView style = { modalStyle }>
|
||||
<GiftedChat
|
||||
messages = { messages }
|
||||
onSend = { this._onSend }
|
||||
renderMessage = { this._renderMessage } />
|
||||
</SafeAreaView>
|
||||
</Modal>
|
||||
<SlidingView
|
||||
position = 'bottom'
|
||||
show = { this.props._isOpen } >
|
||||
<View style = { styles.chatContainer }>
|
||||
<Header>
|
||||
<BackButton onPress = { this.props._onToggleChat } />
|
||||
<HeaderLabel labelKey = 'chat.title' />
|
||||
</Header>
|
||||
<SafeAreaView style = { styles.backdrop }>
|
||||
<GiftedChat
|
||||
messages = { messages }
|
||||
onSend = { this._onSend }
|
||||
renderMessage = { this._renderMessage } />
|
||||
</SafeAreaView>
|
||||
</View>
|
||||
</SlidingView>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -146,21 +135,4 @@ class Chat extends AbstractChat<Props> {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps part of the Redux state to the props of this component.
|
||||
*
|
||||
* @param {Object} state - The Redux state.
|
||||
* @returns {{
|
||||
* _solidBackground: boolean
|
||||
* }}
|
||||
*/
|
||||
function _mapStateToProps(state) {
|
||||
const abstractReduxProps = _abstractMapStateToProps(state);
|
||||
|
||||
return {
|
||||
...abstractReduxProps,
|
||||
_solidBackground: state['features/base/conference'].audioOnly
|
||||
};
|
||||
}
|
||||
|
||||
export default translate(connect(_mapStateToProps, _mapDispatchToProps)(Chat));
|
||||
|
|
|
@ -8,8 +8,8 @@ import { Avatar } from '../../../base/participants';
|
|||
import { connect } from '../../../base/redux';
|
||||
|
||||
import AbstractChatMessage, {
|
||||
_mapStateToProps as _abstractMapStateToProps,
|
||||
type Props as AbstractProps
|
||||
_mapStateToProps,
|
||||
type Props
|
||||
} from '../AbstractChatMessage';
|
||||
import styles from './styles';
|
||||
|
||||
|
@ -23,14 +23,6 @@ const AVATAR_SIZE = 32;
|
|||
*/
|
||||
const TIMESTAMP_FORMAT = 'H:mm';
|
||||
|
||||
type Props = AbstractProps & {
|
||||
|
||||
/**
|
||||
* True if the chat window has a solid BG so then we have to adopt in style.
|
||||
*/
|
||||
_solidBackground: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a single chat message.
|
||||
*/
|
||||
|
@ -54,9 +46,6 @@ class ChatMessage extends AbstractChatMessage<Props> {
|
|||
const textWrapperStyle = [
|
||||
styles.textWrapper
|
||||
];
|
||||
const timeTextStyles = [
|
||||
styles.timeText
|
||||
];
|
||||
|
||||
if (localMessage) {
|
||||
// The wrapper needs to be aligned to the right.
|
||||
|
@ -69,10 +58,6 @@ class ChatMessage extends AbstractChatMessage<Props> {
|
|||
textWrapperStyle.push(styles.systemTextWrapper);
|
||||
}
|
||||
|
||||
if (this.props._solidBackground) {
|
||||
timeTextStyles.push(styles.solidBGTimeText);
|
||||
}
|
||||
|
||||
return (
|
||||
<View style = { styles.messageWrapper } >
|
||||
{
|
||||
|
@ -92,7 +77,7 @@ class ChatMessage extends AbstractChatMessage<Props> {
|
|||
{ message.text }
|
||||
</Text>
|
||||
</View>
|
||||
<Text style = { timeTextStyles }>
|
||||
<Text style = { styles.timeText }>
|
||||
{ timeStamp }
|
||||
</Text>
|
||||
</View>
|
||||
|
@ -133,20 +118,4 @@ class ChatMessage extends AbstractChatMessage<Props> {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps part of the Redux state to the props of this component.
|
||||
*
|
||||
* @param {Object} state - The Redux state.
|
||||
* @param {Props} ownProps - The own props of the component.
|
||||
* @returns {{
|
||||
* _solidBackground: boolean
|
||||
* }}
|
||||
*/
|
||||
function _mapStateToProps(state, ownProps) {
|
||||
return {
|
||||
..._abstractMapStateToProps(state, ownProps),
|
||||
_solidBackground: state['features/base/conference'].audioOnly
|
||||
};
|
||||
}
|
||||
|
||||
export default translate(connect(_mapStateToProps)(ChatMessage));
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
// @flow
|
||||
|
||||
import {
|
||||
ColorPalette,
|
||||
createStyleSheet
|
||||
} from '../../../base/styles';
|
||||
import { ColorPalette } from '../../../base/styles';
|
||||
|
||||
/**
|
||||
* The styles of the feature chat.
|
||||
|
@ -13,7 +10,7 @@ import {
|
|||
* need to extract the brand colors and sizes into a branding feature (planned
|
||||
* for the future).
|
||||
*/
|
||||
export default createStyleSheet({
|
||||
export default {
|
||||
|
||||
/**
|
||||
* Wrapper View for the avatar.
|
||||
|
@ -22,6 +19,19 @@ export default createStyleSheet({
|
|||
marginRight: 8
|
||||
},
|
||||
|
||||
/**
|
||||
* Background of the chat screen.
|
||||
*/
|
||||
backdrop: {
|
||||
backgroundColor: ColorPalette.white,
|
||||
flex: 1
|
||||
},
|
||||
|
||||
chatContainer: {
|
||||
flex: 1,
|
||||
flexDirection: 'column'
|
||||
},
|
||||
|
||||
/**
|
||||
* Wrapper for the details together, such as name, message and time.
|
||||
*/
|
||||
|
@ -58,16 +68,6 @@ export default createStyleSheet({
|
|||
marginVertical: 4
|
||||
},
|
||||
|
||||
/**
|
||||
* Background of the chat screen. Currently it's set to a transparent value
|
||||
* as the idea is that the participant would still want to see at least a
|
||||
* part of the video when he/she is in the chat window.
|
||||
*/
|
||||
modalBackdrop: {
|
||||
backgroundColor: 'rgba(127, 127, 127, 0.8)',
|
||||
flex: 1
|
||||
},
|
||||
|
||||
/**
|
||||
* Style modifier for the {@code detailsWrapper} for own messages.
|
||||
*/
|
||||
|
@ -84,17 +84,6 @@ export default createStyleSheet({
|
|||
borderTopRightRadius: 0
|
||||
},
|
||||
|
||||
solidBGTimeText: {
|
||||
color: 'rgb(164, 184, 209)'
|
||||
},
|
||||
|
||||
/**
|
||||
* Style modifier for the chat window when we're in audio only mode.
|
||||
*/
|
||||
solidModalBackdrop: {
|
||||
backgroundColor: ColorPalette.white
|
||||
},
|
||||
|
||||
/**
|
||||
* Style modifier for system (error) messages.
|
||||
*/
|
||||
|
@ -118,7 +107,7 @@ export default createStyleSheet({
|
|||
* Text node for the timestamp.
|
||||
*/
|
||||
timeText: {
|
||||
color: ColorPalette.white,
|
||||
color: 'rgb(164, 184, 209)',
|
||||
fontSize: 13
|
||||
}
|
||||
});
|
||||
};
|
||||
|
|
|
@ -11,7 +11,7 @@ import {
|
|||
} from '../../base/participants';
|
||||
import {
|
||||
Header,
|
||||
SideBar
|
||||
SlidingView
|
||||
} from '../../base/react';
|
||||
import { connect } from '../../base/redux';
|
||||
import { setSettingsViewVisible } from '../../settings';
|
||||
|
@ -83,9 +83,11 @@ class WelcomePageSideBar extends Component<Props> {
|
|||
*/
|
||||
render() {
|
||||
return (
|
||||
<SideBar
|
||||
<SlidingView
|
||||
onHide = { this._onHideSideBar }
|
||||
show = { this.props._visible }>
|
||||
position = 'left'
|
||||
show = { this.props._visible }
|
||||
style = { styles.sideBar } >
|
||||
<Header style = { styles.sideBarHeader }>
|
||||
<Avatar
|
||||
size = { SIDEBAR_AVATAR_SIZE }
|
||||
|
@ -116,7 +118,7 @@ class WelcomePageSideBar extends Component<Props> {
|
|||
url = { SEND_FEEDBACK_URL } />
|
||||
</ScrollView>
|
||||
</SafeAreaView>
|
||||
</SideBar>
|
||||
</SlidingView>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -171,6 +171,13 @@ export default createStyleSheet({
|
|||
flexDirection: 'column'
|
||||
},
|
||||
|
||||
/**
|
||||
* Container of the side bar.
|
||||
*/
|
||||
sideBar: {
|
||||
width: 250
|
||||
},
|
||||
|
||||
/**
|
||||
* The body of the side bar where the items are.
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue