Skip to content

Commit

Permalink
Entry screen and Channel Loader improvements (perf part 4) (mattermos…
Browse files Browse the repository at this point in the history
…t#1707)

* Entry screen and Channel Loader improvements

* Feedback review

* Removed unnecessary style array
  • Loading branch information
enahum authored and hmhealey committed May 29, 2018
1 parent b500df8 commit cf36832
Show file tree
Hide file tree
Showing 11 changed files with 100 additions and 182 deletions.
167 changes: 24 additions & 143 deletions app/components/channel_loader/channel_loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,152 +6,56 @@ import PropTypes from 'prop-types';
import {
Platform,
View,
Animated,
Easing,
} from 'react-native';
import LinearGradient from 'react-native-linear-gradient';
import Placeholder from 'rn-placeholder';

import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';

const GRADIENT_START_END = 0;
const GRADIENT_MIDDLE = 0.8;

const START_VALUE = 0;
const MIDDLE_VALUE = 50;
const END_VALUE = 100;
const DURATION = 2000;

export default class ChannelLoader extends PureComponent {
static propTypes = {
backgroundColor: PropTypes.string,
channelIsLoading: PropTypes.bool.isRequired,
deviceWidth: PropTypes.number.isRequired,
theme: PropTypes.object.isRequired,
};

constructor() {
super();
this.animation = new Animated.Value(0);
}

componentDidMount() {
if (this.props.channelIsLoading) {
this.start();
}
}

componentWillUnmount() {
this.animation.stopAnimation();
}

componentWillReceiveProps(nextProps) {
if (nextProps.channelIsLoading !== this.props.channelIsLoading) {
if (nextProps.channelIsLoading) {
this.start();
} else {
this.animation.stopAnimation();
}
}
}

start() {
this.animation.setValue(START_VALUE);
Animated.sequence([
Animated.timing(this.animation, {
toValue: END_VALUE,
duration: DURATION,
easing: Easing.linear,
}),
]).start((animation) => {
if (animation.finished) {
this.start();
}
});
}

buildSections({key, style, top, bg}) {
const left = this.animation.interpolate({
inputRange: [START_VALUE, END_VALUE],
outputRange: ['-10%', '50%'],
});

const opacity = this.animation.interpolate({
inputRange: [START_VALUE, MIDDLE_VALUE, END_VALUE],
outputRange: [GRADIENT_START_END, GRADIENT_MIDDLE, GRADIENT_START_END],
});

const bodyPosLeft = this.animation.interpolate({
inputRange: [START_VALUE, END_VALUE],
outputRange: ['-20%', '80%'],
});

const AnimatedGradient = Animated.createAnimatedComponent(LinearGradient);

buildSections({key, style, bg, color}) {
return (
<View
key={key}
style={[style.section, (top && {marginTop: Platform.OS === 'android' ? 0 : -15, paddingTop: 10})]}
style={[style.section, {backgroundColor: bg}]}
>
<View style={style.avatar}/>
<View style={style.sectionMessage}>
<View>
<View style={[style.messageText]}/>
<AnimatedGradient
start={{x: 0.0, y: 1.0}}
end={{x: 1.0, y: 1.0}}
colors={[
changeOpacity(bg, GRADIENT_START_END),
changeOpacity(bg, GRADIENT_MIDDLE),
changeOpacity(bg, GRADIENT_START_END),
]}
locations={[0, 0.5, 1]}
style={[style.gradientText, {left, opacity}]}
/>
</View>
<View>
<View style={[style.messageText, {width: '100%'}]}/>
<AnimatedGradient
start={{x: 0.0, y: 1.0}}
end={{x: 1.0, y: 1.0}}
colors={[
changeOpacity(bg, GRADIENT_START_END),
changeOpacity(bg, GRADIENT_MIDDLE),
changeOpacity(bg, GRADIENT_START_END),
]}
locations={[0, 0.5, 1]}
style={[style.gradientText, {left: bodyPosLeft, opacity}]}
/>
</View>
<View>
<View style={[style.messageText, {width: '100%'}]}/>
<AnimatedGradient
start={{x: 0.0, y: 1.0}}
end={{x: 1.0, y: 1.0}}
colors={[
changeOpacity(bg, GRADIENT_START_END),
changeOpacity(bg, GRADIENT_MIDDLE),
changeOpacity(bg, GRADIENT_START_END),
]}
locations={[0, 0.5, 1]}
style={[style.gradientText, {left: bodyPosLeft, opacity}]}
/>
</View>
</View>
<Placeholder.ImageContent
size={32}
animate='fade'
lineNumber={3}
lineSpacing={5}
firstLineWidth='80%'
hasRadius={true}
textSize={14}
color={changeOpacity(color, 0.2)}
/>
</View>
);
}

render() {
const {channelIsLoading, deviceWidth, theme} = this.props;
const {channelIsLoading, theme} = this.props;

if (!channelIsLoading) {
return null;
}

const style = getStyleSheet(theme);
const bg = this.props.backgroundColor || theme.centerChannelBg;

return (
<View style={[style.container, {width: deviceWidth}]}>
{Array(20).fill().map((item, index) => this.buildSections({key: index, style, top: index === 0, bg: theme.centerChannelBg}))}
<View style={style.container}>
{Array(6).fill().map((item, index) => this.buildSections({
key: index,
style,
bg,
color: theme.centerChannelColor,
}))}
</View>
);
}
Expand All @@ -162,7 +66,6 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
container: {
backgroundColor: theme.centerChannelBg,
flex: 1,
position: 'absolute',
...Platform.select({
android: {
top: 0,
Expand All @@ -172,35 +75,13 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
},
}),
},
avatar: {
backgroundColor: changeOpacity(theme.centerChannelColor, 0.2),
borderRadius: 16,
height: 32,
width: 32,
},
gradientText: {
backgroundColor: changeOpacity(theme.centerChannelBg, 0.2),
height: 10,
marginBottom: 10,
position: 'absolute',
width: '40%',
},
section: {
backgroundColor: theme.centerChannelBg,
flexDirection: 'row',
flex: 1,
paddingLeft: 12,
paddingRight: 20,
marginVertical: 10,
},
sectionMessage: {
marginLeft: 12,
flex: 1,
},
messageText: {
width: '80%',
backgroundColor: changeOpacity(theme.centerChannelColor, 0.2),
height: 10,
marginBottom: 10,
},
};
});
2 changes: 0 additions & 2 deletions app/components/channel_loader/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,8 @@ import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
import ChannelLoader from './channel_loader';

function mapStateToProps(state, ownProps) {
const {deviceWidth} = state.device.dimension;
return {
channelIsLoading: ownProps.channelIsLoading || state.views.channel.loading,
deviceWidth,
theme: getTheme(state),
};
}
Expand Down
14 changes: 11 additions & 3 deletions app/screens/channel/channel.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
import EventEmitter from 'mattermost-redux/utils/event_emitter';

import ChannelDrawer from 'app/components/channel_drawer';
import EmptyToolbar from 'app/components/start/empty_toolbar';
import SettingsDrawer from 'app/components/settings_drawer';
import KeyboardLayout from 'app/components/layout/keyboard_layout';
import OfflineIndicator from 'app/components/offline_indicator';
Expand Down Expand Up @@ -47,6 +48,7 @@ export default class Channel extends PureComponent {
currentChannelId: PropTypes.string,
channelsRequestFailed: PropTypes.bool,
currentTeamId: PropTypes.string,
isLandscape: PropTypes.bool,
navigator: PropTypes.object,
theme: PropTypes.object.isRequired,
};
Expand Down Expand Up @@ -257,9 +259,15 @@ export default class Channel extends PureComponent {

const Loading = require('app/components/channel_loader').default;
return (
<View style={style.loading}>
<Loading channelIsLoading={true}/>
</View>
<SafeAreaView navigator={navigator}>
<View style={style.loading}>
<EmptyToolbar
theme={theme}
isLandscape={this.props.isLandscape}
/>
<Loading channelIsLoading={true}/>
</View>
</SafeAreaView>
);
}

Expand Down
6 changes: 4 additions & 2 deletions app/screens/channel/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.

import {bindActionCreators} from 'redux';
Expand All @@ -9,6 +9,7 @@ import {init as initWebSocket, close as closeWebSocket} from 'mattermost-redux/a
import {RequestStatus} from 'mattermost-redux/constants';
import {getCurrentChannelId} from 'mattermost-redux/selectors/entities/channels';
import {getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams';
import {getTheme} from 'mattermost-redux/selectors/entities/preferences';

import {
loadChannelsIfNecessary,
Expand All @@ -18,7 +19,7 @@ import {
import {connection} from 'app/actions/device';
import {recordLoadTime} from 'app/actions/views/root';
import {selectDefaultTeam} from 'app/actions/views/select_team';
import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
import {isLandscape} from 'app/selectors/device';

import Channel from './channel';

Expand All @@ -29,6 +30,7 @@ function mapStateToProps(state) {
channelsRequestFailed: channelsRequest.status === RequestStatus.FAILURE,
currentTeamId: getCurrentTeamId(state),
currentChannelId: getCurrentChannelId(state),
isLandscape: isLandscape(state),
theme: getTheme(state),
};
}
Expand Down
29 changes: 15 additions & 14 deletions app/screens/entry/entry.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {loadFromPushNotification} from 'app/actions/views/root';
import {ViewTypes} from 'app/constants';
import PushNotifications from 'app/push_notifications';
import {stripTrailingSlashes} from 'app/utils/url';
import {wrapWithContextProvider} from 'app/utils/wrap_context_provider';

import ChannelLoader from 'app/components/channel_loader';
import EmptyToolbar from 'app/components/start/empty_toolbar';
Expand Down Expand Up @@ -212,22 +213,21 @@ export default class Entry extends PureComponent {

renderLogin = () => {
const SelectServer = lazyLoadSelectServer();
return (
<SelectServer
navigator={this.props.navigator}
allowOtherServers={app.allowOtherServers}
/>
);
const props = {
allowOtherServers: app.allowOtherServers,
navigator: this.props.navigator,
};

return wrapWithContextProvider(SelectServer)(props);
};

renderChannel = () => {
const ChannelScreen = lazyLoadChannel();
const props = {
navigator: this.props.navigator,
};

return (
<ChannelScreen
navigator={this.props.navigator}
/>
);
return wrapWithContextProvider(ChannelScreen, true)(props);
};

render() {
Expand Down Expand Up @@ -264,9 +264,10 @@ export default class Entry extends PureComponent {
);

loading = (
<View>
<ChannelLoader channelIsLoading={true}/>
</View>
<ChannelLoader
backgroundColor={backgroundColor}
channelIsLoading={true}
/>
);
} else {
loading = <Loading/>;
Expand Down
19 changes: 2 additions & 17 deletions app/screens/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit cf36832

Please sign in to comment.