Sidebars improvement (#1787)
* Sidebars improvement * Explicitly handle Android back button in code screen * return null on getDerivedStateFromProps when no state changes needed
This commit is contained in:
parent
f273d26435
commit
ba09fb9792
38 changed files with 336 additions and 438 deletions
|
|
@ -6,7 +6,7 @@ import {createDirectChannel, createGroupChannel} from 'mattermost-redux/actions/
|
|||
import {getProfilesByIds, getStatusesByIds} from 'mattermost-redux/actions/users';
|
||||
import {handleSelectChannel, toggleDMChannel, toggleGMChannel} from 'app/actions/views/channel';
|
||||
|
||||
export function makeDirectChannel(otherUserId) {
|
||||
export function makeDirectChannel(otherUserId, switchToChannel = true) {
|
||||
return async (dispatch, getState) => {
|
||||
const state = getState();
|
||||
const {currentUserId} = state.entities.users;
|
||||
|
|
@ -27,7 +27,7 @@ export function makeDirectChannel(otherUserId) {
|
|||
channel = result.data;
|
||||
}
|
||||
|
||||
if (channel) {
|
||||
if (channel && switchToChannel) {
|
||||
dispatch(handleSelectChannel(channel.id));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,15 +9,79 @@ import {
|
|||
} from 'react-native';
|
||||
import Placeholder from 'rn-placeholder';
|
||||
|
||||
import EventEmitter from 'mattermost-redux/utils/event_emitter';
|
||||
|
||||
import CustomPropTypes from 'app/constants/custom_prop_types';
|
||||
import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
|
||||
|
||||
export default class ChannelLoader extends PureComponent {
|
||||
static propTypes = {
|
||||
actions: PropTypes.shape({
|
||||
handleSelectChannel: PropTypes.func.isRequired,
|
||||
markChannelAsViewed: PropTypes.func.isRequired,
|
||||
markChannelAsRead: PropTypes.func.isRequired,
|
||||
setChannelLoading: PropTypes.func.isRequired,
|
||||
}).isRequired,
|
||||
backgroundColor: PropTypes.string,
|
||||
channelIsLoading: PropTypes.bool.isRequired,
|
||||
maxRows: PropTypes.number,
|
||||
style: CustomPropTypes.Style,
|
||||
theme: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
maxRows: 6,
|
||||
};
|
||||
|
||||
state = {
|
||||
switch: false,
|
||||
};
|
||||
|
||||
static getDerivedStateFromProps(nextProps, prevState) {
|
||||
if (!nextProps.channelIsLoading && prevState.switch) {
|
||||
return {
|
||||
switch: false,
|
||||
channel: null,
|
||||
currentChannelId: null,
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
EventEmitter.on('switch_channel', this.handleChannelSwitch);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
EventEmitter.off('switch_channel', this.handleChannelSwitch);
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
if (this.state.switch) {
|
||||
const {
|
||||
handleSelectChannel,
|
||||
markChannelAsRead,
|
||||
markChannelAsViewed,
|
||||
setChannelLoading,
|
||||
} = this.props.actions;
|
||||
|
||||
const {channel, currentChannelId} = this.state;
|
||||
|
||||
setTimeout(() => {
|
||||
handleSelectChannel(channel.id);
|
||||
|
||||
// mark the channel as viewed after all the frame has flushed
|
||||
markChannelAsRead(channel.id, currentChannelId);
|
||||
if (channel.id !== currentChannelId) {
|
||||
markChannelAsViewed(currentChannelId);
|
||||
}
|
||||
|
||||
setChannelLoading(false);
|
||||
}, 250);
|
||||
}
|
||||
}
|
||||
|
||||
buildSections({key, style, bg, color}) {
|
||||
return (
|
||||
<View
|
||||
|
|
@ -38,8 +102,16 @@ export default class ChannelLoader extends PureComponent {
|
|||
);
|
||||
}
|
||||
|
||||
handleChannelSwitch = (channel, currentChannelId) => {
|
||||
if (channel.id === currentChannelId) {
|
||||
this.props.actions.setChannelLoading(false);
|
||||
} else {
|
||||
this.setState({switch: true, channel, currentChannelId});
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const {channelIsLoading, theme} = this.props;
|
||||
const {channelIsLoading, maxRows, style: styleProp, theme} = this.props;
|
||||
|
||||
if (!channelIsLoading) {
|
||||
return null;
|
||||
|
|
@ -49,8 +121,8 @@ export default class ChannelLoader extends PureComponent {
|
|||
const bg = this.props.backgroundColor || theme.centerChannelBg;
|
||||
|
||||
return (
|
||||
<View style={[style.container, {backgroundColor: bg}]}>
|
||||
{Array(6).fill().map((item, index) => this.buildSections({
|
||||
<View style={[style.container, styleProp, {backgroundColor: bg}]}>
|
||||
{Array(maxRows).fill().map((item, index) => this.buildSections({
|
||||
key: index,
|
||||
style,
|
||||
bg,
|
||||
|
|
@ -70,7 +142,7 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
|
|||
top: 0,
|
||||
},
|
||||
ios: {
|
||||
top: 15,
|
||||
paddingTop: 15,
|
||||
},
|
||||
}),
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,9 +1,14 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {bindActionCreators} from 'redux';
|
||||
import {connect} from 'react-redux';
|
||||
|
||||
import {markChannelAsRead, markChannelAsViewed} from 'mattermost-redux/actions/channels';
|
||||
import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
|
||||
|
||||
import {handleSelectChannel, setChannelLoading} from 'app/actions/views/channel';
|
||||
|
||||
import ChannelLoader from './channel_loader';
|
||||
|
||||
function mapStateToProps(state, ownProps) {
|
||||
|
|
@ -13,4 +18,15 @@ function mapStateToProps(state, ownProps) {
|
|||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(ChannelLoader);
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
actions: bindActionCreators({
|
||||
handleSelectChannel,
|
||||
markChannelAsRead,
|
||||
setChannelLoading,
|
||||
markChannelAsViewed,
|
||||
}, dispatch),
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(ChannelLoader);
|
||||
|
|
|
|||
|
|
@ -1,99 +0,0 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {Keyboard, Dimensions} from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
import BaseDrawer from 'react-native-drawer';
|
||||
|
||||
// Extends react-native-drawer to allow better control over the open/closed state from the parent
|
||||
export default class Drawer extends BaseDrawer {
|
||||
static propTypes = {
|
||||
...BaseDrawer.propTypes,
|
||||
onRequestClose: PropTypes.func.isRequired,
|
||||
bottomPanOffset: PropTypes.number,
|
||||
topPanOffset: PropTypes.number,
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.keyboardHeight = 0;
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
Keyboard.addListener('keyboardDidShow', this.keyboardDidShow);
|
||||
Keyboard.addListener('keyboardDidHide', this.keyboardDidHide);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
Keyboard.removeListener('keyboardDidShow', this.keyboardDidShow);
|
||||
Keyboard.removeListener('keyboardDidHide', this.keyboardDidHide);
|
||||
}
|
||||
|
||||
getMainHeight = () => '100%';
|
||||
|
||||
keyboardDidShow = (e) => {
|
||||
this.keyboardHeight = e.endCoordinates.height;
|
||||
};
|
||||
|
||||
keyboardDidHide = () => {
|
||||
this.keyboardHeight = 0;
|
||||
};
|
||||
|
||||
isOpened = () => {
|
||||
return this._open; //eslint-disable-line no-underscore-dangle
|
||||
};
|
||||
|
||||
processTapGestures = () => {
|
||||
// Note that we explicitly don't support tap to open or double tap because I didn't copy them over
|
||||
|
||||
if (this._activeTween) { //eslint-disable-line no-underscore-dangle
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.props.tapToClose && this._open) { //eslint-disable-line no-underscore-dangle
|
||||
this.props.onRequestClose();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
testPanResponderMask = (e) => {
|
||||
if (this.props.disabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Disable if parent or child drawer exist and are open
|
||||
if (this.context.drawer && this.context.drawer._open) { //eslint-disable-line no-underscore-dangle
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this._childDrawer && this._childDrawer._open) { //eslint-disable-line no-underscore-dangle
|
||||
return false;
|
||||
}
|
||||
|
||||
const topPanOffset = this.props.topPanOffset || 0;
|
||||
const bottomPanOffset = this.props.bottomPanOffset || 0;
|
||||
const height = Dimensions.get('window').height;
|
||||
if ((this.props.topPanOffset && e.nativeEvent.pageY < topPanOffset) ||
|
||||
(this.props.bottomPanOffset && e.nativeEvent.pageY > (height - (bottomPanOffset + this.keyboardHeight)))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const pos0 = this.isLeftOrRightSide() ? e.nativeEvent.pageX : e.nativeEvent.pageY;
|
||||
const deltaOpen = this.isLeftOrTopSide() ? this.getDeviceLength() - pos0 : pos0;
|
||||
const deltaClose = this.isLeftOrTopSide() ? pos0 : this.getDeviceLength() - pos0;
|
||||
|
||||
if (this._open && deltaOpen > this.getOpenMask()) { //eslint-disable-line no-underscore-dangle
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!this._open && deltaClose > this.getClosedMask()) { //eslint-disable-line no-underscore-dangle
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
|
@ -102,6 +102,7 @@ export default class SearchBarAndroid extends PureComponent {
|
|||
InteractionManager.runAfterInteractions(() => {
|
||||
this.setState({
|
||||
isFocused: false,
|
||||
value: '',
|
||||
}, () => {
|
||||
this.props.onCancelButtonPress();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -49,15 +49,15 @@ export default class ChannelsList extends PureComponent {
|
|||
}
|
||||
|
||||
onSelectChannel = (channel, currentChannelId) => {
|
||||
if (this.refs.search_bar) {
|
||||
this.refs.search_bar.cancel();
|
||||
}
|
||||
|
||||
if (channel.fake) {
|
||||
this.props.onJoinChannel(channel, currentChannelId);
|
||||
} else {
|
||||
this.props.onSelectChannel(channel, currentChannelId);
|
||||
}
|
||||
|
||||
if (this.refs.search_bar) {
|
||||
this.refs.search_bar.cancel();
|
||||
}
|
||||
};
|
||||
|
||||
onSearch = (term) => {
|
||||
|
|
@ -19,7 +19,7 @@ import {General} from 'mattermost-redux/constants';
|
|||
import {sortChannelsByDisplayName} from 'mattermost-redux/utils/channel_utils';
|
||||
import {displayUsername} from 'mattermost-redux/utils/user_utils';
|
||||
|
||||
import ChannelItem from 'app/components/channel_drawer/channels_list/channel_item';
|
||||
import ChannelItem from 'app/components/sidebars/main/channels_list/channel_item';
|
||||
import {ListTypes} from 'app/constants';
|
||||
|
||||
const VIEWABILITY_CONFIG = ListTypes.VISIBILITY_CONFIG_DEFAULTS;
|
||||
|
|
@ -16,7 +16,7 @@ import MaterialIcon from 'react-native-vector-icons/MaterialIcons';
|
|||
import {General} from 'mattermost-redux/constants';
|
||||
import {debounce} from 'mattermost-redux/actions/helpers';
|
||||
|
||||
import ChannelItem from 'app/components/channel_drawer/channels_list/channel_item';
|
||||
import ChannelItem from 'app/components/sidebars/main/channels_list/channel_item';
|
||||
import {ListTypes} from 'app/constants';
|
||||
import {preventDoubleTap} from 'app/utils/tap';
|
||||
import {changeOpacity} from 'app/utils/theme';
|
||||
|
|
@ -313,7 +313,7 @@ export default class List extends PureComponent {
|
|||
|
||||
emitUnreadIndicatorChange = debounce((showIndicator) => {
|
||||
if (showIndicator && !UnreadIndicator) {
|
||||
UnreadIndicator = require('app/components/channel_drawer/channels_list/unread_indicator').default;
|
||||
UnreadIndicator = require('app/components/sidebars/main/channels_list/unread_indicator').default;
|
||||
}
|
||||
this.setState({showIndicator});
|
||||
}, 100);
|
||||
|
|
@ -25,9 +25,11 @@ export default class DrawerSwiper extends Component {
|
|||
};
|
||||
|
||||
shouldComponentUpdate(nextProps) {
|
||||
const {deviceWidth, showTeams, theme} = this.props;
|
||||
const {deviceWidth, openDrawerOffset, showTeams, theme} = this.props;
|
||||
return nextProps.deviceWidth !== deviceWidth ||
|
||||
nextProps.showTeams !== showTeams || nextProps.theme !== theme;
|
||||
nextProps.showTeams !== showTeams ||
|
||||
nextProps.openDrawerOffset !== openDrawerOffset ||
|
||||
nextProps.theme !== theme;
|
||||
}
|
||||
|
||||
runOnLayout = (shouldRun = true) => {
|
||||
|
|
@ -4,21 +4,22 @@
|
|||
import {bindActionCreators} from 'redux';
|
||||
import {connect} from 'react-redux';
|
||||
|
||||
import {joinChannel, markChannelAsRead, markChannelAsViewed} from 'mattermost-redux/actions/channels';
|
||||
import {joinChannel} from 'mattermost-redux/actions/channels';
|
||||
import {getTeams} from 'mattermost-redux/actions/teams';
|
||||
import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
|
||||
import {getCurrentTeamId, getMyTeamsCount} from 'mattermost-redux/selectors/entities/teams';
|
||||
|
||||
import {handleSelectChannel, setChannelDisplayName, setChannelLoading} from 'app/actions/views/channel';
|
||||
import {setChannelDisplayName, setChannelLoading} from 'app/actions/views/channel';
|
||||
import {makeDirectChannel} from 'app/actions/views/more_dms';
|
||||
import {isLandscape, isTablet} from 'app/selectors/device';
|
||||
import {isLandscape, isTablet, getDimensions} from 'app/selectors/device';
|
||||
|
||||
import ChannelDrawer from './channel_drawer.js';
|
||||
import MainSidebar from './main_sidebar.js';
|
||||
|
||||
function mapStateToProps(state) {
|
||||
const {currentUserId} = state.entities.users;
|
||||
|
||||
return {
|
||||
...getDimensions(state),
|
||||
currentTeamId: getCurrentTeamId(state),
|
||||
currentUserId,
|
||||
isLandscape: isLandscape(state),
|
||||
|
|
@ -32,15 +33,12 @@ function mapDispatchToProps(dispatch) {
|
|||
return {
|
||||
actions: bindActionCreators({
|
||||
getTeams,
|
||||
handleSelectChannel,
|
||||
joinChannel,
|
||||
markChannelAsViewed,
|
||||
makeDirectChannel,
|
||||
markChannelAsRead,
|
||||
setChannelDisplayName,
|
||||
setChannelLoading,
|
||||
}, dispatch),
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps, null, {withRef: true})(ChannelDrawer);
|
||||
export default connect(mapStateToProps, mapDispatchToProps, null, {withRef: true})(MainSidebar);
|
||||
|
|
@ -5,42 +5,31 @@ import React, {Component} from 'react';
|
|||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
BackHandler,
|
||||
InteractionManager,
|
||||
Keyboard,
|
||||
Platform,
|
||||
StyleSheet,
|
||||
View,
|
||||
} from 'react-native';
|
||||
import {intlShape} from 'react-intl';
|
||||
import DrawerLayout from 'react-native-drawer-layout';
|
||||
|
||||
import {General, WebsocketEvents} from 'mattermost-redux/constants';
|
||||
import EventEmitter from 'mattermost-redux/utils/event_emitter';
|
||||
|
||||
import Drawer from 'app/components/drawer';
|
||||
import SafeAreaView from 'app/components/safe_area_view';
|
||||
import {ViewTypes} from 'app/constants';
|
||||
import tracker from 'app/utils/time_tracker';
|
||||
|
||||
import ChannelsList from './channels_list';
|
||||
import DrawerSwiper from './drawer_swipper';
|
||||
import TeamsList from './teams_list';
|
||||
|
||||
const {
|
||||
ANDROID_TOP_LANDSCAPE,
|
||||
ANDROID_TOP_PORTRAIT,
|
||||
IOS_TOP_LANDSCAPE,
|
||||
IOS_TOP_PORTRAIT,
|
||||
} = ViewTypes;
|
||||
const DRAWER_INITIAL_OFFSET = 40;
|
||||
const DRAWER_LANDSCAPE_OFFSET = 150;
|
||||
|
||||
export default class ChannelDrawer extends Component {
|
||||
export default class ChannelSidebar extends Component {
|
||||
static propTypes = {
|
||||
actions: PropTypes.shape({
|
||||
getTeams: PropTypes.func.isRequired,
|
||||
handleSelectChannel: PropTypes.func.isRequired,
|
||||
markChannelAsViewed: PropTypes.func.isRequired,
|
||||
makeDirectChannel: PropTypes.func.isRequired,
|
||||
markChannelAsRead: PropTypes.func.isRequired,
|
||||
setChannelDisplayName: PropTypes.func.isRequired,
|
||||
setChannelLoading: PropTypes.func.isRequired,
|
||||
}).isRequired,
|
||||
|
|
@ -48,16 +37,18 @@ export default class ChannelDrawer extends Component {
|
|||
children: PropTypes.node,
|
||||
currentTeamId: PropTypes.string.isRequired,
|
||||
currentUserId: PropTypes.string.isRequired,
|
||||
deviceWidth: PropTypes.number.isRequired,
|
||||
isLandscape: PropTypes.bool.isRequired,
|
||||
isTablet: PropTypes.bool.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
navigator: PropTypes.object,
|
||||
teamsCount: PropTypes.number.isRequired,
|
||||
theme: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
closeHandle = null;
|
||||
openHandle = null;
|
||||
static contextTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
swiperIndex = 1;
|
||||
|
||||
constructor(props) {
|
||||
|
|
@ -67,6 +58,9 @@ export default class ChannelDrawer extends Component {
|
|||
if (props.isLandscape || props.isTablet) {
|
||||
openDrawerOffset = DRAWER_LANDSCAPE_OFFSET;
|
||||
}
|
||||
|
||||
this.drawerOpened = false;
|
||||
|
||||
this.state = {
|
||||
show: false,
|
||||
openDrawerOffset,
|
||||
|
|
@ -118,8 +112,8 @@ export default class ChannelDrawer extends Component {
|
|||
}
|
||||
|
||||
handleAndroidBack = () => {
|
||||
if (this.refs.drawer && this.refs.drawer.isOpened()) {
|
||||
this.refs.drawer.close();
|
||||
if (this.drawerOpened && this.refs.drawer) {
|
||||
this.refs.drawer.closeDrawer();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -131,8 +125,8 @@ export default class ChannelDrawer extends Component {
|
|||
};
|
||||
|
||||
closeChannelDrawer = () => {
|
||||
if (this.refs.drawer && this.refs.drawer.isOpened()) {
|
||||
this.refs.drawer.close();
|
||||
if (this.drawerOpened && this.refs.drawer) {
|
||||
this.refs.drawer.closeDrawer();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -141,53 +135,16 @@ export default class ChannelDrawer extends Component {
|
|||
};
|
||||
|
||||
handleDrawerClose = () => {
|
||||
this.drawerOpened = false;
|
||||
this.resetDrawer();
|
||||
|
||||
if (this.closeHandle) {
|
||||
InteractionManager.clearInteractionHandle(this.closeHandle);
|
||||
this.closeHandle = null;
|
||||
}
|
||||
};
|
||||
|
||||
handleDrawerCloseStart = () => {
|
||||
if (!this.closeHandle) {
|
||||
this.closeHandle = InteractionManager.createInteractionHandle();
|
||||
}
|
||||
};
|
||||
|
||||
handleDrawerOpen = () => {
|
||||
this.drawerOpened = true;
|
||||
|
||||
if (this.state.openDrawerOffset !== 0) {
|
||||
Keyboard.dismiss();
|
||||
}
|
||||
|
||||
if (this.openHandle) {
|
||||
InteractionManager.clearInteractionHandle(this.openHandle);
|
||||
this.openHandle = null;
|
||||
}
|
||||
};
|
||||
|
||||
handleDrawerOpenStart = () => {
|
||||
if (!this.openHandle) {
|
||||
this.openHandle = InteractionManager.createInteractionHandle();
|
||||
}
|
||||
};
|
||||
|
||||
handleDrawerTween = (ratio) => {
|
||||
const opacity = (ratio / 2);
|
||||
|
||||
EventEmitter.emit('drawer_opacity', opacity);
|
||||
|
||||
return {
|
||||
mainOverlay: {
|
||||
backgroundColor: this.props.theme.centerChannelBg,
|
||||
elevation: 3,
|
||||
opacity,
|
||||
},
|
||||
drawerOverlay: {
|
||||
backgroundColor: ratio ? '#000' : '#FFF',
|
||||
opacity: ratio ? (1 - ratio) / 2 : 1,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
handleUpdateTitle = (channel) => {
|
||||
|
|
@ -198,11 +155,11 @@ export default class ChannelDrawer extends Component {
|
|||
this.props.actions.setChannelDisplayName(channelName);
|
||||
};
|
||||
|
||||
openChannelDrawer = () => {
|
||||
openChannelSidebar = () => {
|
||||
this.props.blurPostTextBox();
|
||||
|
||||
if (this.refs.drawer && !this.refs.drawer.isOpened()) {
|
||||
this.refs.drawer.open();
|
||||
if (this.refs.drawer) {
|
||||
this.refs.drawer.openDrawer();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -212,38 +169,25 @@ export default class ChannelDrawer extends Component {
|
|||
} = this.props;
|
||||
|
||||
const {
|
||||
handleSelectChannel,
|
||||
markChannelAsRead,
|
||||
setChannelLoading,
|
||||
setChannelDisplayName,
|
||||
markChannelAsViewed,
|
||||
} = actions;
|
||||
|
||||
tracker.channelSwitch = Date.now();
|
||||
|
||||
this.closeChannelDrawer();
|
||||
|
||||
InteractionManager.runAfterInteractions(() => {
|
||||
setChannelLoading(channel.id !== currentChannelId);
|
||||
setChannelDisplayName(channel.display_name);
|
||||
|
||||
handleSelectChannel(channel.id);
|
||||
requestAnimationFrame(() => {
|
||||
// mark the channel as viewed after all the frame has flushed
|
||||
markChannelAsRead(channel.id, currentChannelId);
|
||||
if (channel.id !== currentChannelId) {
|
||||
markChannelAsViewed(currentChannelId);
|
||||
}
|
||||
});
|
||||
});
|
||||
setChannelLoading(channel.id !== currentChannelId);
|
||||
setChannelDisplayName(channel.display_name);
|
||||
EventEmitter.emit('switch_channel', channel, currentChannelId);
|
||||
};
|
||||
|
||||
joinChannel = async (channel, currentChannelId) => {
|
||||
const {intl} = this.context;
|
||||
const {
|
||||
actions,
|
||||
currentTeamId,
|
||||
currentUserId,
|
||||
intl,
|
||||
} = this.props;
|
||||
|
||||
const {
|
||||
|
|
@ -256,7 +200,7 @@ export default class ChannelDrawer extends Component {
|
|||
|
||||
let result;
|
||||
if (channel.type === General.DM_CHANNEL) {
|
||||
result = await makeDirectChannel(channel.id);
|
||||
result = await makeDirectChannel(channel.id, false);
|
||||
|
||||
if (result.error) {
|
||||
const dmFailedMessage = {
|
||||
|
|
@ -292,10 +236,6 @@ export default class ChannelDrawer extends Component {
|
|||
//hack to update the drawer when the offset changes
|
||||
const {isLandscape, isTablet} = this.props;
|
||||
|
||||
if (this.refs.drawer) {
|
||||
this.refs.drawer._syncAfterUpdate = true; //eslint-disable-line no-underscore-dangle
|
||||
}
|
||||
|
||||
let openDrawerOffset = DRAWER_INITIAL_OFFSET;
|
||||
if (isLandscape || isTablet) {
|
||||
openDrawerOffset = DRAWER_LANDSCAPE_OFFSET;
|
||||
|
|
@ -304,10 +244,6 @@ export default class ChannelDrawer extends Component {
|
|||
};
|
||||
|
||||
onSearchStart = () => {
|
||||
if (this.refs.drawer) {
|
||||
this.refs.drawer._syncAfterUpdate = true; //eslint-disable-line no-underscore-dangle
|
||||
}
|
||||
|
||||
this.setState({openDrawerOffset: 0});
|
||||
};
|
||||
|
||||
|
|
@ -323,7 +259,7 @@ export default class ChannelDrawer extends Component {
|
|||
}
|
||||
};
|
||||
|
||||
renderContent = () => {
|
||||
renderNavigationView = () => {
|
||||
const {
|
||||
navigator,
|
||||
teamsCount,
|
||||
|
|
@ -401,53 +337,19 @@ export default class ChannelDrawer extends Component {
|
|||
};
|
||||
|
||||
render() {
|
||||
const {children, isLandscape} = this.props;
|
||||
const {children, deviceWidth} = this.props;
|
||||
const {openDrawerOffset} = this.state;
|
||||
|
||||
const androidTop = isLandscape ? ANDROID_TOP_LANDSCAPE : ANDROID_TOP_PORTRAIT;
|
||||
const iosTop = isLandscape ? IOS_TOP_LANDSCAPE : IOS_TOP_PORTRAIT;
|
||||
|
||||
return (
|
||||
<Drawer
|
||||
<DrawerLayout
|
||||
ref='drawer'
|
||||
onOpenStart={this.handleDrawerOpenStart}
|
||||
onOpen={this.handleDrawerOpen}
|
||||
onClose={this.handleDrawerClose}
|
||||
onCloseStart={this.handleDrawerCloseStart}
|
||||
captureGestures='open'
|
||||
type={Platform.OS === 'ios' ? 'static' : 'displace'}
|
||||
acceptTap={true}
|
||||
acceptPanOnDrawer={false}
|
||||
disabled={false}
|
||||
content={this.renderContent()}
|
||||
tapToClose={true}
|
||||
openDrawerOffset={openDrawerOffset}
|
||||
onRequestClose={this.closeChannelDrawer}
|
||||
panOpenMask={0.2}
|
||||
panCloseMask={openDrawerOffset}
|
||||
panThreshold={0.25}
|
||||
acceptPan={true}
|
||||
negotiatePan={true}
|
||||
useInteractionManager={false}
|
||||
tweenDuration={100}
|
||||
tweenHandler={this.handleDrawerTween}
|
||||
elevation={-5}
|
||||
bottomPanOffset={Platform.OS === 'ios' ? ANDROID_TOP_LANDSCAPE : IOS_TOP_PORTRAIT}
|
||||
topPanOffset={Platform.OS === 'ios' ? iosTop : androidTop}
|
||||
styles={{
|
||||
main: {
|
||||
shadowColor: '#000000',
|
||||
shadowOpacity: 0.4,
|
||||
shadowRadius: 12,
|
||||
shadowOffset: {
|
||||
width: -4,
|
||||
height: 0,
|
||||
},
|
||||
},
|
||||
}}
|
||||
renderNavigationView={this.renderNavigationView}
|
||||
onDrawerClose={this.handleDrawerClose}
|
||||
onDrawerOpen={this.handleDrawerOpen}
|
||||
drawerWidth={deviceWidth - openDrawerOffset}
|
||||
>
|
||||
{children}
|
||||
</Drawer>
|
||||
</DrawerLayout>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -6,15 +6,18 @@ import {connect} from 'react-redux';
|
|||
|
||||
import {logout, setStatus} from 'mattermost-redux/actions/users';
|
||||
import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
|
||||
|
||||
import SettingsDrawer from './settings_drawer';
|
||||
import {getCurrentUser, getStatusForUserId} from 'mattermost-redux/selectors/entities/users';
|
||||
|
||||
import {getDimensions} from 'app/selectors/device';
|
||||
|
||||
import SettingsSidebar from './settings_sidebar';
|
||||
|
||||
function mapStateToProps(state) {
|
||||
const currentUser = getCurrentUser(state);
|
||||
const status = getStatusForUserId(state, currentUser.id);
|
||||
|
||||
return {
|
||||
...getDimensions(state),
|
||||
currentUser,
|
||||
status,
|
||||
theme: getTheme(state),
|
||||
|
|
@ -30,4 +33,4 @@ function mapDispatchToProps(dispatch) {
|
|||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps, null, {withRef: true})(SettingsDrawer);
|
||||
export default connect(mapStateToProps, mapDispatchToProps, null, {withRef: true})(SettingsSidebar);
|
||||
|
|
@ -8,17 +8,16 @@ import {
|
|||
BackHandler,
|
||||
InteractionManager,
|
||||
Keyboard,
|
||||
Platform,
|
||||
ScrollView,
|
||||
View,
|
||||
} from 'react-native';
|
||||
import DrawerLayout from 'react-native-drawer-layout';
|
||||
import MaterialIcon from 'react-native-vector-icons/MaterialIcons';
|
||||
|
||||
import {General} from 'mattermost-redux/constants';
|
||||
import EventEmitter from 'mattermost-redux/utils/event_emitter';
|
||||
|
||||
import SafeAreaView from 'app/components/safe_area_view';
|
||||
import Drawer from 'app/components/drawer';
|
||||
import UserStatus from 'app/components/user_status';
|
||||
import {NavigationTypes} from 'app/constants';
|
||||
import {confirmOutOfOfficeDisabled} from 'app/utils/status';
|
||||
|
|
@ -40,8 +39,9 @@ export default class SettingsDrawer extends PureComponent {
|
|||
blurPostTextBox: PropTypes.func.isRequired,
|
||||
children: PropTypes.node,
|
||||
currentUser: PropTypes.object.isRequired,
|
||||
status: PropTypes.string.isRequired,
|
||||
deviceWidth: PropTypes.number.isRequired,
|
||||
navigator: PropTypes.object,
|
||||
status: PropTypes.string.isRequired,
|
||||
theme: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
|
|
@ -56,10 +56,7 @@ export default class SettingsDrawer extends PureComponent {
|
|||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.closeHandle = null;
|
||||
this.openHandle = null;
|
||||
|
||||
MaterialIcon.getImageSource('close', 20, this.props.theme.sidebarHeaderTextColor).then((source) => {
|
||||
MaterialIcon.getImageSource('close', 20, props.theme.sidebarHeaderTextColor).then((source) => {
|
||||
this.closeButton = source;
|
||||
});
|
||||
}
|
||||
|
|
@ -73,68 +70,30 @@ export default class SettingsDrawer extends PureComponent {
|
|||
}
|
||||
|
||||
handleAndroidBack = () => {
|
||||
if (this.refs.drawer && this.refs.drawer.isOpened()) {
|
||||
this.refs.drawer.close();
|
||||
if (this.refs.drawer) {
|
||||
this.refs.drawer.closeDrawer();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
openSettingsDrawer = () => {
|
||||
openSettingsSidebar = () => {
|
||||
this.props.blurPostTextBox();
|
||||
|
||||
if (this.refs.drawer && !this.refs.drawer.isOpened()) {
|
||||
this.refs.drawer.open();
|
||||
if (this.refs.drawer) {
|
||||
this.refs.drawer.openDrawer();
|
||||
}
|
||||
};
|
||||
|
||||
closeSettingsDrawer = () => {
|
||||
if (this.refs.drawer && this.refs.drawer.isOpened()) {
|
||||
this.refs.drawer.close();
|
||||
}
|
||||
};
|
||||
|
||||
handleDrawerTween = (ratio) => {
|
||||
const opacity = (ratio / 2);
|
||||
|
||||
EventEmitter.emit('drawer_opacity', opacity);
|
||||
|
||||
return {
|
||||
mainOverlay: {
|
||||
backgroundColor: '#000',
|
||||
elevation: 3,
|
||||
opacity,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
handleDrawerClose = () => {
|
||||
if (this.closeHandle) {
|
||||
InteractionManager.clearInteractionHandle(this.closeHandle);
|
||||
this.closeHandle = null;
|
||||
}
|
||||
};
|
||||
|
||||
handleDrawerCloseStart = () => {
|
||||
if (!this.closeHandle) {
|
||||
this.closeHandle = InteractionManager.createInteractionHandle();
|
||||
closeSettingsSidebar = () => {
|
||||
if (this.refs.drawer) {
|
||||
this.refs.drawer.closeDrawer();
|
||||
}
|
||||
};
|
||||
|
||||
handleDrawerOpen = () => {
|
||||
Keyboard.dismiss();
|
||||
|
||||
if (this.openHandle) {
|
||||
InteractionManager.clearInteractionHandle(this.openHandle);
|
||||
this.openHandle = null;
|
||||
}
|
||||
};
|
||||
|
||||
handleDrawerOpenStart = () => {
|
||||
if (!this.openHandle) {
|
||||
this.openHandle = InteractionManager.createInteractionHandle();
|
||||
}
|
||||
};
|
||||
|
||||
handleSetStatus = preventDoubleTap(() => {
|
||||
|
|
@ -185,7 +144,6 @@ export default class SettingsDrawer extends PureComponent {
|
|||
const {currentUser} = this.props;
|
||||
const {formatMessage} = this.context.intl;
|
||||
|
||||
this.closeSettingsDrawer();
|
||||
this.openModal(
|
||||
'EditProfile',
|
||||
formatMessage({id: 'mobile.routes.edit_profile', defaultMessage: 'Edit Profile'}),
|
||||
|
|
@ -196,7 +154,6 @@ export default class SettingsDrawer extends PureComponent {
|
|||
goToFlagged = preventDoubleTap(() => {
|
||||
const {formatMessage} = this.context.intl;
|
||||
|
||||
this.closeSettingsDrawer();
|
||||
this.openModal(
|
||||
'FlaggedPosts',
|
||||
formatMessage({id: 'search_header.title3', defaultMessage: 'Flagged Posts'}),
|
||||
|
|
@ -206,7 +163,6 @@ export default class SettingsDrawer extends PureComponent {
|
|||
goToMentions = preventDoubleTap(() => {
|
||||
const {intl} = this.context;
|
||||
|
||||
this.closeSettingsDrawer();
|
||||
this.openModal(
|
||||
'RecentMentions',
|
||||
intl.formatMessage({id: 'search_header.title2', defaultMessage: 'Recent Mentions'}),
|
||||
|
|
@ -216,7 +172,6 @@ export default class SettingsDrawer extends PureComponent {
|
|||
goToSettings = preventDoubleTap(() => {
|
||||
const {intl} = this.context;
|
||||
|
||||
this.closeSettingsDrawer();
|
||||
this.openModal(
|
||||
'Settings',
|
||||
intl.formatMessage({id: 'mobile.routes.settings', defaultMessage: 'Settings'}),
|
||||
|
|
@ -225,33 +180,36 @@ export default class SettingsDrawer extends PureComponent {
|
|||
|
||||
logout = preventDoubleTap(() => {
|
||||
const {logout} = this.props.actions;
|
||||
this.closeSettingsDrawer();
|
||||
InteractionManager.runAfterInteractions(logout);
|
||||
this.closeSettingsSidebar();
|
||||
logout();
|
||||
});
|
||||
|
||||
openModal = (screen, title, passProps) => {
|
||||
const {navigator, theme} = this.props;
|
||||
|
||||
this.closeSettingsDrawer();
|
||||
navigator.showModal({
|
||||
screen,
|
||||
title,
|
||||
animationType: 'slide-up',
|
||||
animated: true,
|
||||
backButtonTitle: '',
|
||||
navigatorStyle: {
|
||||
navBarTextColor: theme.sidebarHeaderTextColor,
|
||||
navBarBackgroundColor: theme.sidebarHeaderBg,
|
||||
navBarButtonColor: theme.sidebarHeaderTextColor,
|
||||
screenBackgroundColor: theme.centerChannelBg,
|
||||
},
|
||||
navigatorButtons: {
|
||||
leftButtons: [{
|
||||
id: 'close-settings',
|
||||
icon: this.closeButton,
|
||||
}],
|
||||
},
|
||||
passProps,
|
||||
this.closeSettingsSidebar();
|
||||
|
||||
InteractionManager.runAfterInteractions(() => {
|
||||
navigator.showModal({
|
||||
screen,
|
||||
title,
|
||||
animationType: 'slide-up',
|
||||
animated: true,
|
||||
backButtonTitle: '',
|
||||
navigatorStyle: {
|
||||
navBarTextColor: theme.sidebarHeaderTextColor,
|
||||
navBarBackgroundColor: theme.sidebarHeaderBg,
|
||||
navBarButtonColor: theme.sidebarHeaderTextColor,
|
||||
screenBackgroundColor: theme.centerChannelBg,
|
||||
},
|
||||
navigatorButtons: {
|
||||
leftButtons: [{
|
||||
id: 'close-settings',
|
||||
icon: this.closeButton,
|
||||
}],
|
||||
},
|
||||
passProps,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -270,7 +228,7 @@ export default class SettingsDrawer extends PureComponent {
|
|||
);
|
||||
};
|
||||
|
||||
renderContent = () => {
|
||||
renderNavigationView = () => {
|
||||
const {currentUser, navigator, theme} = this.props;
|
||||
const style = getStyleSheet(theme);
|
||||
|
||||
|
|
@ -382,50 +340,18 @@ export default class SettingsDrawer extends PureComponent {
|
|||
};
|
||||
|
||||
render() {
|
||||
const {children} = this.props;
|
||||
const {children, deviceWidth} = this.props;
|
||||
|
||||
return (
|
||||
<Drawer
|
||||
<DrawerLayout
|
||||
ref='drawer'
|
||||
onOpenStart={this.handleDrawerOpenStart}
|
||||
onOpen={this.handleDrawerOpen}
|
||||
onClose={this.handleDrawerClose}
|
||||
onCloseStart={this.handleDrawerCloseStart}
|
||||
side='right'
|
||||
captureGestures='open'
|
||||
type='overlay'
|
||||
acceptTap={true}
|
||||
acceptPanOnDrawer={false}
|
||||
disabled={false}
|
||||
content={this.renderContent()}
|
||||
tapToClose={true}
|
||||
openDrawerOffset={DRAWER_INITIAL_OFFSET}
|
||||
onRequestClose={this.closeSettingsDrawer}
|
||||
panOpenMask={0.05}
|
||||
panCloseMask={DRAWER_INITIAL_OFFSET}
|
||||
panThreshold={0.25}
|
||||
acceptPan={true}
|
||||
negotiatePan={true}
|
||||
useInteractionManager={false}
|
||||
tweenDuration={100}
|
||||
tweenHandler={this.handleDrawerTween}
|
||||
elevation={5}
|
||||
bottomPanOffset={Platform.OS === 'ios' ? 46 : 64}
|
||||
topPanOffset={Platform.OS === 'ios' ? 64 : 46}
|
||||
styles={{
|
||||
main: {
|
||||
shadowColor: '#000000',
|
||||
shadowOpacity: 0.4,
|
||||
shadowRadius: 12,
|
||||
shadowOffset: {
|
||||
width: -4,
|
||||
height: 0,
|
||||
},
|
||||
},
|
||||
}}
|
||||
renderNavigationView={this.renderNavigationView}
|
||||
onDrawerOpen={this.handleDrawerOpen}
|
||||
drawerPosition='right'
|
||||
drawerWidth={deviceWidth - DRAWER_INITIAL_OFFSET}
|
||||
>
|
||||
{children}
|
||||
</Drawer>
|
||||
</DrawerLayout>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -8,7 +8,9 @@ import {
|
|||
ScrollView,
|
||||
ViewPagerAndroid,
|
||||
Platform,
|
||||
StyleSheet, InteractionManager,
|
||||
StyleSheet,
|
||||
InteractionManager,
|
||||
PanResponder,
|
||||
} from 'react-native';
|
||||
|
||||
export default class Swiper extends PureComponent {
|
||||
|
|
@ -52,6 +54,21 @@ export default class Swiper extends PureComponent {
|
|||
this.state = this.initialState(props);
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this.panResponder = PanResponder.create({
|
||||
onStartShouldSetPanResponder: () => true,
|
||||
onStartShouldSetPanResponderCapture: () => true,
|
||||
onMoveShouldSetPanResponder: () => true,
|
||||
onMoveShouldSetPanResponderCapture: () => true,
|
||||
});
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (this.props.width !== nextProps.width) {
|
||||
this.scrollByWidth(nextProps.width);
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
// If the index has changed, we notify the parent via the onIndexChanged callback
|
||||
if (this.state.index !== prevState.index) {
|
||||
|
|
@ -61,7 +78,6 @@ export default class Swiper extends PureComponent {
|
|||
|
||||
initialState = (props) => {
|
||||
const index = props.initialPage;
|
||||
|
||||
return {
|
||||
index,
|
||||
total: React.Children.count(props.children),
|
||||
|
|
@ -69,20 +85,7 @@ export default class Swiper extends PureComponent {
|
|||
};
|
||||
|
||||
onLayout = (e) => {
|
||||
this.offset = e.nativeEvent.layout.width * this.state.index;
|
||||
|
||||
if (this.runOnLayout) {
|
||||
if (Platform.OS === 'ios') {
|
||||
setTimeout(() => {
|
||||
if (this.scrollView) {
|
||||
this.scrollView.scrollTo({x: this.props.width * this.state.index, animated: false});
|
||||
}
|
||||
}, 100);
|
||||
} else if (this.scrollView) {
|
||||
this.scrollView.setPageWithoutAnimation(this.state.index);
|
||||
}
|
||||
this.runOnLayout = false;
|
||||
}
|
||||
this.scrollByWidth(e.nativeEvent.layout.width);
|
||||
};
|
||||
|
||||
onScrollBegin = () => {
|
||||
|
|
@ -114,6 +117,20 @@ export default class Swiper extends PureComponent {
|
|||
}
|
||||
};
|
||||
|
||||
scrollByWidth = (width) => {
|
||||
this.offset = width * this.state.index;
|
||||
|
||||
if (Platform.OS === 'ios') {
|
||||
setTimeout(() => {
|
||||
if (this.scrollView) {
|
||||
this.scrollView.scrollTo({x: width * this.state.index, animated: false});
|
||||
}
|
||||
}, 0);
|
||||
} else if (this.scrollView) {
|
||||
this.scrollView.setPageWithoutAnimation(this.state.index);
|
||||
}
|
||||
};
|
||||
|
||||
scrollToStart = () => {
|
||||
if (Platform.OS === 'ios') {
|
||||
InteractionManager.runAfterInteractions(() => {
|
||||
|
|
@ -135,6 +152,7 @@ export default class Swiper extends PureComponent {
|
|||
if (Platform.OS === 'ios') {
|
||||
return (
|
||||
<ScrollView
|
||||
{...this.panResponder.panHandlers}
|
||||
ref={this.refScrollView}
|
||||
bounces={false}
|
||||
horizontal={true}
|
||||
|
|
@ -147,7 +165,7 @@ export default class Swiper extends PureComponent {
|
|||
onMomentumScrollEnd={this.onScrollEnd}
|
||||
pagingEnabled={true}
|
||||
keyboardShouldPersistTaps={keyboardShouldPersistTaps}
|
||||
scrollEnabled={scrollEnabled}
|
||||
scrollEnabled={true}
|
||||
>
|
||||
{pages}
|
||||
</ScrollView>
|
||||
|
|
@ -287,7 +305,8 @@ const styles = StyleSheet.create({
|
|||
flex: 1,
|
||||
},
|
||||
slide: {
|
||||
backgroundColor: 'transparent',
|
||||
flex: 1,
|
||||
width: '100%',
|
||||
},
|
||||
pagination: {
|
||||
position: 'absolute',
|
||||
|
|
|
|||
|
|
@ -6,15 +6,18 @@ import PropTypes from 'prop-types';
|
|||
import {intlShape} from 'react-intl';
|
||||
import {
|
||||
AppState,
|
||||
Dimensions,
|
||||
Platform,
|
||||
View,
|
||||
} from 'react-native';
|
||||
import DeviceInfo from 'react-native-device-info';
|
||||
|
||||
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 ChannelLoader from 'app/components/channel_loader';
|
||||
import MainSidebar from 'app/components/sidebars/main';
|
||||
import SettingsSidebar from 'app/components/sidebars/settings';
|
||||
import KeyboardLayout from 'app/components/layout/keyboard_layout';
|
||||
import OfflineIndicator from 'app/components/offline_indicator';
|
||||
import SafeAreaView from 'app/components/safe_area_view';
|
||||
|
|
@ -30,6 +33,15 @@ import LocalConfig from 'assets/config';
|
|||
import ChannelNavBar from './channel_nav_bar';
|
||||
import ChannelPostList from './channel_post_list';
|
||||
|
||||
import {ViewTypes} from 'app/constants';
|
||||
const {
|
||||
ANDROID_TOP_LANDSCAPE,
|
||||
ANDROID_TOP_PORTRAIT,
|
||||
IOS_TOP_LANDSCAPE,
|
||||
IOS_TOP_PORTRAIT,
|
||||
IOSX_TOP_PORTRAIT,
|
||||
} = ViewTypes;
|
||||
|
||||
let ClientUpgradeListener;
|
||||
|
||||
export default class Channel extends PureComponent {
|
||||
|
|
@ -61,6 +73,8 @@ export default class Channel extends PureComponent {
|
|||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.isX = DeviceInfo.getModel() === 'iPhone X';
|
||||
|
||||
if (LocalConfig.EnableMobileClientUpgrade && !ClientUpgradeListener) {
|
||||
ClientUpgradeListener = require('app/components/client_upgrade_listener').default;
|
||||
}
|
||||
|
|
@ -137,15 +151,41 @@ export default class Channel extends PureComponent {
|
|||
}
|
||||
};
|
||||
|
||||
channelDrawerRef = (ref) => {
|
||||
channelLoaderDimensions = () => {
|
||||
const {isLandscape} = this.props;
|
||||
let top = 0;
|
||||
let {height} = Dimensions.get('window');
|
||||
switch (Platform.OS) {
|
||||
case 'android':
|
||||
if (isLandscape) {
|
||||
top = ANDROID_TOP_LANDSCAPE;
|
||||
} else {
|
||||
top = ANDROID_TOP_PORTRAIT;
|
||||
height = (height - 84);
|
||||
}
|
||||
break;
|
||||
case 'ios':
|
||||
if (isLandscape) {
|
||||
top = IOS_TOP_LANDSCAPE;
|
||||
} else {
|
||||
height = this.isX ? (height - IOSX_TOP_PORTRAIT) : (height - IOS_TOP_PORTRAIT);
|
||||
top = this.isX ? IOSX_TOP_PORTRAIT : IOS_TOP_PORTRAIT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return {height, top};
|
||||
};
|
||||
|
||||
channelSidebarRef = (ref) => {
|
||||
if (ref) {
|
||||
this.channelDrawer = ref.getWrappedInstance();
|
||||
this.channelSidebar = ref.getWrappedInstance();
|
||||
}
|
||||
};
|
||||
|
||||
settingsDrawerRef = (ref) => {
|
||||
settingsSidebarRef = (ref) => {
|
||||
if (ref) {
|
||||
this.settingsDrawer = ref.getWrappedInstance();
|
||||
this.settingsSidebar = ref.getWrappedInstance();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -231,15 +271,15 @@ export default class Channel extends PureComponent {
|
|||
});
|
||||
};
|
||||
|
||||
openChannelDrawer = () => {
|
||||
if (this.channelDrawer) {
|
||||
this.channelDrawer.openChannelDrawer();
|
||||
openChannelSidebar = () => {
|
||||
if (this.channelSidebar) {
|
||||
this.channelSidebar.openChannelSidebar();
|
||||
}
|
||||
};
|
||||
|
||||
openSettingsDrawer = () => {
|
||||
if (this.settingsDrawer) {
|
||||
this.settingsDrawer.openSettingsDrawer();
|
||||
openSettingsSidebar = () => {
|
||||
if (this.settingsSidebar) {
|
||||
this.settingsSidebar.openSettingsSidebar();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -248,10 +288,10 @@ export default class Channel extends PureComponent {
|
|||
};
|
||||
|
||||
render() {
|
||||
const {intl} = this.context;
|
||||
const {
|
||||
channelsRequestFailed,
|
||||
currentChannelId,
|
||||
isLandscape,
|
||||
navigator,
|
||||
theme,
|
||||
} = this.props;
|
||||
|
|
@ -283,15 +323,17 @@ export default class Channel extends PureComponent {
|
|||
);
|
||||
}
|
||||
|
||||
const loaderDimensions = this.channelLoaderDimensions();
|
||||
|
||||
// console.warn('height', height, Date.now())
|
||||
return (
|
||||
<ChannelDrawer
|
||||
ref={this.channelDrawerRef}
|
||||
<MainSidebar
|
||||
ref={this.channelSidebarRef}
|
||||
blurPostTextBox={this.blurPostTextBox}
|
||||
intl={intl}
|
||||
navigator={navigator}
|
||||
>
|
||||
<SettingsDrawer
|
||||
ref={this.settingsDrawerRef}
|
||||
<SettingsSidebar
|
||||
ref={this.settingsSidebarRef}
|
||||
blurPostTextBox={this.blurPostTextBox}
|
||||
navigator={navigator}
|
||||
>
|
||||
|
|
@ -300,8 +342,8 @@ export default class Channel extends PureComponent {
|
|||
<OfflineIndicator/>
|
||||
<ChannelNavBar
|
||||
navigator={navigator}
|
||||
openChannelDrawer={this.openChannelDrawer}
|
||||
openSettingsDrawer={this.openSettingsDrawer}
|
||||
openChannelDrawer={this.openChannelSidebar}
|
||||
openSettingsDrawer={this.openSettingsSidebar}
|
||||
onPress={this.goToChannelInfo}
|
||||
/>
|
||||
<KeyboardLayout>
|
||||
|
|
@ -313,10 +355,14 @@ export default class Channel extends PureComponent {
|
|||
navigator={navigator}
|
||||
/>
|
||||
</KeyboardLayout>
|
||||
<ChannelLoader
|
||||
style={[style.channelLoader, loaderDimensions]}
|
||||
maxRows={isLandscape ? 4 : 6}
|
||||
/>
|
||||
{LocalConfig.EnableMobileClientUpgrade && <ClientUpgradeListener navigator={navigator}/>}
|
||||
</SafeAreaView>
|
||||
</SettingsDrawer>
|
||||
</ChannelDrawer>
|
||||
</SettingsSidebar>
|
||||
</MainSidebar>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -330,5 +376,10 @@ const getStyleFromTheme = makeStyleSheetFromTheme((theme) => {
|
|||
backgroundColor: theme.centerChannelBg,
|
||||
flex: 1,
|
||||
},
|
||||
channelLoader: {
|
||||
position: 'absolute',
|
||||
width: '100%',
|
||||
flex: 1,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import {
|
||||
BackHandler,
|
||||
Platform,
|
||||
ScrollView,
|
||||
StyleSheet,
|
||||
|
|
@ -22,12 +23,25 @@ export default class Code extends React.PureComponent {
|
|||
content: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
BackHandler.addEventListener('hardwareBackPress', this.handleAndroidBack);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (this.props.theme !== nextProps.theme) {
|
||||
setNavigatorStyles(this.props.navigator, nextProps.theme);
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
BackHandler.removeEventListener('hardwareBackPress', this.handleAndroidBack);
|
||||
}
|
||||
|
||||
handleAndroidBack = () => {
|
||||
this.props.navigator.pop();
|
||||
return true;
|
||||
};
|
||||
|
||||
countLines = (content) => {
|
||||
return content.split('\n').length;
|
||||
};
|
||||
|
|
|
|||
33
package-lock.json
generated
33
package-lock.json
generated
|
|
@ -14666,22 +14666,10 @@
|
|||
"resolved": "https://registry.npmjs.org/react-native-document-picker/-/react-native-document-picker-2.1.0.tgz",
|
||||
"integrity": "sha512-BFCBXwz8xuLvHLVFVeQM+RhaY8yZ38PEWt9WSbq5VIoZ/VssP6uu51XxOfdwaMALOrAHIojK0SiYnd155upZAg=="
|
||||
},
|
||||
"react-native-drawer": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/react-native-drawer/-/react-native-drawer-2.5.0.tgz",
|
||||
"integrity": "sha512-I8rGv0EM6PxRWeq8g463OBt4DYoTri7v9rh98Qpg9q/JToZYTIjavjY0BwchDwyV7J5LdAg7IPbfZUYBkZJsZQ==",
|
||||
"requires": {
|
||||
"prop-types": "^15.5.8",
|
||||
"tween-functions": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"react-native-drawer-layout": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/react-native-drawer-layout/-/react-native-drawer-layout-1.3.2.tgz",
|
||||
"integrity": "sha512-fjO0scqbJUfNu2wuEpvywL7DYLXuCXJ2W/zYhWz986rdLytidbys1QGVvkaszHrb4Y7OqO96mTkgpOcP8KWevw==",
|
||||
"requires": {
|
||||
"react-native-dismiss-keyboard": "1.0.0"
|
||||
}
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/react-native-drawer-layout/-/react-native-drawer-layout-2.0.0.tgz",
|
||||
"integrity": "sha512-zYmzv+4QKDwxmAj7pF1yr8VUb+Hp7oBlwMjRZsvv56vPwO89I+kPTI8G78uwSNIf5b4e/iOChE4vpB5J2XsJFA=="
|
||||
},
|
||||
"react-native-drawer-layout-polyfill": {
|
||||
"version": "1.3.2",
|
||||
|
|
@ -14689,6 +14677,16 @@
|
|||
"integrity": "sha512-XzPhfLDJrYHru+e8+dFwhf0FtTeAp7JXPpFYezYV6P1nTeA1Tia/kDpFT+O2DWTrBKBEI8FGhZnThrroZmHIxg==",
|
||||
"requires": {
|
||||
"react-native-drawer-layout": "1.3.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"react-native-drawer-layout": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/react-native-drawer-layout/-/react-native-drawer-layout-1.3.2.tgz",
|
||||
"integrity": "sha512-fjO0scqbJUfNu2wuEpvywL7DYLXuCXJ2W/zYhWz986rdLytidbys1QGVvkaszHrb4Y7OqO96mTkgpOcP8KWevw==",
|
||||
"requires": {
|
||||
"react-native-dismiss-keyboard": "1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"react-native-exception-handler": {
|
||||
|
|
@ -17795,11 +17793,6 @@
|
|||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"tween-functions": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/tween-functions/-/tween-functions-1.2.0.tgz",
|
||||
"integrity": "sha1-GuOlDnxguz3vd06scHrLynO7w/8="
|
||||
},
|
||||
"tweetnacl": {
|
||||
"version": "0.14.5",
|
||||
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
"react-native-device-info": "enahum/react-native-device-info.git#a7bb3cff1086780b2c791a3e43e5b826fdf3ab11",
|
||||
"react-native-doc-viewer": "2.7.8",
|
||||
"react-native-document-picker": "2.1.0",
|
||||
"react-native-drawer": "2.5.0",
|
||||
"react-native-drawer-layout": "2.0.0",
|
||||
"react-native-exception-handler": "2.7.5",
|
||||
"react-native-fast-image": "4.0.8",
|
||||
"react-native-fetch-blob": "enahum/react-native-fetch-blob.git#27983c83d7fad1cb4821dd6ba8e405da4af64f3a",
|
||||
|
|
|
|||
Loading…
Reference in a new issue