Files
mattermost-mobile/app/components/channel_loader/channel_loader.js
Miguel Alatzar 2d81b497cf [MM-23520] Port mattermost-redux (#4088)
* Remove mattermost-redux

* Move mm-redux files into app/redux

* Add @redux path to tsconfig.json

* Fix imports

* Install missing dependencies

* Fix tsc errors

* Fix i18n_utils test

* Fix more imports

* Remove redux websocket

* Fix tests

* Rename @redux

* Apply changes from mattermost-redux PR 1103

* Remove mattermost-redux mention in template

* Add missing imports

* Rename app/redux/ to app/mm-redux/

* Remove test file

* Fix fetching Sidebar GM profiles

Co-authored-by: Elias Nahum <nahumhbl@gmail.com>
2020-04-17 21:12:09 -07:00

203 lines
5.7 KiB
JavaScript

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React, {PureComponent} from 'react';
import PropTypes from 'prop-types';
import {
Animated,
Easing,
View,
Dimensions,
} from 'react-native';
import {ImageContent} from 'rn-placeholder';
import EventEmitter from '@mm-redux/utils/event_emitter';
import CustomPropTypes from 'app/constants/custom_prop_types';
import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
import {paddingHorizontal as padding} from 'app/components/safe_area_view/iphone_x_spacing';
const {View: AnimatedView} = Animated;
function calculateMaxRows(height) {
return Math.round(height / 100);
}
export default class ChannelLoader extends PureComponent {
static propTypes = {
actions: PropTypes.shape({
handleSelectChannel: PropTypes.func.isRequired,
setChannelLoading: PropTypes.func.isRequired,
}).isRequired,
backgroundColor: PropTypes.string,
channelIsLoading: PropTypes.bool.isRequired,
style: CustomPropTypes.Style,
theme: PropTypes.object.isRequired,
height: PropTypes.number,
isLandscape: PropTypes.bool.isRequired,
};
constructor(props) {
super(props);
const height = props.height || Dimensions.get('window').height;
const maxRows = calculateMaxRows(height);
this.state = {
barsOpacity: new Animated.Value(0.6),
switch: false,
maxRows,
};
}
static getDerivedStateFromProps(nextProps, prevState) {
const state = {};
if (nextProps.height) {
state.maxRows = calculateMaxRows(nextProps.height);
}
if (!nextProps.channelIsLoading && prevState.switch) {
state.switch = false;
state.channel = null;
}
return Object.keys(state) ? state : null;
}
componentDidMount() {
EventEmitter.on('switch_channel', this.handleChannelSwitch);
}
componentWillUnmount() {
EventEmitter.off('switch_channel', this.handleChannelSwitch);
}
startLoadingAnimation = () => {
Animated.loop(
Animated.sequence([
Animated.timing(this.state.barsOpacity, {
toValue: 1,
duration: 750,
easing: Easing.quad,
useNativeDriver: true,
}),
Animated.timing(this.state.barsOpacity, {
toValue: 0.6,
duration: 750,
easing: Easing.quad,
useNativeDriver: true,
}),
]),
).start();
};
stopLoadingAnimation = () => {
Animated.timing(
this.state.barsOpacity,
).stop();
}
componentDidUpdate(prevProps) {
if (prevProps.channelIsLoading === false && this.props.channelIsLoading === true) {
this.startLoadingAnimation();
} else if (prevProps.channelIsLoading === true && this.props.channelIsLoading === false) {
this.stopLoadingAnimation();
}
if (this.state.switch) {
const {
handleSelectChannel,
setChannelLoading,
} = this.props.actions;
const {channel} = this.state;
setTimeout(() => {
handleSelectChannel(channel.id);
setChannelLoading(false);
}, 250);
}
}
buildSections({key, style, bg, color}) {
return (
<AnimatedView
key={key}
style={[style.section, {backgroundColor: bg}, {opacity: this.state.barsOpacity}]}
>
<ImageContent
size={32}
animate='fade'
lineNumber={3}
lineSpacing={5}
firstLineWidth='80%'
hasRadius={true}
textSize={14}
color={changeOpacity(color, 0.15)}
/>
</AnimatedView>
);
}
handleChannelSwitch = (channel, currentChannelId) => {
if (channel.id === currentChannelId) {
this.props.actions.setChannelLoading(false);
} else {
this.setState({switch: true, channel});
}
};
handleLayout = (e) => {
const {height} = e.nativeEvent.layout;
const maxRows = calculateMaxRows(height);
this.setState({maxRows});
}
render() {
const {
channelIsLoading,
style: styleProp,
theme,
isLandscape,
} = this.props;
if (!channelIsLoading) {
return null;
}
const style = getStyleSheet(theme);
const bg = this.props.backgroundColor || theme.centerChannelBg;
return (
<View
style={[style.container, styleProp, padding(isLandscape), {backgroundColor: bg}]}
onLayout={this.handleLayout}
>
{Array(this.state.maxRows).fill().map((item, index) => this.buildSections({
key: index,
style,
bg,
color: theme.centerChannelColor,
}))}
</View>
);
}
}
const getStyleSheet = makeStyleSheetFromTheme((theme) => {
return {
container: {
flex: 1,
overflow: 'hidden',
},
section: {
backgroundColor: theme.centerChannelBg,
flexDirection: 'row',
flex: 1,
paddingLeft: 12,
paddingRight: 20,
marginVertical: 10,
},
};
});