[CHORE] Create DimensionsContext (#2098)

Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com>

Co-authored-by: Diego Mello <diegolmello@gmail.com>
This commit is contained in:
Ezequiel de Oliveira 2020-06-17 14:35:58 -03:00 committed by GitHub
parent 2632ef50f5
commit 36b37eb747
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 148 additions and 103 deletions

View File

@ -19,11 +19,7 @@ import Animated, {
Easing Easing
} from 'react-native-reanimated'; } from 'react-native-reanimated';
import * as Haptics from 'expo-haptics'; import * as Haptics from 'expo-haptics';
import { import { useBackHandler } from '@react-native-community/hooks';
useDimensions,
useBackHandler,
useDeviceOrientation
} from '@react-native-community/hooks';
import { Item } from './Item'; import { Item } from './Item';
import { Handle } from './Handle'; import { Handle } from './Handle';
@ -33,6 +29,7 @@ import styles, { ITEM_HEIGHT } from './styles';
import { isTablet, isIOS } from '../../utils/deviceInfo'; import { isTablet, isIOS } from '../../utils/deviceInfo';
import Separator from '../Separator'; import Separator from '../Separator';
import I18n from '../../i18n'; import I18n from '../../i18n';
import { useOrientation, useDimensions } from '../../dimensions';
const getItemLayout = (data, index) => ({ length: ITEM_HEIGHT, offset: ITEM_HEIGHT * index, index }); const getItemLayout = (data, index) => ({ length: ITEM_HEIGHT, offset: ITEM_HEIGHT * index, index });
@ -52,10 +49,9 @@ const ActionSheet = React.memo(forwardRef(({ children, theme }, ref) => {
const bottomSheetRef = useRef(); const bottomSheetRef = useRef();
const [data, setData] = useState({}); const [data, setData] = useState({});
const [isVisible, setVisible] = useState(false); const [isVisible, setVisible] = useState(false);
const orientation = useDeviceOrientation(); const { height } = useDimensions();
const { height } = useDimensions().window; const { isLandscape } = useOrientation();
const insets = useSafeAreaInsets(); const insets = useSafeAreaInsets();
const { landscape } = orientation;
const maxSnap = Math.max( const maxSnap = Math.max(
( (
@ -81,7 +77,7 @@ const ActionSheet = React.memo(forwardRef(({ children, theme }, ref) => {
* we'll provide more one snap * we'll provide more one snap
* that point 50% of the whole screen * that point 50% of the whole screen
*/ */
const snaps = (height - maxSnap > height * 0.6) && !landscape ? [maxSnap, height * 0.5, height] : [maxSnap, height]; const snaps = (height - maxSnap > height * 0.6) && !isLandscape ? [maxSnap, height * 0.5, height] : [maxSnap, height];
const openedSnapIndex = snaps.length > 2 ? 1 : 0; const openedSnapIndex = snaps.length > 2 ? 1 : 0;
const closedSnapIndex = snaps.length - 1; const closedSnapIndex = snaps.length - 1;
@ -120,7 +116,7 @@ const ActionSheet = React.memo(forwardRef(({ children, theme }, ref) => {
// Hides action sheet when orientation changes // Hides action sheet when orientation changes
useEffect(() => { useEffect(() => {
setVisible(false); setVisible(false);
}, [orientation.landscape]); }, [isLandscape]);
useImperativeHandle(ref, () => ({ useImperativeHandle(ref, () => ({
showActionSheet: show, showActionSheet: show,
@ -186,7 +182,7 @@ const ActionSheet = React.memo(forwardRef(({ children, theme }, ref) => {
containerStyle={[ containerStyle={[
styles.container, styles.container,
{ backgroundColor: themes[theme].focusedBackground }, { backgroundColor: themes[theme].focusedBackground },
(landscape || isTablet) && styles.bottomSheet (isLandscape || isTablet) && styles.bottomSheet
]} ]}
animationConfig={ANIMATION_CONFIG} animationConfig={ANIMATION_CONFIG}
// FlatList props // FlatList props

View File

@ -1,7 +1,6 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Text, TouchableOpacity, FlatList } from 'react-native'; import { Text, TouchableOpacity, FlatList } from 'react-native';
import { responsive } from 'react-native-responsive-ui';
import shortnameToUnicode from '../../utils/shortnameToUnicode'; import shortnameToUnicode from '../../utils/shortnameToUnicode';
import styles from './styles'; import styles from './styles';
@ -25,7 +24,6 @@ class EmojiCategory extends React.Component {
static propTypes = { static propTypes = {
baseUrl: PropTypes.string.isRequired, baseUrl: PropTypes.string.isRequired,
emojis: PropTypes.any, emojis: PropTypes.any,
window: PropTypes.any,
onEmojiSelected: PropTypes.func, onEmojiSelected: PropTypes.func,
emojisPerRow: PropTypes.number, emojisPerRow: PropTypes.number,
width: PropTypes.number width: PropTypes.number
@ -73,4 +71,4 @@ class EmojiCategory extends React.Component {
} }
} }
export default responsive(EmojiCategory); export default EmojiCategory;

View File

@ -5,7 +5,6 @@ import Touchable from 'react-native-platform-touchable';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { Notifier } from 'react-native-notifier'; import { Notifier } from 'react-native-notifier';
import { useSafeAreaInsets } from 'react-native-safe-area-context'; import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { useDeviceOrientation } from '@react-native-community/hooks';
import Avatar from '../Avatar'; import Avatar from '../Avatar';
import { CustomIcon } from '../../lib/Icons'; import { CustomIcon } from '../../lib/Icons';
@ -16,6 +15,7 @@ import { getUserSelector } from '../../selectors/login';
import { ROW_HEIGHT } from '../../presentation/RoomItem'; import { ROW_HEIGHT } from '../../presentation/RoomItem';
import { goRoom } from '../../utils/goRoom'; import { goRoom } from '../../utils/goRoom';
import Navigation from '../../lib/Navigation'; import Navigation from '../../lib/Navigation';
import { useOrientation } from '../../dimensions';
const AVATAR_SIZE = 48; const AVATAR_SIZE = 48;
const BUTTON_HIT_SLOP = { const BUTTON_HIT_SLOP = {
@ -70,7 +70,7 @@ const NotifierComponent = React.memo(({
}) => { }) => {
const { theme } = useTheme(); const { theme } = useTheme();
const insets = useSafeAreaInsets(); const insets = useSafeAreaInsets();
const { landscape } = useDeviceOrientation(); const { isLandscape } = useOrientation();
const { id: userId, token } = user; const { id: userId, token } = user;
const { text, payload } = notification; const { text, payload } = notification;
@ -98,7 +98,7 @@ const NotifierComponent = React.memo(({
return ( return (
<View style={[ <View style={[
styles.container, styles.container,
(isMasterDetail || landscape) && styles.small, (isMasterDetail || isLandscape) && styles.small,
{ {
backgroundColor: themes[theme].focusedBackground, backgroundColor: themes[theme].focusedBackground,
borderColor: themes[theme].separatorColor, borderColor: themes[theme].separatorColor,

View File

@ -1,7 +1,7 @@
import React, { useEffect, useState, useCallback } from 'react'; import React, { useEffect, useState, useCallback } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { import {
View, Text, FlatList, StyleSheet, Dimensions View, Text, FlatList, StyleSheet
} from 'react-native'; } from 'react-native';
import { withTheme } from '../../theme'; import { withTheme } from '../../theme';
@ -11,6 +11,7 @@ import shortnameToUnicode from '../../utils/shortnameToUnicode';
import CustomEmoji from '../EmojiPicker/CustomEmoji'; import CustomEmoji from '../EmojiPicker/CustomEmoji';
import database from '../../lib/database'; import database from '../../lib/database';
import { Button } from '../ActionSheet'; import { Button } from '../ActionSheet';
import { useDimensions } from '../../dimensions';
export const HEADER_HEIGHT = 36; export const HEADER_HEIGHT = 36;
@ -86,6 +87,7 @@ const Header = React.memo(({
handleReaction, server, message, theme handleReaction, server, message, theme
}) => { }) => {
const [items, setItems] = useState([]); const [items, setItems] = useState([]);
const { width, height } = useDimensions();
const setEmojis = async() => { const setEmojis = async() => {
try { try {
@ -93,7 +95,6 @@ const Header = React.memo(({
const freqEmojiCollection = db.collections.get('frequently_used_emojis'); const freqEmojiCollection = db.collections.get('frequently_used_emojis');
let freqEmojis = await freqEmojiCollection.query().fetch(); let freqEmojis = await freqEmojiCollection.query().fetch();
const { width, height } = Dimensions.get('window');
const isLandscape = width > height; const isLandscape = width > height;
const size = isLandscape ? width / 2 : width; const size = isLandscape ? width / 2 : width;
const quantity = (size / 50) - 1; const quantity = (size / 50) - 1;

View File

@ -4,7 +4,6 @@ import {
} from 'react-native'; } from 'react-native';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import Modal from 'react-native-modal'; import Modal from 'react-native-modal';
import { responsive } from 'react-native-responsive-ui';
import equal from 'deep-equal'; import equal from 'deep-equal';
import TextInput from '../TextInput'; import TextInput from '../TextInput';
@ -15,6 +14,7 @@ import { isIOS } from '../../utils/deviceInfo';
import { themes } from '../../constants/colors'; import { themes } from '../../constants/colors';
import { CustomIcon } from '../../lib/Icons'; import { CustomIcon } from '../../lib/Icons';
import { withTheme } from '../../theme'; import { withTheme } from '../../theme';
import { withDimensions } from '../../dimensions';
const styles = StyleSheet.create({ const styles = StyleSheet.create({
modal: { modal: {
@ -88,7 +88,7 @@ class UploadModal extends Component {
file: PropTypes.object, file: PropTypes.object,
close: PropTypes.func, close: PropTypes.func,
submit: PropTypes.func, submit: PropTypes.func,
window: PropTypes.object, width: PropTypes.number,
theme: PropTypes.string, theme: PropTypes.string,
isMasterDetail: PropTypes.bool isMasterDetail: PropTypes.bool
} }
@ -112,7 +112,7 @@ class UploadModal extends Component {
shouldComponentUpdate(nextProps, nextState) { shouldComponentUpdate(nextProps, nextState) {
const { name, description, file } = this.state; const { name, description, file } = this.state;
const { window, isVisible, theme } = this.props; const { width, isVisible, theme } = this.props;
if (nextState.name !== name) { if (nextState.name !== name) {
return true; return true;
@ -126,7 +126,7 @@ class UploadModal extends Component {
if (nextProps.isVisible !== isVisible) { if (nextProps.isVisible !== isVisible) {
return true; return true;
} }
if (nextProps.window.width !== window.width) { if (nextProps.width !== width) {
return true; return true;
} }
if (!equal(nextState.file, file)) { if (!equal(nextState.file, file)) {
@ -204,7 +204,7 @@ class UploadModal extends Component {
render() { render() {
const { const {
window: { width }, isVisible, close, isMasterDetail, theme width, isVisible, close, isMasterDetail, theme
} = this.props; } = this.props;
const { name, description } = this.state; const { name, description } = this.state;
return ( return (
@ -246,4 +246,4 @@ class UploadModal extends Component {
} }
} }
export default responsive(withTheme(UploadModal)); export default withDimensions(withTheme(UploadModal));

View File

@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { import {
View, StyleSheet, Text, Easing, Dimensions View, StyleSheet, Text, Easing
} from 'react-native'; } from 'react-native';
import { Audio } from 'expo-av'; import { Audio } from 'expo-av';
import Slider from '@react-native-community/slider'; import Slider from '@react-native-community/slider';
@ -17,6 +17,7 @@ import { themes } from '../../constants/colors';
import { isAndroid, isIOS } from '../../utils/deviceInfo'; import { isAndroid, isIOS } from '../../utils/deviceInfo';
import MessageContext from './Context'; import MessageContext from './Context';
import ActivityIndicator from '../ActivityIndicator'; import ActivityIndicator from '../ActivityIndicator';
import { withDimensions } from '../../dimensions';
const mode = { const mode = {
allowsRecordingIOS: false, allowsRecordingIOS: false,
@ -97,7 +98,8 @@ class MessageAudio extends React.Component {
static propTypes = { static propTypes = {
file: PropTypes.object.isRequired, file: PropTypes.object.isRequired,
theme: PropTypes.string, theme: PropTypes.string,
getCustomEmoji: PropTypes.func getCustomEmoji: PropTypes.func,
scale: PropTypes.number
} }
constructor(props) { constructor(props) {
@ -243,7 +245,9 @@ class MessageAudio extends React.Component {
const { const {
loading, paused, currentTime, duration loading, paused, currentTime, duration
} = this.state; } = this.state;
const { file, getCustomEmoji, theme } = this.props; const {
file, getCustomEmoji, theme, scale
} = this.props;
const { description } = file; const { description } = file;
const { baseUrl, user } = this.context; const { baseUrl, user } = this.context;
@ -271,7 +275,7 @@ class MessageAudio extends React.Component {
minimumTrackTintColor={themes[theme].tintColor} minimumTrackTintColor={themes[theme].tintColor}
maximumTrackTintColor={themes[theme].auxiliaryText} maximumTrackTintColor={themes[theme].auxiliaryText}
onValueChange={this.onValueChange} onValueChange={this.onValueChange}
thumbImage={isIOS && { uri: 'audio_thumb', scale: Dimensions.get('window').scale }} thumbImage={isIOS && { uri: 'audio_thumb', scale }}
/> />
<Text style={[styles.duration, { color: themes[theme].auxiliaryText }]}>{this.duration}</Text> <Text style={[styles.duration, { color: themes[theme].auxiliaryText }]}>{this.duration}</Text>
</View> </View>
@ -281,4 +285,4 @@ class MessageAudio extends React.Component {
} }
} }
export default MessageAudio; export default withDimensions(MessageAudio);

26
app/dimensions.js Normal file
View File

@ -0,0 +1,26 @@
import React from 'react';
import { Dimensions } from 'react-native';
import hoistNonReactStatics from 'hoist-non-react-statics';
export const DimensionsContext = React.createContext(Dimensions.get('window'));
export function withDimensions(Component) {
const DimensionsComponent = props => (
<DimensionsContext.Consumer>
{contexts => <Component {...props} {...contexts} />}
</DimensionsContext.Consumer>
);
hoistNonReactStatics(DimensionsComponent, Component);
return DimensionsComponent;
}
export const useDimensions = () => React.useContext(DimensionsContext);
export const useOrientation = () => {
const { width, height } = React.useContext(DimensionsContext);
const isPortrait = height > width;
return {
isPortrait,
isLandscape: !isPortrait
};
};

View File

@ -21,6 +21,7 @@ import { initializePushNotifications, onNotification } from './notifications/pus
import store from './lib/createStore'; import store from './lib/createStore';
import { loggerConfig, analytics } from './utils/log'; import { loggerConfig, analytics } from './utils/log';
import { ThemeContext } from './theme'; import { ThemeContext } from './theme';
import { DimensionsContext } from './dimensions';
import RocketChat, { THEME_PREFERENCES_KEY } from './lib/rocketchat'; import RocketChat, { THEME_PREFERENCES_KEY } from './lib/rocketchat';
import { MIN_WIDTH_MASTER_DETAIL_LAYOUT } from './constants/tablet'; import { MIN_WIDTH_MASTER_DETAIL_LAYOUT } from './constants/tablet';
import { import {
@ -34,6 +35,7 @@ import ChangePasscodeView from './views/ChangePasscodeView';
import Toast from './containers/Toast'; import Toast from './containers/Toast';
import InAppNotification from './containers/InAppNotification'; import InAppNotification from './containers/InAppNotification';
import { ActionSheetProvider } from './containers/ActionSheet'; import { ActionSheetProvider } from './containers/ActionSheet';
import debounce from './utils/debounce';
RNScreens.enableScreens(); RNScreens.enableScreens();
@ -57,12 +59,16 @@ export default class Root extends React.Component {
super(props); super(props);
this.init(); this.init();
this.initCrashReport(); this.initCrashReport();
const { width, height, scale } = Dimensions.get('window');
this.state = { this.state = {
theme: defaultTheme(), theme: defaultTheme(),
themePreferences: { themePreferences: {
currentTheme: supportSystemTheme() ? 'automatic' : 'light', currentTheme: supportSystemTheme() ? 'automatic' : 'light',
darkLevel: 'dark' darkLevel: 'dark'
} },
width,
height,
scale
}; };
if (isTablet) { if (isTablet) {
this.initTablet(); this.initTablet();
@ -118,9 +124,11 @@ export default class Root extends React.Component {
store.dispatch(setMasterDetailAction(isMasterDetail)); store.dispatch(setMasterDetailAction(isMasterDetail));
}; };
onDimensionsChange = ({ window: { width } }) => { // Dimensions update fires twice
onDimensionsChange = debounce(({ window: { width, height, scale } }) => {
this.setDimensions({ width, height, scale });
this.setMasterDetail(width); this.setMasterDetail(width);
} })
setTheme = (newTheme = {}) => { setTheme = (newTheme = {}) => {
// change theme state // change theme state
@ -131,8 +139,12 @@ export default class Root extends React.Component {
}); });
} }
setDimensions = ({ width, height, scale }) => {
this.setState({ width, height, scale });
}
initTablet = () => { initTablet = () => {
const { width } = Dimensions.get('window'); const { width } = this.state;
this.setMasterDetail(width); this.setMasterDetail(width);
this.onKeyCommands = KeyCommandsEmitter.addListener( this.onKeyCommands = KeyCommandsEmitter.addListener(
'onKeyCommand', 'onKeyCommand',
@ -154,7 +166,9 @@ export default class Root extends React.Component {
} }
render() { render() {
const { themePreferences, theme } = this.state; const {
themePreferences, theme, width, height, scale
} = this.state;
return ( return (
<SafeAreaProvider initialMetrics={initialWindowMetrics}> <SafeAreaProvider initialMetrics={initialWindowMetrics}>
<AppearanceProvider> <AppearanceProvider>
@ -165,6 +179,14 @@ export default class Root extends React.Component {
themePreferences, themePreferences,
setTheme: this.setTheme setTheme: this.setTheme
}} }}
>
<DimensionsContext.Provider
value={{
width,
height,
scale,
setDimensions: this.setDimensions
}}
> >
<ActionSheetProvider> <ActionSheetProvider>
<AppContainer /> <AppContainer />
@ -174,6 +196,7 @@ export default class Root extends React.Component {
<InAppNotification /> <InAppNotification />
<Toast /> <Toast />
</ActionSheetProvider> </ActionSheetProvider>
</DimensionsContext.Provider>
</ThemeContext.Provider> </ThemeContext.Provider>
</Provider> </Provider>
</AppearanceProvider> </AppearanceProvider>

View File

@ -1,4 +1,4 @@
import React from 'react'; import React, { Component } from 'react';
import { StyleSheet, View } from 'react-native'; import { StyleSheet, View } from 'react-native';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { import {
@ -8,7 +8,7 @@ import {
} from 'react-native-gesture-handler'; } from 'react-native-gesture-handler';
import FastImage from 'react-native-fast-image'; import FastImage from 'react-native-fast-image';
import Animated, { Easing } from 'react-native-reanimated'; import Animated, { Easing } from 'react-native-reanimated';
import { ResponsiveComponent } from 'react-native-responsive-ui'; import { withDimensions } from '../../dimensions';
const AnimatedFastImage = Animated.createAnimatedComponent(FastImage); const AnimatedFastImage = Animated.createAnimatedComponent(FastImage);
@ -264,13 +264,10 @@ const HEIGHT = 300;
// it was picked from https://github.com/software-mansion/react-native-reanimated/tree/master/Example/imageViewer // it was picked from https://github.com/software-mansion/react-native-reanimated/tree/master/Example/imageViewer
// and changed to use FastImage animated component // and changed to use FastImage animated component
class ImageViewer extends ResponsiveComponent { class ImageViewer extends Component {
pinchRef = React.createRef();
panRef = React.createRef();
static propTypes = { static propTypes = {
uri: PropTypes.string uri: PropTypes.string,
width: PropTypes.number
} }
constructor(props) { constructor(props) {
@ -382,9 +379,12 @@ class ImageViewer extends ResponsiveComponent {
); );
} }
pinchRef = React.createRef();
panRef = React.createRef();
render() { render() {
const { uri, ...props } = this.props; const { uri, width, ...props } = this.props;
const { width } = this.state.window;
// The below two animated values makes it so that scale appears to be done // The below two animated values makes it so that scale appears to be done
// from the top left corner of the image view instead of its center. This // from the top left corner of the image view instead of its center. This
@ -439,4 +439,4 @@ class ImageViewer extends ResponsiveComponent {
} }
} }
export default ImageViewer; export default withDimensions(ImageViewer);

View File

@ -1,13 +1,13 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { responsive } from 'react-native-responsive-ui';
import equal from 'deep-equal'; import equal from 'deep-equal';
import Header from './Header'; import Header from './Header';
import RightButtons from './RightButtons'; import RightButtons from './RightButtons';
import { withTheme } from '../../../theme'; import { withTheme } from '../../../theme';
import RoomHeaderLeft from './RoomHeaderLeft'; import RoomHeaderLeft from './RoomHeaderLeft';
import { withDimensions } from '../../../dimensions';
class RoomHeaderView extends Component { class RoomHeaderView extends Component {
static propTypes = { static propTypes = {
@ -17,19 +17,20 @@ class RoomHeaderView extends Component {
prid: PropTypes.string, prid: PropTypes.string,
tmid: PropTypes.string, tmid: PropTypes.string,
usersTyping: PropTypes.string, usersTyping: PropTypes.string,
window: PropTypes.object,
status: PropTypes.string, status: PropTypes.string,
statusText: PropTypes.string, statusText: PropTypes.string,
connecting: PropTypes.bool, connecting: PropTypes.bool,
theme: PropTypes.string, theme: PropTypes.string,
roomUserId: PropTypes.string, roomUserId: PropTypes.string,
widthOffset: PropTypes.number, widthOffset: PropTypes.number,
goRoomActionsView: PropTypes.func goRoomActionsView: PropTypes.func,
width: PropTypes.number,
height: PropTypes.number
}; };
shouldComponentUpdate(nextProps) { shouldComponentUpdate(nextProps) {
const { const {
type, title, subtitle, status, statusText, window, connecting, goRoomActionsView, usersTyping, theme type, title, subtitle, status, statusText, connecting, goRoomActionsView, usersTyping, theme, width, height
} = this.props; } = this.props;
if (nextProps.theme !== theme) { if (nextProps.theme !== theme) {
return true; return true;
@ -52,10 +53,10 @@ class RoomHeaderView extends Component {
if (nextProps.connecting !== connecting) { if (nextProps.connecting !== connecting) {
return true; return true;
} }
if (nextProps.window.width !== window.width) { if (nextProps.width !== width) {
return true; return true;
} }
if (nextProps.window.height !== window.height) { if (nextProps.height !== height) {
return true; return true;
} }
if (!equal(nextProps.usersTyping, usersTyping)) { if (!equal(nextProps.usersTyping, usersTyping)) {
@ -64,12 +65,18 @@ class RoomHeaderView extends Component {
if (nextProps.goRoomActionsView !== goRoomActionsView) { if (nextProps.goRoomActionsView !== goRoomActionsView) {
return true; return true;
} }
if (nextProps.width !== width) {
return true;
}
if (nextProps.height !== height) {
return true;
}
return false; return false;
} }
render() { render() {
const { const {
window, title, subtitle, type, prid, tmid, widthOffset, status = 'offline', statusText, connecting, usersTyping, goRoomActionsView, roomUserId, theme title, subtitle, type, prid, tmid, widthOffset, status = 'offline', statusText, connecting, usersTyping, goRoomActionsView, roomUserId, theme, width, height
} = this.props; } = this.props;
return ( return (
@ -80,8 +87,8 @@ class RoomHeaderView extends Component {
subtitle={type === 'd' ? statusText : subtitle} subtitle={type === 'd' ? statusText : subtitle}
type={type} type={type}
status={status} status={status}
width={window.width} width={width}
height={window.height} height={height}
theme={theme} theme={theme}
usersTyping={usersTyping} usersTyping={usersTyping}
widthOffset={widthOffset} widthOffset={widthOffset}
@ -114,6 +121,6 @@ const mapStateToProps = (state, ownProps) => {
}; };
}; };
export default responsive(connect(mapStateToProps)(withTheme(RoomHeaderView))); export default connect(mapStateToProps)(withDimensions(withTheme(RoomHeaderView)));
export { RightButtons, RoomHeaderLeft }; export { RightButtons, RoomHeaderLeft };

View File

@ -3,7 +3,6 @@ import PropTypes from 'prop-types';
import { View } from 'react-native'; import { View } from 'react-native';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import Modal from 'react-native-modal'; import Modal from 'react-native-modal';
import { responsive } from 'react-native-responsive-ui';
import EmojiPicker from '../../containers/EmojiPicker'; import EmojiPicker from '../../containers/EmojiPicker';
import styles from './styles'; import styles from './styles';
@ -15,17 +14,18 @@ const maxSize = 400;
class ReactionPicker extends React.Component { class ReactionPicker extends React.Component {
static propTypes = { static propTypes = {
baseUrl: PropTypes.string.isRequired, baseUrl: PropTypes.string.isRequired,
window: PropTypes.any,
message: PropTypes.object, message: PropTypes.object,
show: PropTypes.bool, show: PropTypes.bool,
isMasterDetail: PropTypes.bool, isMasterDetail: PropTypes.bool,
reactionClose: PropTypes.func, reactionClose: PropTypes.func,
onEmojiSelected: PropTypes.func onEmojiSelected: PropTypes.func,
width: PropTypes.number,
height: PropTypes.number
}; };
shouldComponentUpdate(nextProps) { shouldComponentUpdate(nextProps) {
const { show, window } = this.props; const { show, width, height } = this.props;
return nextProps.show !== show || window.width !== nextProps.window.width; return nextProps.show !== show || width !== nextProps.width || height !== nextProps.height;
} }
onEmojiSelected = (emoji, shortname) => { onEmojiSelected = (emoji, shortname) => {
@ -38,7 +38,7 @@ class ReactionPicker extends React.Component {
render() { render() {
const { const {
window: { width, height }, show, baseUrl, reactionClose, isMasterDetail width, height, show, baseUrl, reactionClose, isMasterDetail
} = this.props; } = this.props;
let widthStyle = width - margin; let widthStyle = width - margin;
@ -87,4 +87,4 @@ const mapStateToProps = state => ({
isMasterDetail: state.app.isMasterDetail isMasterDetail: state.app.isMasterDetail
}); });
export default responsive(connect(mapStateToProps)(ReactionPicker)); export default connect(mapStateToProps)(ReactionPicker);

View File

@ -3,7 +3,6 @@ import {
View, Text, StyleSheet, TouchableOpacity, ScrollView View, Text, StyleSheet, TouchableOpacity, ScrollView
} from 'react-native'; } from 'react-native';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { responsive } from 'react-native-responsive-ui';
import { Q } from '@nozbe/watermelondb'; import { Q } from '@nozbe/watermelondb';
import database from '../../lib/database'; import database from '../../lib/database';
@ -56,7 +55,7 @@ const styles = StyleSheet.create({
class UploadProgress extends Component { class UploadProgress extends Component {
static propTypes = { static propTypes = {
window: PropTypes.object, width: PropTypes.number,
rid: PropTypes.string, rid: PropTypes.string,
theme: PropTypes.string, theme: PropTypes.string,
user: PropTypes.shape({ user: PropTypes.shape({
@ -167,7 +166,7 @@ class UploadProgress extends Component {
} }
renderItemContent = (item) => { renderItemContent = (item) => {
const { window, theme } = this.props; const { width, theme } = this.props;
if (!item.error) { if (!item.error) {
return ( return (
@ -179,7 +178,7 @@ class UploadProgress extends Component {
</Text> </Text>
<CustomIcon name='Cross' size={20} color={themes[theme].auxiliaryText} onPress={() => this.cancelUpload(item)} /> <CustomIcon name='Cross' size={20} color={themes[theme].auxiliaryText} onPress={() => this.cancelUpload(item)} />
</View>, </View>,
<View key='progress' style={[styles.progress, { width: (window.width * item.progress) / 100, backgroundColor: themes[theme].tintColor }]} /> <View key='progress' style={[styles.progress, { width: (width * item.progress) / 100, backgroundColor: themes[theme].tintColor }]} />
] ]
); );
} }
@ -228,4 +227,4 @@ class UploadProgress extends Component {
} }
} }
export default responsive(withTheme(UploadProgress)); export default withTheme(UploadProgress);

View File

@ -52,6 +52,7 @@ import { CONTAINER_TYPES } from '../../lib/methods/actions';
import Banner from './Banner'; import Banner from './Banner';
import Navigation from '../../lib/Navigation'; import Navigation from '../../lib/Navigation';
import SafeAreaView from '../../containers/SafeAreaView'; import SafeAreaView from '../../containers/SafeAreaView';
import { withDimensions } from '../../dimensions';
const stateAttrsUpdate = [ const stateAttrsUpdate = [
'joined', 'joined',
@ -88,7 +89,9 @@ class RoomView extends React.Component {
customEmojis: PropTypes.object, customEmojis: PropTypes.object,
isMasterDetail: PropTypes.bool, isMasterDetail: PropTypes.bool,
theme: PropTypes.string, theme: PropTypes.string,
replyBroadcast: PropTypes.func replyBroadcast: PropTypes.func,
width: PropTypes.number,
height: PropTypes.number
}; };
constructor(props) { constructor(props) {
@ -963,7 +966,7 @@ class RoomView extends React.Component {
room, reactionsModalVisible, selectedMessage, loading, reacting room, reactionsModalVisible, selectedMessage, loading, reacting
} = this.state; } = this.state;
const { const {
user, baseUrl, theme, navigation, Hide_System_Messages user, baseUrl, theme, navigation, Hide_System_Messages, width, height
} = this.props; } = this.props;
const { const {
rid, t, sysMes, bannerClosed, announcement rid, t, sysMes, bannerClosed, announcement
@ -1004,8 +1007,10 @@ class RoomView extends React.Component {
message={selectedMessage} message={selectedMessage}
onEmojiSelected={this.onReactionPress} onEmojiSelected={this.onReactionPress}
reactionClose={this.onReactionClose} reactionClose={this.onReactionClose}
width={width}
height={height}
/> />
<UploadProgress rid={this.rid} user={user} baseUrl={baseUrl} /> <UploadProgress rid={this.rid} user={user} baseUrl={baseUrl} width={width} />
<ReactionsModal <ReactionsModal
message={selectedMessage} message={selectedMessage}
isVisible={reactionsModalVisible} isVisible={reactionsModalVisible}
@ -1037,4 +1042,4 @@ const mapDispatchToProps = dispatch => ({
replyBroadcast: message => dispatch(replyBroadcastAction(message)) replyBroadcast: message => dispatch(replyBroadcastAction(message))
}); });
export default connect(mapStateToProps, mapDispatchToProps)(withTheme(RoomView)); export default connect(mapStateToProps, mapDispatchToProps)(withDimensions(withTheme(RoomView)));

View File

@ -6,7 +6,6 @@ import {
BackHandler, BackHandler,
Text, Text,
Keyboard, Keyboard,
Dimensions,
RefreshControl RefreshControl
} from 'react-native'; } from 'react-native';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
@ -61,6 +60,7 @@ import { getUserSelector } from '../../selectors/login';
import { goRoom } from '../../utils/goRoom'; import { goRoom } from '../../utils/goRoom';
import SafeAreaView from '../../containers/SafeAreaView'; import SafeAreaView from '../../containers/SafeAreaView';
import Header from '../../containers/Header'; import Header from '../../containers/Header';
import { withDimensions } from '../../dimensions';
const SCROLL_OFFSET = 56; const SCROLL_OFFSET = 56;
const INITIAL_NUM_TO_RENDER = isTablet ? 20 : 12; const INITIAL_NUM_TO_RENDER = isTablet ? 20 : 12;
@ -128,7 +128,8 @@ class RoomsListView extends React.Component {
useRealName: PropTypes.bool, useRealName: PropTypes.bool,
connected: PropTypes.bool, connected: PropTypes.bool,
isMasterDetail: PropTypes.bool, isMasterDetail: PropTypes.bool,
rooms: PropTypes.array rooms: PropTypes.array,
width: PropTypes.number
}; };
constructor(props) { constructor(props) {
@ -138,14 +139,12 @@ class RoomsListView extends React.Component {
this.gotSubscriptions = false; this.gotSubscriptions = false;
this.animated = false; this.animated = false;
const { width } = Dimensions.get('window');
this.state = { this.state = {
searching: false, searching: false,
search: [], search: [],
loading: true, loading: true,
allChats: [], allChats: [],
chats: [], chats: [],
width,
item: {} item: {}
}; };
this.setHeader(); this.setHeader();
@ -157,7 +156,6 @@ class RoomsListView extends React.Component {
if (isTablet) { if (isTablet) {
EventEmitter.addEventListener(KEY_COMMAND, this.handleCommands); EventEmitter.addEventListener(KEY_COMMAND, this.handleCommands);
} }
Dimensions.addEventListener('change', this.onDimensionsChange);
this.unsubscribeFocus = navigation.addListener('focus', () => { this.unsubscribeFocus = navigation.addListener('focus', () => {
Orientation.unlockAllOrientations(); Orientation.unlockAllOrientations();
this.animated = true; this.animated = true;
@ -228,14 +226,13 @@ class RoomsListView extends React.Component {
const { const {
loading, loading,
width,
search search
} = this.state; } = this.state;
const { rooms } = this.props; const { rooms, width } = this.props;
if (nextState.loading !== loading) { if (nextState.loading !== loading) {
return true; return true;
} }
if (nextState.width !== width) { if (nextProps.width !== width) {
return true; return true;
} }
if (!isEqual(nextState.search, search)) { if (!isEqual(nextState.search, search)) {
@ -302,7 +299,6 @@ class RoomsListView extends React.Component {
if (isTablet) { if (isTablet) {
EventEmitter.removeListener(KEY_COMMAND, this.handleCommands); EventEmitter.removeListener(KEY_COMMAND, this.handleCommands);
} }
Dimensions.removeEventListener('change', this.onDimensionsChange);
console.countReset(`${ this.constructor.name }.render calls`); console.countReset(`${ this.constructor.name }.render calls`);
} }
@ -352,9 +348,6 @@ class RoomsListView extends React.Component {
navigation.setOptions(options); navigation.setOptions(options);
} }
// eslint-disable-next-line react/sort-comp
onDimensionsChange = ({ window: { width } }) => this.setState({ width });
internalSetState = (...args) => { internalSetState = (...args) => {
if (this.animated) { if (this.animated) {
animateNextTransition(); animateNextTransition();
@ -783,7 +776,7 @@ class RoomsListView extends React.Component {
return this.renderSectionHeader(item.rid); return this.renderSectionHeader(item.rid);
} }
const { width, item: currentItem } = this.state; const { item: currentItem } = this.state;
const { const {
user: { user: {
id: userId, id: userId,
@ -794,7 +787,8 @@ class RoomsListView extends React.Component {
StoreLastMessage, StoreLastMessage,
useRealName, useRealName,
theme, theme,
isMasterDetail isMasterDetail,
width
} = this.props; } = this.props;
const id = this.getUidDirectMessage(item); const id = this.getUidDirectMessage(item);
const isGroupChat = RocketChat.isGroupChat(item); const isGroupChat = RocketChat.isGroupChat(item);
@ -945,4 +939,4 @@ const mapDispatchToProps = dispatch => ({
closeServerDropdown: () => dispatch(closeServerDropdownAction()) closeServerDropdown: () => dispatch(closeServerDropdownAction())
}); });
export default connect(mapStateToProps, mapDispatchToProps)(withTheme(RoomsListView)); export default connect(mapStateToProps, mapDispatchToProps)(withDimensions(withTheme(RoomsListView)));

View File

@ -91,7 +91,6 @@
"react-native-progress": "4.1.2", "react-native-progress": "4.1.2",
"react-native-prompt-android": "^1.1.0", "react-native-prompt-android": "^1.1.0",
"react-native-reanimated": "^1.8.0", "react-native-reanimated": "^1.8.0",
"react-native-responsive-ui": "^1.1.1",
"react-native-safe-area-context": "^3.0.2", "react-native-safe-area-context": "^3.0.2",
"react-native-screens": "^2.7.0", "react-native-screens": "^2.7.0",
"react-native-scroll-bottom-sheet": "0.6.1", "react-native-scroll-bottom-sheet": "0.6.1",

View File

@ -11944,13 +11944,6 @@ react-native-reanimated@^1.8.0:
dependencies: dependencies:
fbjs "^1.0.0" fbjs "^1.0.0"
react-native-responsive-ui@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/react-native-responsive-ui/-/react-native-responsive-ui-1.1.1.tgz#eb41839d4f3951ff025660185c36a9a9ce33759f"
integrity sha1-60GDnU85Uf8CVmAYXDapqc4zdZ8=
dependencies:
lodash "^4.17.4"
react-native-safe-area-context@^3.0.2: react-native-safe-area-context@^3.0.2:
version "3.0.2" version "3.0.2"
resolved "https://registry.yarnpkg.com/react-native-safe-area-context/-/react-native-safe-area-context-3.0.2.tgz#95dd7e56bc89bcc4f3f7bb5fada30c98420328b2" resolved "https://registry.yarnpkg.com/react-native-safe-area-context/-/react-native-safe-area-context-3.0.2.tgz#95dd7e56bc89bcc4f3f7bb5fada30c98420328b2"