Repository: kiwicom/mobile
Pull request #764 (2018-06-26 08:13:05)

Hotels: Fix isDateBeforeToday bug

tbergq: Ok, thanks for pointing this out. I will try to solve it differently.
tbergq: I added some new functions to date utils, isBeforeDate & isAfterDate. 

I also found another issue, that if dates passed from native code to AllHotels would be null or undefined, we should really set a date, so we do not search with invalid dates. 

please have a second look @RobinCsl 

Patch:
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 02fd97ce..5d42c2a6 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -13,7 +13,7 @@
 
         <meta-data android:name="com.google.android.geo.API_KEY" android:value="@string/google_maps_key" />
 
-        <activity android:name=".MainActivity" android:label="@string/app_name" android:configChanges="keyboard|keyboardHidden|orientation|screenSize" android:windowSoftInputMode="adjustResize">
+        <activity android:name=".MainActivity" android:label="@string/app_name" android:configChanges="keyboard|keyboardHidden|orientation|screenSize|smallestScreenSize|screenLayout" android:windowSoftInputMode="adjustResize">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
diff --git a/app/App.js b/app/App.js
index 28c995d1..ab0ae924 100644
--- a/app/App.js
+++ b/app/App.js
@@ -1,3 +1,18 @@
 // @flow
 
-export { default } from './core/src/navigation';
+import React from 'react';
+import { type DimensionType, Dimensions } from '@kiwicom/mobile-shared';
+
+import Navigation from './core/src/navigation';
+
+type initialProps = {|
+  +dimensions: DimensionType,
+|};
+
+export default function App(props: initialProps) {
+  return (
+    <Dimensions.Provider dimensions={props.dimensions}>
+      <Navigation />
+    </Dimensions.Provider>
+  );
+}
diff --git a/app/MMB/index.js b/app/MMB/index.js
index c0f37e9f..cc77dbac 100644
--- a/app/MMB/index.js
+++ b/app/MMB/index.js
@@ -3,7 +3,7 @@
 import * as React from 'react';
 import { AppRegistry } from 'react-native';
 import { AuthContext } from '@kiwicom/mobile-relay';
-import { AdaptableLayout } from '@kiwicom/mobile-shared';
+import { Dimensions, type DimensionType } from '@kiwicom/mobile-shared';
 
 import NavigationStack from './src/navigation/NavigationStack';
 import BookingDetailContext from './src/context/BookingDetailContext';
@@ -11,17 +11,18 @@ import BookingDetailContext from './src/context/BookingDetailContext';
 type Props = {|
   currency: string,
   accessToken: string,
+  dimensions: DimensionType,
 |};
 
 class ManageMyBookingPackage extends React.Component<Props> {
   render = () => (
-    <AdaptableLayout.Provider>
+    <Dimensions.Provider dimensions={this.props.dimensions}>
       <AuthContext.Provider accessToken={this.props.accessToken}>
         <BookingDetailContext.Provider>
           <NavigationStack />
         </BookingDetailContext.Provider>
       </AuthContext.Provider>
-    </AdaptableLayout.Provider>
+    </Dimensions.Provider>
   );
 }
 
diff --git a/app/MMB/src/components/header/Header.js b/app/MMB/src/components/header/Header.js
index 722c7765..b64e22b6 100644
--- a/app/MMB/src/components/header/Header.js
+++ b/app/MMB/src/components/header/Header.js
@@ -59,7 +59,7 @@ class Header extends React.Component<HeaderProps, HeaderState> {
     const booking = idx(this.props, _ => _.data);
 
     return (
-      <AdaptableLayout.Consumer
+      <AdaptableLayout
         renderOnWide={
           <React.Fragment>
             <HeaderShared data={booking}>
diff --git a/app/MMB/src/navigation/DetailScreen.js b/app/MMB/src/navigation/DetailScreen.js
index f5f9b125..ef90c49f 100644
--- a/app/MMB/src/navigation/DetailScreen.js
+++ b/app/MMB/src/navigation/DetailScreen.js
@@ -180,7 +180,7 @@ export default class DetailsScreen extends React.Component<Props, State> {
     return (
       <LayoutDoubleColumn
         menuComponent={
-          <AdaptableLayout.Consumer
+          <AdaptableLayout
             renderOnWide={
               <MainMenuContainer openMenu={this.changeContentOnTablet} />
             }
diff --git a/app/MMB/src/scenes/list/FlightList.js b/app/MMB/src/scenes/list/FlightList.js
index c5f7c983..bd5389e9 100644
--- a/app/MMB/src/scenes/list/FlightList.js
+++ b/app/MMB/src/scenes/list/FlightList.js
@@ -3,7 +3,12 @@
 import * as React from 'react';
 import { View } from 'react-native';
 import { graphql, createFragmentContainer } from '@kiwicom/mobile-relay';
-import { StyleSheet, Device, AdaptableLayout } from '@kiwicom/mobile-shared';
+import {
+  StyleSheet,
+  Device,
+  AdaptableLayout,
+  Dimensions,
+} from '@kiwicom/mobile-shared';
 import idx from 'idx';
 
 import OneWayFlight from './OneWayFlight';
@@ -20,17 +25,6 @@ type State = {|
 |};
 
 export class FlightList extends React.Component<Props, State> {
-  state = {
-    isPortrait: true,
-  };
-
-  componentDidMount = () => this.onLayoutChange();
-
-  onLayoutChange = () => {
-    const isPortrait = Device.isPortrait();
-    this.setState({ isPortrait });
-  };
-
   render = () => {
     const flights = idx(this.props, _ => _.data.edges);
 
@@ -55,19 +49,26 @@ export class FlightList extends React.Component<Props, State> {
       }
 
       return (
-        <AdaptableLayout.Consumer
+        <AdaptableLayout
           key={key}
           renderOnNarrow={<View style={styles.itemContainer}>{Component}</View>}
           renderOnWide={
-            <View
-              style={[
-                styles.itemContainer,
-                this.state.isPortrait ? styles.portrait : styles.landscape,
-              ]}
-              onLayout={this.onLayoutChange}
-            >
-              {Component}
-            </View>
+            <Dimensions.Consumer>
+              {dimensions => {
+                return (
+                  <View
+                    style={[
+                      styles.itemContainer,
+                      Device.isPortrait(dimensions)
+                        ? styles.portrait
+                        : styles.landscape,
+                    ]}
+                  >
+                    {Component}
+                  </View>
+                );
+              }}
+            </Dimensions.Consumer>
           }
         />
       );
diff --git a/app/MMB/src/scenes/list/FlightListContainer.js b/app/MMB/src/scenes/list/FlightListContainer.js
index 5373180a..e43c134c 100644
--- a/app/MMB/src/scenes/list/FlightListContainer.js
+++ b/app/MMB/src/scenes/list/FlightListContainer.js
@@ -59,7 +59,7 @@ class FlightListContainer extends React.Component<Props, State> {
         <Text style={styles.subtitle}>
           <Translation id="mmb.my_bookings.future_trips" />
         </Text>
-        <AdaptableLayout.Consumer
+        <AdaptableLayout
           renderOnNarrow={<FlightList data={this.props.future} />}
           renderOnWide={
             <View style={styles.tabletWrapper}>
@@ -70,7 +70,7 @@ class FlightListContainer extends React.Component<Props, State> {
         <Text style={styles.subtitle}>
           <Translation id="mmb.my_bookings.past_trips" />
         </Text>
-        <AdaptableLayout.Consumer
+        <AdaptableLayout
           renderOnNarrow={<FlightList data={this.props.past} />}
           renderOnWide={
             <View style={styles.tabletWrapper}>
diff --git a/app/core/src/screens/HotelsPackageWrapper.js b/app/core/src/screens/HotelsPackageWrapper.js
index 50f5f54c..fd573a05 100644
--- a/app/core/src/screens/HotelsPackageWrapper.js
+++ b/app/core/src/screens/HotelsPackageWrapper.js
@@ -3,6 +3,7 @@
 import * as React from 'react';
 import { HotelsStandalonePackage } from '@kiwicom/react-native-app-hotels';
 import { type NavigationType } from '@kiwicom/mobile-navigation';
+import { type DimensionType } from '@kiwicom/mobile-shared';
 
 import Config from '../../config/application';
 
@@ -14,6 +15,7 @@ type Props = {|
   |},
   checkin?: string,
   checkout?: string,
+  dimensions: DimensionType,
 |};
 
 export default class HotelsPackageWrapper extends React.Component<Props> {
@@ -33,6 +35,7 @@ export default class HotelsPackageWrapper extends React.Component<Props> {
         coordinates={coordinates}
         checkin={this.props.checkin}
         checkout={this.props.checkout}
+        dimensions={this.props.dimensions}
       />
     );
   };
diff --git a/app/core/src/screens/MMBPackageWrapper.js b/app/core/src/screens/MMBPackageWrapper.js
index 73e22deb..93bb642d 100644
--- a/app/core/src/screens/MMBPackageWrapper.js
+++ b/app/core/src/screens/MMBPackageWrapper.js
@@ -5,10 +5,11 @@ import { AsyncStorage, View } from 'react-native';
 import { ManageMyBookingPackage } from '@kiwicom/mobile-manage-my-booking';
 import { type NavigationType } from '@kiwicom/mobile-navigation';
 import { Translation } from '@kiwicom/mobile-localization';
-import { StyleSheet } from '@kiwicom/mobile-shared';
+import { StyleSheet, type DimensionType } from '@kiwicom/mobile-shared';
 
 type Props = {|
   navigation: NavigationType,
+  dimensions: DimensionType,
 |};
 
 export default class MMBPackageWrapper extends React.Component<
@@ -58,7 +59,11 @@ export default class MMBPackageWrapper extends React.Component<
     }
 
     return (
-      <ManageMyBookingPackage currency="EUR" accessToken={this.state.token} />
+      <ManageMyBookingPackage
+        dimensions={this.props.dimensions}
+        currency="EUR"
+        accessToken={this.state.token}
+      />
     );
   };
 }
diff --git a/app/core/src/screens/SingleHotelPackageWrapper.js b/app/core/src/screens/SingleHotelPackageWrapper.js
index 3485a258..e00f511b 100644
--- a/app/core/src/screens/SingleHotelPackageWrapper.js
+++ b/app/core/src/screens/SingleHotelPackageWrapper.js
@@ -4,11 +4,13 @@ import * as React from 'react';
 import { SingleHotelStandalonePackage } from '@kiwicom/react-native-app-hotels';
 import { type NavigationType } from '@kiwicom/mobile-navigation';
 import { DateFormatter, DateUtils } from '@kiwicom/mobile-localization';
+import { type DimensionType } from '@kiwicom/mobile-shared';
 
 import Config from '../../config/application';
 
 type Props = {|
   navigation: NavigationType,
+  dimensions: DimensionType,
 |};
 
 export default class SingleHotelPackageWrapper extends React.Component<Props> {
@@ -27,6 +29,7 @@ export default class SingleHotelPackageWrapper extends React.Component<Props> {
         checkout={DateFormatter(DateUtils().addDays(7)).formatForMachine()}
         hotelId="aG90ZWw6ODAyMDQ="
         roomsConfiguration={[{ adultsCount: 1, children: [] }]}
+        dimensions={this.props.dimensions}
       />
     );
   };
diff --git a/app/hotels/src/appRegistry/HotelsStandalonePackage.js b/app/hotels/src/appRegistry/HotelsStandalonePackage.js
index 09d836ec..6fc9441b 100644
--- a/app/hotels/src/appRegistry/HotelsStandalonePackage.js
+++ b/app/hotels/src/appRegistry/HotelsStandalonePackage.js
@@ -1,7 +1,10 @@
 // @flow
 
 import * as React from 'react';
-import { WithNativeNavigation } from '@kiwicom/mobile-shared';
+import {
+  WithNativeNavigation,
+  type DimensionType,
+} from '@kiwicom/mobile-shared';
 
 import RootComponent from './RootComponent';
 import HotelsStack from '../navigation/NavigationStack';
@@ -17,6 +20,7 @@ type Props = {
   checkout?: string,
   onNavigationStateChange: () => void,
   onBackClicked: () => void,
+  dimensions: DimensionType,
 };
 
 class HotelsStandalonePackage extends React.Component<Props> {
@@ -40,7 +44,10 @@ class HotelsStandalonePackage extends React.Component<Props> {
 
   render = () => {
     return (
-      <RootComponent dataSaverEnabled={this.props.dataSaverEnabled}>
+      <RootComponent
+        dimensions={this.props.dimensions}
+        dataSaverEnabled={this.props.dataSaverEnabled}
+      >
         {this.renderInnerComponent()}
       </RootComponent>
     );
diff --git a/app/hotels/src/appRegistry/RootComponent.js b/app/hotels/src/appRegistry/RootComponent.js
index e6054363..14298650 100644
--- a/app/hotels/src/appRegistry/RootComponent.js
+++ b/app/hotels/src/appRegistry/RootComponent.js
@@ -3,10 +3,9 @@
 import * as React from 'react';
 import { ConfigContext } from '@kiwicom/mobile-config';
 import {
-  Device,
   GeolocationContext,
-  AdaptableLayout,
-  type OnLayout,
+  Dimensions,
+  type DimensionType,
 } from '@kiwicom/mobile-shared';
 
 import HotelsSearchContext from '../HotelsSearchContext';
@@ -15,22 +14,18 @@ import HotelsFilterContext from '../HotelsFilterContext';
 type Props = {|
   dataSaverEnabled: boolean,
   children: React.Node,
+  dimensions: DimensionType,
 |};
 
 export default class RootComponent extends React.Component<Props> {
-  emitDimensionChanges = (event: OnLayout) => {
-    const { width, height } = event.nativeEvent.layout;
-    Device.emitDimensionChanges(height, width);
-  };
-
   render = () => (
     <ConfigContext.Provider dataSaverEnabled={this.props.dataSaverEnabled}>
       <HotelsSearchContext.Provider>
         <HotelsFilterContext.Provider>
           <GeolocationContext.Provider>
-            <AdaptableLayout.Provider>
+            <Dimensions.Provider dimensions={this.props.dimensions}>
               {this.props.children}
-            </AdaptableLayout.Provider>
+            </Dimensions.Provider>
           </GeolocationContext.Provider>
         </HotelsFilterContext.Provider>
       </HotelsSearchContext.Provider>
diff --git a/app/hotels/src/appRegistry/SingleHotelStandalonePackage.js b/app/hotels/src/appRegistry/SingleHotelStandalonePackage.js
index d8d08353..6c7ce22c 100644
--- a/app/hotels/src/appRegistry/SingleHotelStandalonePackage.js
+++ b/app/hotels/src/appRegistry/SingleHotelStandalonePackage.js
@@ -1,7 +1,10 @@
 // @flow
 
 import * as React from 'react';
-import { WithNativeNavigation } from '@kiwicom/mobile-shared';
+import {
+  WithNativeNavigation,
+  type DimensionType,
+} from '@kiwicom/mobile-shared';
 
 import RootComponent from './RootComponent';
 import SingleHotelStack from '../navigation/singleHotel/SingleHotelStack';
@@ -18,6 +21,7 @@ type Props = {
   language: string,
   onNavigationStateChange: () => void,
   onBackClicked: () => void,
+  dimensions: DimensionType,
 };
 
 class SingleHotelStandAlonePackage extends React.Component<Props> {
@@ -41,7 +45,10 @@ class SingleHotelStandAlonePackage extends React.Component<Props> {
 
   render = () => {
     return (
-      <RootComponent dataSaverEnabled={this.props.dataSaverEnabled}>
+      <RootComponent
+        dimensions={this.props.dimensions}
+        dataSaverEnabled={this.props.dataSaverEnabled}
+      >
         {this.renderInnerComponent()}
       </RootComponent>
     );
diff --git a/app/hotels/src/gallery/GalleryGrid.js b/app/hotels/src/gallery/GalleryGrid.js
index 2a4a758b..6c23e61f 100644
--- a/app/hotels/src/gallery/GalleryGrid.js
+++ b/app/hotels/src/gallery/GalleryGrid.js
@@ -5,9 +5,9 @@ import { FlatList } from 'react-native';
 import {
   GeneralError,
   Modal,
-  Device,
-  type OnLayout,
   StyleSheet,
+  type OnLayout,
+  type DimensionType,
 } from '@kiwicom/mobile-shared';
 import { Translation } from '@kiwicom/mobile-localization';
 
@@ -31,6 +31,7 @@ export type Image = {
 
 type Props = {|
   hotelName: string,
+  dimensions: DimensionType,
   images: Image[],
   onGoToGalleryStripe: (
     hotelName: string,
@@ -47,34 +48,30 @@ type State = {|
 
 export default class GalleryGrid extends React.Component<Props, State> {
   state = {
-    tileWidth: 0,
+    /**
+     * This assumes that the gallery is expanded over the whole screen
+     * without additional paddings (this is how it's designed).
+     *
+     * Event `onLayout` attached to the `FlatList` is called after all
+     * images are loaded which is too late (works good on iOS). But it's
+     * still needed for portrait <-> layout changes.
+     */
+    tileWidth: this.getTileWidth(this.props.dimensions.width),
     stripeVisible: false,
     stripeImageIndex: 0,
   };
 
-  /**
-   * This assumes that the gallery is expanded over the whole screen
-   * without additional paddings (this is how it's designed).
-   *
-   * Event `onLayout` attached to the `FlatList` is called after all
-   * images are loaded which is too late (works good on iOS). But it's
-   * still needed for portrait <-> layout changes.
-   */
-  componentDidMount = () => {
-    this.updateTileWidth(Device.getDimensions().width);
-  };
-
   calculateTileWidth = (event: OnLayout) => {
     const width = event.nativeEvent.layout.width;
-    this.updateTileWidth(width);
-  };
-
-  updateTileWidth = (width: number) => {
     this.setState({
-      tileWidth: (width - tileGap * (tilesInRow - 1)) / tilesInRow,
+      tileWidth: this.getTileWidth(width),
     });
   };
 
+  getTileWidth = (width: number) => {
+    return width - (tileGap * (tilesInRow - 1)) / tilesInRow;
+  };
+
   openStripe = (imageIndex: number) =>
     this.setState({
       stripeVisible: true,
diff --git a/app/hotels/src/map/allHotels/AllHotelsMap.js b/app/hotels/src/map/allHotels/AllHotelsMap.js
index 7e7310ff..005d48f8 100644
--- a/app/hotels/src/map/allHotels/AllHotelsMap.js
+++ b/app/hotels/src/map/allHotels/AllHotelsMap.js
@@ -106,7 +106,7 @@ class AllHotelsMap extends React.Component<PropsWithContext> {
         onStateChange={this.validateCheckinDate}
       >
         <View style={styles.container}>
-          <AdaptableLayout.Consumer
+          <AdaptableLayout
             renderOnNarrow={<FilterStripe currency={currency} />}
           />
           {canSearch ? (
diff --git a/app/hotels/src/map/allHotels/HotelSwipeList.js b/app/hotels/src/map/allHotels/HotelSwipeList.js
index b9843f00..0769fedc 100644
--- a/app/hotels/src/map/allHotels/HotelSwipeList.js
+++ b/app/hotels/src/map/allHotels/HotelSwipeList.js
@@ -45,7 +45,7 @@ const styles = StyleSheet.create({
     width: '100%',
   },
   wide: {
-    maxWidth: Device.getWideDeviceThreshold(),
+    maxWidth: Device.DEVICE_THRESHOLD,
   },
   noResultsContainer: {
     alignItems: 'center',
@@ -53,6 +53,8 @@ const styles = StyleSheet.create({
   },
 });
 
+const CARD_ITEM_WIDTH = Device.DEVICE_THRESHOLD * SNAP_WIDTH;
+
 class HotelSwipeList extends React.Component<Props, State> {
   carouselRef: React.ElementRef<typeof Carousel>;
 
@@ -60,10 +62,6 @@ class HotelSwipeList extends React.Component<Props, State> {
     this.carouselRef.snapToItem(this.props.selectedIndex, false);
   };
 
-  getCardItemWidth = () => {
-    return Device.getWideDeviceThreshold() * SNAP_WIDTH;
-  };
-
   getSelectedAddress = () => {
     const { selectedIndex, data } = this.props;
 
@@ -75,7 +73,7 @@ class HotelSwipeList extends React.Component<Props, State> {
 
     return (
       <HotelSwipeItem
-        width={this.getCardItemWidth()}
+        width={CARD_ITEM_WIDTH}
         data={item.node}
         onPress={onOpenSingleHotel}
       />
@@ -99,8 +97,8 @@ class HotelSwipeList extends React.Component<Props, State> {
                 ref={this.storeRef}
                 data={data}
                 renderItem={this.renderItem}
-                sliderWidth={Device.getWideDeviceThreshold()}
-                itemWidth={this.getCardItemWidth()}
+                sliderWidth={Device.DEVICE_THRESHOLD}
+                itemWidth={CARD_ITEM_WIDTH}
                 inactiveSlideScale={1}
                 inactiveSlideOpacity={0.5}
                 decelerationRate="fast"
@@ -122,7 +120,7 @@ class HotelSwipeList extends React.Component<Props, State> {
     );
 
     return (
-      <AdaptableLayout.Consumer
+      <AdaptableLayout
         renderOnWide={
           <View style={[styles.fullWidth, styles.wide]}>{child}</View>
         }
diff --git a/app/hotels/src/map/singleHotel/BottomSheet.js b/app/hotels/src/map/singleHotel/BottomSheet.js
index 31b6f161..9bb9a4a3 100644
--- a/app/hotels/src/map/singleHotel/BottomSheet.js
+++ b/app/hotels/src/map/singleHotel/BottomSheet.js
@@ -13,7 +13,7 @@ import { openHeight, closedHeight } from '../bottomSheetDimensions';
 
 const styles = StyleSheet.create({
   wideContainer: {
-    width: Device.getWideDeviceThreshold(),
+    width: Device.DEVICE_THRESHOLD,
     alignSelf: 'center',
   },
   narrowContainer: {
@@ -35,7 +35,7 @@ export default class BottomSheet extends React.Component<Props> {
     );
 
     return (
-      <AdaptableLayout.Consumer
+      <AdaptableLayout
         renderOnWide={<View style={styles.wideContainer}>{content}</View>}
         renderOnNarrow={<View style={styles.narrowContainer}>{content}</View>}
       />
diff --git a/app/hotels/src/navigation/allHotels/AllHotelsNavigationScreen.js b/app/hotels/src/navigation/allHotels/AllHotelsNavigationScreen.js
index 380a49c6..2cabb284 100644
--- a/app/hotels/src/navigation/allHotels/AllHotelsNavigationScreen.js
+++ b/app/hotels/src/navigation/allHotels/AllHotelsNavigationScreen.js
@@ -51,7 +51,7 @@ export default class AllHotelsNavigationScreen extends React.Component<Props> {
         </HeaderTitle>
       ),
       headerRight: (
-        <AdaptableLayout.Consumer
+        <AdaptableLayout
           renderOnNarrow={<MapHeaderButton onPress={goToAllHotelsMap} />}
         />
       ),
diff --git a/app/hotels/src/navigation/singleHotel/AdditionalPropsInjector.js b/app/hotels/src/navigation/singleHotel/AdditionalPropsInjector.js
index 5c6db171..c2eeb1c4 100644
--- a/app/hotels/src/navigation/singleHotel/AdditionalPropsInjector.js
+++ b/app/hotels/src/navigation/singleHotel/AdditionalPropsInjector.js
@@ -2,6 +2,7 @@
 
 import * as React from 'react';
 import { type NavigationType } from '@kiwicom/mobile-navigation';
+import { Dimensions } from '@kiwicom/mobile-shared';
 
 type InjectorProps = {|
   navigation: NavigationType,
@@ -30,10 +31,15 @@ export default class AdditionalPropsInjecter extends React.Component<
   render = () => {
     const { WrappedComponent } = this.props;
     return (
-      <WrappedComponent
-        {...this.props}
-        onGoToGalleryStripe={this.goToGalleryStripe}
-      />
+      <Dimensions.Consumer>
+        {dimensions => (
+          <WrappedComponent
+            {...this.props}
+            dimensions={dimensions}
+            onGoToGalleryStripe={this.goToGalleryStripe}
+          />
+        )}
+      </Dimensions.Consumer>
     );
   };
 }
diff --git a/app/hotels/src/navigation/singleHotel/SingleHotelStack.js b/app/hotels/src/navigation/singleHotel/SingleHotelStack.js
index 24e0377a..235c182e 100644
--- a/app/hotels/src/navigation/singleHotel/SingleHotelStack.js
+++ b/app/hotels/src/navigation/singleHotel/SingleHotelStack.js
@@ -1,7 +1,7 @@
 // @flow
 
 import * as React from 'react';
-import { Platform } from 'react-native';
+import { Platform, Dimensions as RNDimensions } from 'react-native'; // eslint-disable-line no-restricted-imports
 import { withMappedNavigationAndConfigProps as withMappedProps } from 'react-navigation-props-mapper';
 import {
   HeaderTitle,
@@ -10,7 +10,7 @@ import {
   createTransparentHeaderStyle,
 } from '@kiwicom/mobile-navigation';
 import { Translation } from '@kiwicom/mobile-localization';
-import { Device } from '@kiwicom/mobile-shared';
+import { Dimensions, Device } from '@kiwicom/mobile-shared';
 
 import SingleHotelNavigationScreen from './SingleHotelNavigationScreen';
 import SingleHotelMapNavigationScreen from './SingleHotelMapNavigationScreen';
@@ -23,13 +23,27 @@ export default StackNavigator(
     SingleHotel: {
       screen: SingleHotelNavigationScreen,
       navigationOptions: {
-        headerTitle:
-          Device.isNarrowLayout() && Platform.OS === 'android' ? null : (
-            <HeaderTitle>
-              <Translation id="hotels.navigation.title.single_hotel" />
-            </HeaderTitle>
-          ),
-        ...createTransparentHeaderStyle(),
+        headerTitle: (
+          <Dimensions.Consumer>
+            {dimensions => {
+              return Device.isNarrowLayout(dimensions) &&
+                Platform.OS === 'android' ? null : (
+                <HeaderTitle>
+                  <Translation id="hotels.navigation.title.single_hotel" />
+                </HeaderTitle>
+              );
+            }}
+          </Dimensions.Consumer>
+        ),
+        /**
+         * @todo Due to static nature of React Navigation, this configuration
+         * will not update when screen width changes (when used with SplitView)
+         * or rotates.
+         *
+         * This has to be fixed by providing a custom Header component that forks
+         * React Navigation one and uses Dimensions.Consumer to re-render itself.
+         */
+        ...createTransparentHeaderStyle(RNDimensions.get('screen')),
       },
     },
     SingleHotelMap: {
diff --git a/app/hotels/src/search/SearchQueryHelpers.js b/app/hotels/src/search/SearchQueryHelpers.js
index b70ee0c7..d64e19b8 100644
--- a/app/hotels/src/search/SearchQueryHelpers.js
+++ b/app/hotels/src/search/SearchQueryHelpers.js
@@ -40,14 +40,16 @@ export const getSearchQueryParams = (
 
 export const isDateBeforeToday = (date: Date) => {
   const today = new Date();
-  return date < today && date.getUTCDay() !== today.getUTCDay();
+  return DateUtils.isBeforeDate(date, today);
 };
 
 export const updateCheckinDateIfBeforeToday = (
   search: SearchParams,
   onSearchChange: OnChangeSearchParams => void,
 ) => {
-  if (isDateBeforeToday(search.checkin)) {
+  // In case we do not get sent any dates from native,
+  // we should update if checkin date is missing
+  if (search.checkin == null || isDateBeforeToday(search.checkin)) {
     onSearchChange({
       ...search,
       checkin: new Date(),
diff --git a/app/hotels/src/singleHotel/HotelDetailScreen.js b/app/hotels/src/singleHotel/HotelDetailScreen.js
index 971c9d89..955a2cec 100644
--- a/app/hotels/src/singleHotel/HotelDetailScreen.js
+++ b/app/hotels/src/singleHotel/HotelDetailScreen.js
@@ -124,7 +124,7 @@ export class HotelDetailScreen extends React.Component<Props, State> {
       <React.Fragment>
         <ScrollView>
           <LayoutSingleColumn>
-            <AdaptableLayout.Consumer
+            <AdaptableLayout
               renderOnWide={<View style={styles.marginView} />}
             />
             <Header openGallery={openGallery} hotel={availableHotel.hotel} />
diff --git a/app/hotels/src/singleHotel/header/Header.js b/app/hotels/src/singleHotel/header/Header.js
index e29d9f4c..fe51e2f0 100644
--- a/app/hotels/src/singleHotel/header/Header.js
+++ b/app/hotels/src/singleHotel/header/Header.js
@@ -11,6 +11,7 @@ import {
   AdaptableLayout,
   Device,
   BlackToAlpha as gradient,
+  Dimensions,
 } from '@kiwicom/mobile-shared';
 import { createFragmentContainer, graphql } from '@kiwicom/mobile-relay';
 import { Translation } from '@kiwicom/mobile-localization';
@@ -21,31 +22,35 @@ import Rating from './Rating';
 import type { Image as GalleryGridImage } from '../../gallery/GalleryGrid';
 import type { Header_hotel } from './__generated__/Header_hotel.graphql';
 
-const height = Platform.select({
-  android: Device.isWideLayout() ? 150 : 200,
-  ios: 150,
-});
-
-const styles = StyleSheet.create({
-  picture: {
-    height: height,
-  },
-  galleryButton: {
-    position: 'absolute',
-    end: 10,
-    android: {
-      top: Device.isWideLayout() ? 10 : StatusBar.currentHeight + 16,
+const generateDynamicStyles = dim => {
+  const height = Platform.select({
+    android: Device.isWideLayout(dim) ? 150 : 200,
+    ios: 150,
+  });
+  return {
+    nameAndRatingContainer: {
+      height: height,
+      marginTop: -height,
+      alignItems: 'flex-end',
+      flexDirection: 'row',
     },
-    ios: {
-      top: 10,
+    picture: {
+      height: height,
     },
-  },
-  nameAndRatingContainer: {
-    height: height,
-    marginTop: -height,
-    alignItems: 'flex-end',
-    flexDirection: 'row',
-  },
+    galleryButton: {
+      position: 'absolute',
+      end: 10,
+      android: {
+        top: Device.isWideLayout(dim) ? 10 : StatusBar.currentHeight + 16,
+      },
+      ios: {
+        top: 10,
+      },
+    },
+  };
+};
+
+const styles = StyleSheet.create({
   nameAndRating: {
     marginStart: 15,
     marginEnd: 15,
@@ -102,38 +107,49 @@ export class Header extends React.Component<Props> {
     const mainPhotoUrl = idx(hotel, _ => _.mainPhoto.highResUrl);
     const photosCount = idx(hotel, _ => _.photos.edges.length);
     return (
-      <Touchable onPress={this.openGallery}>
-        <View>
-          <NetworkImage style={styles.picture} source={{ uri: mainPhotoUrl }} />
-          <View style={styles.nameAndRatingContainer}>
-            <StretchedImage source={gradient} />
-            <View style={styles.nameAndRating}>
-              <Text style={styles.hotelName}>
-                <Translation passThrough={idx(hotel, _ => _.name)} />
-              </Text>
-              <Text style={styles.rating}>
-                <Rating
-                  stars={idx(hotel, _ => _.rating.stars)}
-                  score={idx(hotel, _ => _.review.score)}
-                  description={idx(hotel, _ => _.review.description)}
+      <Dimensions.Consumer>
+        {dimensions => {
+          const dynamicStyles = generateDynamicStyles(dimensions);
+
+          return (
+            <Touchable onPress={this.openGallery}>
+              <View>
+                <NetworkImage
+                  style={dynamicStyles.picture}
+                  source={{ uri: mainPhotoUrl }}
                 />
-              </Text>
-            </View>
-          </View>
-          {photosCount && (
-            <View style={styles.galleryButton}>
-              <GalleryButton count={photosCount} />
-            </View>
-          )}
-        </View>
-      </Touchable>
+                <View style={dynamicStyles.nameAndRatingContainer}>
+                  <StretchedImage source={gradient} />
+                  <View style={styles.nameAndRating}>
+                    <Text style={styles.hotelName}>
+                      <Translation passThrough={idx(hotel, _ => _.name)} />
+                    </Text>
+                    <Text style={styles.rating}>
+                      <Rating
+                        stars={idx(hotel, _ => _.rating.stars)}
+                        score={idx(hotel, _ => _.review.score)}
+                        description={idx(hotel, _ => _.review.description)}
+                      />
+                    </Text>
+                  </View>
+                </View>
+                {photosCount && (
+                  <View style={dynamicStyles.galleryButton}>
+                    <GalleryButton count={photosCount} />
+                  </View>
+                )}
+              </View>
+            </Touchable>
+          );
+        }}
+      </Dimensions.Consumer>
     );
   };
 
   render = () => {
     const header = this.renderHeader();
     return (
-      <AdaptableLayout.Consumer
+      <AdaptableLayout
         renderOnNarrow={header}
         renderOnWide={<View style={styles.tabletContainer}>{header}</View>}
       />
diff --git a/app/hotels/src/singleHotel/hotelInformation/HotelInformation.js b/app/hotels/src/singleHotel/hotelInformation/HotelInformation.js
index 6ee63dfb..19035541 100644
--- a/app/hotels/src/singleHotel/hotelInformation/HotelInformation.js
+++ b/app/hotels/src/singleHotel/hotelInformation/HotelInformation.js
@@ -34,7 +34,7 @@ export class HotelInformation extends React.Component<Props> {
 
   render = () => {
     return (
-      <AdaptableLayout.Consumer
+      <AdaptableLayout
         renderOnNarrow={
           <React.Fragment>
             {this.renderLocation(false)}
diff --git a/app/hotels/src/singleHotel/hotelInformation/description/Description.js b/app/hotels/src/singleHotel/hotelInformation/description/Description.js
index b18e0db5..7cf157f2 100644
--- a/app/hotels/src/singleHotel/hotelInformation/description/Description.js
+++ b/app/hotels/src/singleHotel/hotelInformation/description/Description.js
@@ -48,7 +48,7 @@ export class Description extends React.Component<Props> {
 
   render = () => {
     return (
-      <AdaptableLayout.Consumer
+      <AdaptableLayout
         renderOnNarrow={
           <View style={styles.simpleCardWrapper}>
             <SimpleCard>{this.renderCardChildren(false)}</SimpleCard>
diff --git a/app/hotels/src/singleHotel/roomList/RoomRow.js b/app/hotels/src/singleHotel/roomList/RoomRow.js
index f2ea78b6..091d71ad 100644
--- a/app/hotels/src/singleHotel/roomList/RoomRow.js
+++ b/app/hotels/src/singleHotel/roomList/RoomRow.js
@@ -136,7 +136,7 @@ export class RoomRow extends React.Component<Props> {
   };
 
   render = () => (
-    <AdaptableLayout.Consumer
+    <AdaptableLayout
       renderOnNarrow={this.renderRow(false)}
       renderOnWide={this.renderRow(true)}
     />
diff --git a/ios/RNNativePlayground/ViewController.m b/ios/RNNativePlayground/ViewController.m
index 9de10efb..7ff32669 100644
--- a/ios/RNNativePlayground/ViewController.m
+++ b/ios/RNNativePlayground/ViewController.m
@@ -3,13 +3,13 @@
 #import <RNKiwiMobile/RNKiwiMobile.h>
 
 @interface ViewController () <UIGestureRecognizerDelegate, RNKiwiOptions, RNKiwiCurrencyManager, RNKiwiTranslationProvider, RNKiwiViewControllerFlowDelegate>
-  
-  @property (nonatomic, strong) RNKiwiViewController *vc;
-  
-  @end
+
+@property (nonatomic, strong) RNKiwiViewController *vc;
+
+@end
 
 @implementation ViewController
-  
+
 - (instancetype)initWithCoder:(NSCoder *)coder {
   self = [super initWithCoder:coder];
   
@@ -25,7 +25,7 @@
   }
   return self;
 }
-  
+
 - (IBAction)showHotelsView:(id)sender {
   __weak typeof(self) weakSelf = self;
   _vc = [[RNKiwiViewController alloc] initWithOptions:weakSelf];
@@ -35,54 +35,59 @@
   
   [[self navigationController] pushViewController:_vc animated:YES];
 }
-  
+
 # pragma mark - RNKiwiOptions
-  
+
 - (NSDictionary<NSString *, NSObject *> *)initialProperties {
+  CGRect windowRect = self.view.window.frame;
   return @{
            @"coordinates": @{
                @"latitude" : @59.9139,
                @"longitude": @10.7522
                },
            @"language": @"en",
-           @"currency": @"EUR"
+           @"currency": @"EUR",
+           @"dimensions": @{
+               @"width": @(windowRect.size.width),
+               @"height": @(windowRect.size.height)
+               }
            };
 }
-  
+
 - (NSString *)moduleName {
   return @"KiwiHotels";
 }
-  
+
 - (NSURL *)jsCodeLocation {
   return RNKiwiConstants.hotelsBundle;
 }
-  
+
 - (void)viewDidAppear:(BOOL)animated {
   self.navigationController.navigationBar.hidden = YES;
   self.navigationController.interactivePopGestureRecognizer.delegate = self;
 }
-  
+
 # pragma mark - RNKiwiViewControllerFlowDelegate
-  
+
 - (void)RNKiwiViewControllerDidFinish:(nonnull RNKiwiViewController *)viewController {
   [self.navigationController popViewControllerAnimated:YES];
 }
-  
+
 # pragma mark - RNKiwiCurrencyManager
-  
+
 - (NSString *)formattedPrice:(NSNumber *)price withCurrency:(NSString *)currencyCode {
   return [[price stringValue] stringByAppendingString:currencyCode];
 }
-  
+
 #pragma mark - RNKiwiTranslationProvider
-  
+
 - (NSString *)localizedStringWithKey:(NSString *)key {
   // In real app it would give us the String based on localization
   return nil;
 }
-  
+
 #pragma mark - UIGestureRecognizer
-  
+
 - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
   
   if (self.navigationController.interactivePopGestureRecognizer == gestureRecognizer) {
@@ -91,5 +96,5 @@
   
   return YES;
 }
-  
-  @end
+
+@end
diff --git a/packages/localization/src/DateUtils.js b/packages/localization/src/DateUtils.js
index 21c7b247..f5ab22c7 100644
--- a/packages/localization/src/DateUtils.js
+++ b/packages/localization/src/DateUtils.js
@@ -7,6 +7,14 @@ function addDays(date: Date, days: number): Date {
   return result;
 }
 
+const getUTCYearMonthDate = (date: Date) => {
+  return {
+    year: date.getUTCFullYear(),
+    month: date.getUTCMonth(),
+    date: date.getUTCDate(),
+  };
+};
+
 function DateUtils(rawDate: Date = new Date()) {
   return {
     addDays: (count: number) => addDays(rawDate, count),
@@ -26,10 +34,36 @@ DateUtils.diffInDays = (higherDate: Date, lowerDate: Date) => {
 };
 
 DateUtils.isSameDay = (firstDate: Date, secondDate: Date): boolean => {
+  const first = getUTCYearMonthDate(firstDate);
+  const second = getUTCYearMonthDate(secondDate);
+  return (
+    first.year === second.year &&
+    first.month === second.month &&
+    first.date === second.date
+  );
+};
+
+DateUtils.isAfterDate = (firstDate: Date, secondDate: Date): boolean => {
+  const first = getUTCYearMonthDate(firstDate);
+  const second = getUTCYearMonthDate(secondDate);
+  return (
+    first.year > second.year ||
+    (first.year === second.year && first.month > second.month) ||
+    (first.year === second.year &&
+      first.month === second.month &&
+      first.date > second.date)
+  );
+};
+
+DateUtils.isBeforeDate = (firstDate: Date, secondDate: Date): boolean => {
+  const first = getUTCYearMonthDate(firstDate);
+  const second = getUTCYearMonthDate(secondDate);
   return (
-    firstDate.getUTCFullYear() === secondDate.getUTCFullYear() &&
-    firstDate.getUTCMonth() === secondDate.getUTCMonth() &&
-    firstDate.getUTCDate() === secondDate.getUTCDate()
+    first.year < second.year ||
+    (first.year === second.year && first.month < second.month) ||
+    (first.year === second.year &&
+      first.month === second.month &&
+      first.date < second.date)
   );
 };
 
diff --git a/packages/navigation/index.js b/packages/navigation/index.js
index 4a6ccad4..73c61cea 100644
--- a/packages/navigation/index.js
+++ b/packages/navigation/index.js
@@ -9,7 +9,9 @@ import {
   Text,
   StyleSheet,
   Touchable,
+  Dimensions,
   type StylePropType,
+  type DimensionType,
 } from '@kiwicom/mobile-shared';
 import type { TranslationType } from '@kiwicom/mobile-localization';
 
@@ -41,7 +43,7 @@ const createNavigationOptions = () => {
   if (Platform.OS === 'android') {
     navigationOptions.headerStyle.paddingTop = StatusBar.currentHeight;
     navigationOptions.headerStyle.height =
-      StatusBar.currentHeight + Device.getToolbarHeight();
+      StatusBar.currentHeight + Device.TOOLBAR_HEIGHT;
   }
   return navigationOptions;
 };
@@ -93,7 +95,10 @@ export const StackNavigator = (
     [string]: {|
       +screen: mixed,
       +navigationOptions?: {|
-        +headerTitle: React.Element<typeof HeaderTitle> | null,
+        +headerTitle:
+          | React.Element<typeof HeaderTitle>
+          | null
+          | React.Element<typeof Dimensions.Consumer>,
         +headerStyle?: StylePropType,
         +mode?: 'modal',
       |},
@@ -120,8 +125,8 @@ export const StackNavigatorOptions = {
   },
 };
 
-export const createTransparentHeaderStyle = () => {
-  if (Platform.OS === 'ios' || Device.isWideLayout()) {
+export const createTransparentHeaderStyle = (dim: DimensionType) => {
+  if (Platform.OS === 'ios' || Device.isWideLayout(dim)) {
     // normal header on iOS and wide Android
     return {};
   }
diff --git a/packages/navigation/src/MenuItem.js b/packages/navigation/src/MenuItem.js
index e99ec814..abda3528 100644
--- a/packages/navigation/src/MenuItem.js
+++ b/packages/navigation/src/MenuItem.js
@@ -75,7 +75,7 @@ function MenuItem(props: Props) {
         {props.actionIcon ? (
           <View style={styleSheet.rightArrow}>{props.actionIcon}</View>
         ) : (
-          <AdaptableLayout.Consumer
+          <AdaptableLayout
             renderOnNarrow={
               <View style={styleSheet.rightArrow}>
                 <Icon name="chevron-right" size={26} color={Color.brand} />
@@ -97,7 +97,7 @@ export default function AdaptableMenuItem(props: Props) {
   // it's not possible to activate it because new scene should always open
   // on mobile devices.
   return (
-    <AdaptableLayout.Consumer
+    <AdaptableLayout
       renderOnNarrow={<MenuItem {...props} isActive={false} />}
       renderOnWide={<MenuItem {...props} />}
     />
diff --git a/packages/playground/src/Playground.js b/packages/playground/src/Playground.js
index a509a039..22568cae 100644
--- a/packages/playground/src/Playground.js
+++ b/packages/playground/src/Playground.js
@@ -5,8 +5,9 @@ import { View, ScrollView } from 'react-native';
 import {
   StyleSheet,
   Text,
-  AdaptableLayout,
+  Dimensions,
   Color,
+  type DimensionType,
 } from '@kiwicom/mobile-shared';
 import { Translation } from '@kiwicom/mobile-localization';
 import { type NavigationType } from '@kiwicom/mobile-navigation';
@@ -18,6 +19,7 @@ type Props = {|
   +name: string,
   +navigation: NavigationType,
   +onGoBack: () => void,
+  +dimensions: DimensionType,
 |};
 
 const PlaygroundSection = props => (
@@ -56,7 +58,7 @@ export default class Playground extends React.Component<Props> {
       );
     }
     return (
-      <AdaptableLayout.Provider>
+      <Dimensions.Provider dimensions={this.props.dimensions}>
         <ScrollView>
           {PlaygroundRenderer.components[this.props.name].components.map(
             (component, index) => {
@@ -68,7 +70,7 @@ export default class Playground extends React.Component<Props> {
             },
           )}
         </ScrollView>
-      </AdaptableLayout.Provider>
+      </Dimensions.Provider>
     );
   };
 }
diff --git a/packages/shared/index.js b/packages/shared/index.js
index 2a675831..0e4ff169 100644
--- a/packages/shared/index.js
+++ b/packages/shared/index.js
@@ -49,6 +49,7 @@ export { default as Text } from './src/Text';
  * These components helps us to build the layout but they are more or less
  * useless without UI components.
  */
+export { default as Dimensions } from './src/view/Dimensions';
 export { default as AdaptableLayout } from './src/view/AdaptableLayout';
 export { default as CenteredView } from './src/view/CenteredView';
 export { default as DismissKeyboardView } from './src/view/DismissKeyboardView';
@@ -111,3 +112,5 @@ export type {
   StyleObjectType,
   PlatformStyleObjectType,
 } from './types/Styles';
+
+export type { DimensionType } from './types/Objects';
diff --git a/packages/shared/src/Device.js b/packages/shared/src/Device.js
index 6944f022..abe86098 100644
--- a/packages/shared/src/Device.js
+++ b/packages/shared/src/Device.js
@@ -1,75 +1,16 @@
 // @flow strict
 
-import { Dimensions, Platform } from 'react-native'; // eslint-disable-line no-restricted-imports
+import { Platform } from 'react-native';
+import { type DimensionType } from '@kiwicom/mobile-shared';
 
-type DimensionsType = {|
-  width: number,
-  height: number,
-|};
-
-let dimensions: DimensionsType = {
-  width: 0,
-  height: 0,
-};
-
-function renewDimensions(): DimensionsType {
-  if (dimensions.width === 0 && dimensions.height === 0) {
-    return Dimensions.get('screen');
-  }
-  return dimensions;
-}
-
-const dimensionChangeListeners = [];
-
-/**
- * Note: getDimensions should only be used in componentDidMount. Dimensions are
- * changing during the application lifecycle so you have to use
- * `AdaptableLayout` component or subscribe to these changes.
- */
 export default {
-  /**
-   * This is just a workaround for RN issue with wrong screen dimensions while
-   * multitasking in iOS devices. It should be called ONLY from the root
-   * element.
-   *
-   * @see: https://github.com/facebook/react-native/issues/16152
-   */
-  emitDimensionChanges(height: number, width: number) {
-    // store new dimensions to the memory so they persist
-    dimensions = {
-      height,
-      width,
-    };
-
-    // invoke listeners with new dimensions
-    dimensionChangeListeners.forEach(event => {
-      event({ height, width });
-    });
-  },
-
-  /**
-   * Dimensions may change (landscape <-> portrait, multitasking). Subscribe to
-   * this event if you want to be notified about these changes.
-   */
-  subscribeToDimensionChanges(
-    handler: (dimensions: DimensionsType) => void,
-  ): () => void {
-    dimensionChangeListeners.push(handler);
-
-    return function unsubscribe() {
-      const index = dimensionChangeListeners.indexOf(handler);
-      dimensionChangeListeners.splice(index, 1);
-    };
-  },
-
   /**
    * .---.
    * |   |
    * |   |
    * `---`
    */
-  isPortrait() {
-    const { height, width } = renewDimensions();
+  isPortrait({ height, width }: DimensionType) {
     return height >= width;
   },
 
@@ -78,52 +19,33 @@ export default {
    * |      |
    * `------`
    */
-  isLandscape() {
-    const { height, width } = renewDimensions();
+  isLandscape({ height, width }: DimensionType) {
     return width >= height;
   },
 
   /**
    * Wide layout is usually for tablets. However, this may be false even
    * on tablet for example during iOS multitasking mode.
-   *
-   * WARNING: this won't update with device change. Use subscriber instead.
    */
-  isWideLayout() {
-    const { width } = renewDimensions();
-    return width > this.getWideDeviceThreshold();
+  isWideLayout({ width }: DimensionType) {
+    return width > this.DEVICE_THRESHOLD;
   },
 
-  /**
-   * WARNING: this won't update with device change. Use subscriber instead.
-   */
-  isNarrowLayout() {
-    return !this.isWideLayout();
+  isNarrowLayout(dimensions: DimensionType) {
+    return !this.isWideLayout(dimensions);
   },
 
   /**
    * Wide device is every device above this value.
    */
-  getWideDeviceThreshold() {
-    return 668; // according to the graphic design
-  },
+  DEVICE_THRESHOLD: 668, // according to the graphic design
 
   /**
    * Height of the application toobar. Please note that toolbar is the
    * place where top navigation resides. Don't confuse it with statusbar.
    */
-  getToolbarHeight() {
-    return Platform.select({
-      android: 56,
-      ios: 64,
-    });
-  },
-
-  /**
-   * WARNING: this won't update with device change.
-   * Should only be used in componentDidMount.
-   */
-  getDimensions() {
-    return renewDimensions();
-  },
+  TOOLBAR_HEIGHT: Platform.select({
+    android: 56,
+    ios: 64,
+  }),
 };
diff --git a/packages/shared/src/popup/Popup.js b/packages/shared/src/popup/Popup.js
index 4cc3b537..6ed495cb 100644
--- a/packages/shared/src/popup/Popup.js
+++ b/packages/shared/src/popup/Popup.js
@@ -35,7 +35,7 @@ export default class Popup extends React.Component<Props> {
         onBackdropPress={this.onClose}
         onRequestClose={this.onClose}
       >
-        <AdaptableLayout.Consumer
+        <AdaptableLayout
           renderOnWide={
             <View
               style={[styles.contentContainer, styles.wideContentContainer]}
diff --git a/packages/shared/src/view/AdaptableLayout.js b/packages/shared/src/view/AdaptableLayout.js
index f999a70f..b67724ef 100644
--- a/packages/shared/src/view/AdaptableLayout.js
+++ b/packages/shared/src/view/AdaptableLayout.js
@@ -1,9 +1,34 @@
 // @flow
 
-import Provider from './AdaptableLayoutProvider';
-import Consumer from './AdaptableLayoutConsumer';
+import * as React from 'react';
 
-export default {
-  Provider,
-  Consumer,
-};
+import Dimensions from './Dimensions';
+import Device from '../Device';
+
+type Props = {|
+  +renderOnWide?: React.Node,
+  +renderOnNarrow?: React.Node,
+|};
+
+// may return nothing:
+// 1. renderOnWide set but we have narrow layout
+// 2. renderOnNarrow set but we have wide layout
+export default class AdaptableLayout extends React.Component<Props> {
+  render = () => {
+    return (
+      <Dimensions.Consumer>
+        {dimensions => {
+          if (!dimensions) {
+            return;
+          }
+          const wideLayout = Device.isWideLayout(dimensions);
+          if (wideLayout === true && this.props.renderOnWide) {
+            return this.props.renderOnWide;
+          } else if (wideLayout === false && this.props.renderOnNarrow) {
+            return this.props.renderOnNarrow;
+          }
+        }}
+      </Dimensions.Consumer>
+    );
+  };
+}
diff --git a/packages/shared/src/view/AdaptableLayoutConsumer.js b/packages/shared/src/view/AdaptableLayoutConsumer.js
deleted file mode 100644
index 5482fcad..00000000
--- a/packages/shared/src/view/AdaptableLayoutConsumer.js
+++ /dev/null
@@ -1,71 +0,0 @@
-// @flow
-
-import * as React from 'react';
-
-import Context from './AdaptableLayoutContext';
-import Device from '../Device';
-
-type Props = {|
-  +renderOnWide?: React.Node,
-  +renderOnNarrow?: React.Node,
-|};
-
-type State = {|
-  wideLayout: boolean,
-|};
-
-export default class AdaptableLayoutConsumer extends React.Component<
-  Props,
-  State,
-> {
-  unsubscribeDimensionListener: Function = () => {};
-
-  state = {
-    wideLayout: Device.isWideLayout(),
-  };
-
-  componentDidMount = () => {
-    this.unsubscribeDimensionListener = Device.subscribeToDimensionChanges(
-      ({ width }) => {
-        this.setState({
-          wideLayout: width > Device.getWideDeviceThreshold(),
-        });
-      },
-    );
-  };
-
-  componentWillUnmount = () => {
-    this.unsubscribeDimensionListener();
-  };
-
-  render = () => {
-    // may return nothing:
-    // 1. renderOnWide set but we have narrow layout
-    // 2. renderOnNarrow set but we have wide layout
-    let children = null;
-
-    if (this.state.wideLayout === true && this.props.renderOnWide) {
-      children = this.props.renderOnWide;
-    } else if (this.state.wideLayout === false && this.props.renderOnNarrow) {
-      children = this.props.renderOnNarrow;
-    }
-
-    return (
-      <Context.Consumer>
-        {contextValue => {
-          if (contextValue.isSet === false) {
-            if (process.env.NODE_ENV !== 'test') {
-              throw new Error(
-                'AdaptableLayout has been called in wrong context. You have to ' +
-                  'use "AdaptableLayout.Provider" on the root level first ' +
-                  "otherwise it won't work.",
-              );
-            }
-          }
-
-          return children;
-        }}
-      </Context.Consumer>
-    );
-  };
-}
diff --git a/packages/shared/src/view/AdaptableLayoutContext.js b/packages/shared/src/view/AdaptableLayoutContext.js
deleted file mode 100644
index 2509a6b5..00000000
--- a/packages/shared/src/view/AdaptableLayoutContext.js
+++ /dev/null
@@ -1,7 +0,0 @@
-// @flow
-
-import * as React from 'react';
-
-export default React.createContext({
-  isSet: false,
-});
diff --git a/packages/shared/src/view/AdaptableLayoutProvider.js b/packages/shared/src/view/AdaptableLayoutProvider.js
deleted file mode 100644
index d9eb00b2..00000000
--- a/packages/shared/src/view/AdaptableLayoutProvider.js
+++ /dev/null
@@ -1,48 +0,0 @@
-// @flow
-
-import * as React from 'react';
-import { View } from 'react-native';
-
-import Context from './AdaptableLayoutContext';
-import Device from '../Device';
-import StyleSheet from '../PlatformStyleSheet';
-import type { OnLayout } from '../../index';
-
-type Props = {|
-  +children: React.Node,
-|};
-
-type State = {|
-  isSet: boolean,
-|};
-
-export default class AdaptableLayoutProvider extends React.Component<
-  Props,
-  State,
-> {
-  state = {
-    isSet: true,
-  };
-
-  emitDimensionChanges = (event: OnLayout) => {
-    const { width, height } = event.nativeEvent.layout;
-    Device.emitDimensionChanges(height, width);
-  };
-
-  render = () => (
-    <View
-      style={styleSheet.providerWrapper}
-      onLayout={this.emitDimensionChanges}
-    >
-      <Context.Provider value={this.state}>
-        {this.props.children}
-      </Context.Provider>
-    </View>
-  );
-}
-
-const styleSheet = StyleSheet.create({
-  providerWrapper: {
-    flex: 1,
-  },
-});
diff --git a/packages/shared/src/view/Dimensions.js b/packages/shared/src/view/Dimensions.js
new file mode 100644
index 00000000..57b91450
--- /dev/null
+++ b/packages/shared/src/view/Dimensions.js
@@ -0,0 +1,9 @@
+// @flow
+
+import Provider from './DimensionsProvider';
+import Consumer from './DimensionsConsumer';
+
+export default {
+  Provider,
+  Consumer,
+};
diff --git a/packages/shared/src/view/DimensionsConsumer.js b/packages/shared/src/view/DimensionsConsumer.js
new file mode 100644
index 00000000..d0e9786c
--- /dev/null
+++ b/packages/shared/src/view/DimensionsConsumer.js
@@ -0,0 +1,32 @@
+// @flow
+
+import * as React from 'react';
+import { type DimensionType } from '@kiwicom/mobile-shared';
+
+import Context from './DimensionsContext';
+
+type Props = {|
+  +children: DimensionType => React.Node,
+|};
+
+export default class DimensionsConsumer extends React.Component<Props> {
+  render = () => {
+    return (
+      <Context.Consumer>
+        {({ dimensions }) => {
+          if (dimensions == null) {
+            if (process.env.NODE_ENV !== 'test') {
+              throw new Error(
+                'DimensionsConsumer has been called in wrong context. You have to ' +
+                  'use "DimensionsProvider" on the root level first ' +
+                  "otherwise it won't work.",
+              );
+            }
+            return null;
+          }
+          return this.props.children(dimensions);
+        }}
+      </Context.Consumer>
+    );
+  };
+}
diff --git a/packages/shared/src/view/DimensionsContext.js b/packages/shared/src/view/DimensionsContext.js
new file mode 100644
index 00000000..cc675736
--- /dev/null
+++ b/packages/shared/src/view/DimensionsContext.js
@@ -0,0 +1,15 @@
+// @flow
+
+import * as React from 'React';
+
+import type { DimensionType } from '../../index';
+
+type ContextType = {|
+  +dimensions: ?DimensionType,
+|};
+
+export default React.createContext(
+  ({
+    dimensions: null,
+  }: ContextType),
+);
diff --git a/packages/shared/src/view/DimensionsProvider.js b/packages/shared/src/view/DimensionsProvider.js
new file mode 100644
index 00000000..0283b6df
--- /dev/null
+++ b/packages/shared/src/view/DimensionsProvider.js
@@ -0,0 +1,65 @@
+// @flow
+
+import * as React from 'react';
+import { View } from 'react-native';
+
+import Context from './DimensionsContext';
+import StyleSheet from '../PlatformStyleSheet';
+import type { OnLayout, DimensionType } from '../../index';
+
+type Props = {|
+  +children: React.Node,
+  +dimensions: ?DimensionType,
+|};
+
+type State = {|
+  dimensions: ?DimensionType,
+|};
+
+class DimensionsProvider extends React.Component<Props, State> {
+  state = {
+    dimensions: this.props.dimensions,
+  };
+
+  onLayout = (event: OnLayout) => {
+    const { width, height } = event.nativeEvent.layout;
+    this.setState({
+      dimensions: { width, height },
+    });
+  };
+
+  render = () => (
+    <View style={styleSheet.providerWrapper} onLayout={this.onLayout}>
+      <Context.Provider value={this.state}>
+        {this.state.dimensions !== null && this.props.children}
+      </Context.Provider>
+    </View>
+  );
+}
+
+/**
+ * When multiple DimensionsProviders are embedded within each other, use the outermost one.
+ *
+ * This is typically the case when we are running Javascript playground and each standalone
+ * component has one DimensionsProvider (to be used by native apps) and one used by the Javascript
+ * side.
+ */
+export default function DimensionsProviderWrapper(props: Props) {
+  return (
+    <Context.Consumer>
+      {ctx => {
+        return ctx.dimensions !== null ? (
+          props.children
+        ) : (
+          <DimensionsProvider {...props} />
+        );
+      }}
+    </Context.Consumer>
+  );
+}
+
+const styleSheet = StyleSheet.create({
+  providerWrapper: {
+    flex: 1,
+  },
+});
diff --git a/packages/shared/src/view/LayoutDoubleColumn.js b/packages/shared/src/view/LayoutDoubleColumn.js
index f8b213e4..d04a3d2f 100644
--- a/packages/shared/src/view/LayoutDoubleColumn.js
+++ b/packages/shared/src/view/LayoutDoubleColumn.js
@@ -51,7 +51,7 @@ type Props = {|
  */
 export default function LayoutDoubleColumn(props: Props) {
   return (
-    <AdaptableLayout.Consumer
+    <AdaptableLayout
       renderOnNarrow={<NarrowLayout menuComponent={props.menuComponent} />}
       renderOnWide={
         <WideLayout
diff --git a/packages/shared/src/view/LayoutSingleColumn.js b/packages/shared/src/view/LayoutSingleColumn.js
index 22b59e82..b730f2b1 100644
--- a/packages/shared/src/view/LayoutSingleColumn.js
+++ b/packages/shared/src/view/LayoutSingleColumn.js
@@ -19,7 +19,7 @@ type Props = {|
 export default function LayoutSingleColumn(props: Props) {
   const innerStyle = {
     width: '100%',
-    maxWidth: Device.getWideDeviceThreshold(),
+    maxWidth: Device.DEVICE_THRESHOLD,
   };
 
   return (
diff --git a/packages/shared/types/Objects.js b/packages/shared/types/Objects.js
new file mode 100644
index 00000000..cd9e4aac
--- /dev/null
+++ b/packages/shared/types/Objects.js
@@ -0,0 +1,6 @@
+// @flow
+
+export type DimensionType = {
+  width: number,
+  height: number,
+};


Test patch:
diff --git a/app/hotels/src/allHotels/__tests__/AllHotels.test.js b/app/hotels/src/allHotels/__tests__/AllHotels.test.js
index 501b100e..cd3c4b86 100644
--- a/app/hotels/src/allHotels/__tests__/AllHotels.test.js
+++ b/app/hotels/src/allHotels/__tests__/AllHotels.test.js
@@ -19,7 +19,7 @@ describe('AllHotels', () => {
     expect(setSearch).toHaveBeenCalled();
   });
 
-  it('does not call onSearchChange if checkin is before today', () => {
+  it('calls onSearchChange if checkin is before today', () => {
     const setSearch = jest.fn();
     // $FlowExpectedError: Only passing props needed for test to run
     const Component = new AllHotels({
@@ -30,10 +30,10 @@ describe('AllHotels', () => {
     });
 
     Component.componentDidMount();
-    expect(setSearch).not.toHaveBeenCalled();
+    expect(setSearch).toHaveBeenCalled();
   });
 
-  it('does not call onSearchChange if dates are missing', () => {
+  it('calls onSearchChange if dates are missing', () => {
     const setSearch = jest.fn();
     // $FlowExpectedError: Only passing props needed for test to run
     const Component = new AllHotels({
@@ -42,6 +42,6 @@ describe('AllHotels', () => {
     });
 
     Component.componentDidMount();
-    expect(setSearch).not.toHaveBeenCalled();
+    expect(setSearch).toHaveBeenCalled();
   });
 });
diff --git a/app/hotels/src/search/__tests__/SearchQueryHelpers.test.js b/app/hotels/src/search/__tests__/SearchQueryHelpers.test.js
index 0b58000f..0a29625d 100644
--- a/app/hotels/src/search/__tests__/SearchQueryHelpers.test.js
+++ b/app/hotels/src/search/__tests__/SearchQueryHelpers.test.js
@@ -6,6 +6,7 @@ import {
   getSearchQueryParams,
   hasCoordinates,
   updateCheckinDateIfBeforeToday,
+  isDateBeforeToday,
 } from '../SearchQueryHelpers';
 import { sanitizeDate } from '../../GraphQLSanitizers';
 
@@ -127,4 +128,19 @@ describe('SearchQueryHelpers', () => {
       expect(onSearchChange).toHaveBeenCalled();
     });
   });
+
+  describe('isDateBeforeToday', () => {
+    it('should return true if date is before today', () => {
+      expect(isDateBeforeToday(DateUtils().addDays(-1))).toBe(true);
+      expect(isDateBeforeToday(DateUtils().addDays(-7))).toBe(true);
+    });
+
+    it('should return false if date is today', () => {
+      expect(isDateBeforeToday(new Date())).toBe(false);
+    });
+
+    it('should return false if date is after today', () => {
+      expect(isDateBeforeToday(DateUtils().addDays(1))).toBe(false);
+    });
+  });
 });
diff --git a/packages/localization/src/__tests__/DateUtils.test.js b/packages/localization/src/__tests__/DateUtils.test.js
index 111cdeba..87cbcfd4 100644
--- a/packages/localization/src/__tests__/DateUtils.test.js
+++ b/packages/localization/src/__tests__/DateUtils.test.js
@@ -53,4 +53,62 @@ describe('isSameDay', () => {
       DateUtils.isSameDay(new Date('2018-12-24'), new Date('2018-12-23')),
     ).toBe(false);
   });
+
+  describe('isAfterDate', () => {
+    it('returns right answer', () => {
+      expect(
+        DateUtils.isAfterDate(new Date('2018-12-24'), new Date('2018-12-23')),
+      ).toBe(true);
+      expect(
+        DateUtils.isAfterDate(new Date('2018-12-23'), new Date('2018-12-24')),
+      ).toBe(false);
+
+      expect(
+        DateUtils.isAfterDate(new Date('2019-12-24'), new Date('2018-12-24')),
+      ).toBe(true);
+      expect(
+        DateUtils.isAfterDate(new Date('2018-12-24'), new Date('2019-12-24')),
+      ).toBe(false);
+
+      expect(
+        DateUtils.isAfterDate(new Date('2018-12-24'), new Date('2018-11-24')),
+      ).toBe(true);
+      expect(
+        DateUtils.isAfterDate(new Date('2018-11-24'), new Date('2019-12-24')),
+      ).toBe(false);
+
+      expect(
+        DateUtils.isAfterDate(new Date('2018-12-24'), new Date('2018-12-24')),
+      ).toBe(false);
+    });
+  });
+
+  describe('isBeforeDate', () => {
+    it('returns right answer', () => {
+      expect(
+        DateUtils.isBeforeDate(new Date('2018-12-24'), new Date('2018-12-23')),
+      ).toBe(false);
+      expect(
+        DateUtils.isBeforeDate(new Date('2018-12-23'), new Date('2018-12-24')),
+      ).toBe(true);
+
+      expect(
+        DateUtils.isBeforeDate(new Date('2019-12-24'), new Date('2018-12-24')),
+      ).toBe(false);
+      expect(
+        DateUtils.isBeforeDate(new Date('2018-12-24'), new Date('2019-12-24')),
+      ).toBe(true);
+
+      expect(
+        DateUtils.isBeforeDate(new Date('2018-12-24'), new Date('2018-11-24')),
+      ).toBe(false);
+      expect(
+        DateUtils.isBeforeDate(new Date('2018-11-24'), new Date('2019-12-24')),
+      ).toBe(true);
+
+      expect(
+        DateUtils.isBeforeDate(new Date('2018-12-24'), new Date('2018-12-24')),
+      ).toBe(false);
+    });
+  });
 });
diff --git a/packages/shared/src/__tests__/Device.test.js b/packages/shared/src/__tests__/Device.test.js
index f1866a5e..06044167 100644
--- a/packages/shared/src/__tests__/Device.test.js
+++ b/packages/shared/src/__tests__/Device.test.js
@@ -2,53 +2,22 @@
 
 import Device from '../Device';
 
-it('is able to emit dimension changes', () => {
-  const sink = [];
-  Device.subscribeToDimensionChanges(newDimensions => {
-    sink.push(newDimensions);
-  });
+it('orientation is portrait', () => {
+  const device = Device.isPortrait({ height: 500, width: 200 });
+  expect(device).toBeTruthy();
+});
 
-  expect(sink).toEqual([]);
-  Device.emitDimensionChanges(1, 2);
-  expect(sink).toEqual([
-    {
-      height: 1,
-      width: 2,
-    },
-  ]);
-  Device.emitDimensionChanges(3, 4);
-  expect(sink).toEqual([
-    {
-      height: 1,
-      width: 2,
-    },
-    {
-      height: 3,
-      width: 4,
-    },
-  ]);
+it('orientation is landscape', () => {
+  const device = Device.isLandscape({ height: 200, width: 500 });
+  expect(device).toBeTruthy();
 });
 
-it('is possible to unsubscribe', () => {
-  const sink = [];
-  const unsubscribe = Device.subscribeToDimensionChanges(newDimensions => {
-    sink.push(newDimensions);
-  });
+it('layout is wide', () => {
+  const device = Device.isWideLayout({ height: 500, width: 700 });
+  expect(device).toBeTruthy();
+});
 
-  expect(sink).toEqual([]);
-  Device.emitDimensionChanges(1, 2);
-  expect(sink).toEqual([
-    {
-      height: 1,
-      width: 2,
-    },
-  ]);
-  unsubscribe();
-  Device.emitDimensionChanges(3, 4);
-  expect(sink).toEqual([
-    {
-      height: 1,
-      width: 2,
-    },
-  ]);
+it('layout is narrow', () => {
+  const device = Device.isNarrowLayout({ height: 200, width: 500 });
+  expect(device).toBeTruthy();
 });
diff --git a/packages/shared/src/popup/__tests__/ButtonPopup.test.js b/packages/shared/src/popup/__tests__/ButtonPopup.test.js
index 0f5e63d6..57273404 100644
--- a/packages/shared/src/popup/__tests__/ButtonPopup.test.js
+++ b/packages/shared/src/popup/__tests__/ButtonPopup.test.js
@@ -2,21 +2,23 @@
 
 import * as React from 'react';
 import renderer from 'react-test-renderer';
-import { Touchable } from '@kiwicom/mobile-shared';
+import { Touchable, Dimensions } from '@kiwicom/mobile-shared';
 import { Translation } from '@kiwicom/mobile-localization';
 
 import ButtonPopup from '../ButtonPopup';
 
 const renderPopup = (onSave, onClose) =>
   renderer.create(
-    <ButtonPopup
-      buttonTitle={<Translation passThrough="Save" />}
-      isVisible={true}
-      onSave={onSave}
-      onClose={onClose}
-    >
-      <Translation passThrough="Child" />
-    </ButtonPopup>,
+    <Dimensions.Provider dimensions={{ width: 500, height: 700 }}>
+      <ButtonPopup
+        buttonTitle={<Translation passThrough="Save" />}
+        isVisible={true}
+        onSave={onSave}
+        onClose={onClose}
+      >
+        <Translation passThrough="Child" />
+      </ButtonPopup>
+    </Dimensions.Provider>,
   );
 
 describe('ButtonPopup', () => {
diff --git a/packages/shared/src/view/__tests__/AdaptableLayout.narrow.test.js b/packages/shared/src/view/__tests__/AdaptableLayout.narrow.test.js
index 8ca0a4f2..3a20e539 100644
--- a/packages/shared/src/view/__tests__/AdaptableLayout.narrow.test.js
+++ b/packages/shared/src/view/__tests__/AdaptableLayout.narrow.test.js
@@ -3,11 +3,11 @@
 import * as React from 'react';
 import Renderer from 'react-test-renderer';
 
+import Dimensions from '../Dimensions';
 import AdaptableLayout from '../AdaptableLayout';
 
 jest.mock('../../Device', () => ({
   isWideLayout: () => false,
-  subscribeToDimensionChanges: () => () => {},
 }));
 
 const RendersCorrectly = () => 'I am going to render without any problems...';
@@ -19,12 +19,12 @@ const ThrowsError = () => {
 it('renders narrow components', () => {
   expect(
     Renderer.create(
-      <AdaptableLayout.Provider>
-        <AdaptableLayout.Consumer
+      <Dimensions.Provider dimensions={{ width: 200, height: 500 }}>
+        <AdaptableLayout
           renderOnWide={<ThrowsError />}
           renderOnNarrow={<RendersCorrectly />}
         />
-      </AdaptableLayout.Provider>,
+      </Dimensions.Provider>,
     ),
   ).toMatchSnapshot();
 });
@@ -32,9 +32,9 @@ it('renders narrow components', () => {
 it('renders empty element if there is no narrow layout', () => {
   expect(
     Renderer.create(
-      <AdaptableLayout.Provider>
-        <AdaptableLayout.Consumer renderOnWide={<ThrowsError />} />
-      </AdaptableLayout.Provider>,
+      <Dimensions.Provider dimensions={{ width: 700, height: 500 }}>
+        <AdaptableLayout renderOnWide={<ThrowsError />} />
+      </Dimensions.Provider>,
     ),
   ).toMatchSnapshot();
 });
diff --git a/packages/shared/src/view/__tests__/AdaptableLayout.test.js b/packages/shared/src/view/__tests__/AdaptableLayout.test.js
index 19f4bd23..3ae5883c 100644
--- a/packages/shared/src/view/__tests__/AdaptableLayout.test.js
+++ b/packages/shared/src/view/__tests__/AdaptableLayout.test.js
@@ -4,13 +4,14 @@ import * as React from 'react';
 import Renderer from 'react-test-renderer';
 
 import AdaptableLayout from '../AdaptableLayout';
+import Dimensions from '../Dimensions';
 
 it('renders empty element without props', () => {
   expect(
     Renderer.create(
-      <AdaptableLayout.Provider>
-        <AdaptableLayout.Consumer />
-      </AdaptableLayout.Provider>,
+      <Dimensions.Provider dimensions={null}>
+        <AdaptableLayout />
+      </Dimensions.Provider>,
     ),
   ).toMatchSnapshot();
 });
@@ -24,7 +25,7 @@ it('throw error when called without provider', () => {
   jest.spyOn(console, 'error').mockImplementation(() => {});
 
   expect(() =>
-    Renderer.create(<AdaptableLayout.Consumer />),
+    Renderer.create(<AdaptableLayout />),
   ).toThrowErrorMatchingSnapshot();
 
   process.env.NODE_ENV = NODE_ENV;
diff --git a/packages/shared/src/view/__tests__/AdaptableLayout.wide.test.js b/packages/shared/src/view/__tests__/AdaptableLayout.wide.test.js
index 6f3a4f3d..607ee206 100644
--- a/packages/shared/src/view/__tests__/AdaptableLayout.wide.test.js
+++ b/packages/shared/src/view/__tests__/AdaptableLayout.wide.test.js
@@ -3,11 +3,11 @@
 import * as React from 'react';
 import Renderer from 'react-test-renderer';
 
+import Dimensions from '../Dimensions';
 import AdaptableLayout from '../AdaptableLayout';
 
 jest.mock('../../Device', () => ({
   isWideLayout: () => true,
-  subscribeToDimensionChanges: () => () => {},
 }));
 
 const RendersCorrectly = () => 'I am going to render without any problems...';
@@ -19,12 +19,12 @@ const ThrowsError = () => {
 it('renders wide components', () => {
   expect(
     Renderer.create(
-      <AdaptableLayout.Provider>
-        <AdaptableLayout.Consumer
+      <Dimensions.Provider dimensions={{ width: 700, height: 500 }}>
+        <AdaptableLayout
           renderOnWide={<RendersCorrectly />}
           renderOnNarrow={<ThrowsError />}
         />
-      </AdaptableLayout.Provider>,
+      </Dimensions.Provider>,
     ),
   ).toMatchSnapshot();
 });
@@ -32,9 +32,9 @@ it('renders wide components', () => {
 it('renders empty element if there is no wide layout', () => {
   expect(
     Renderer.create(
-      <AdaptableLayout.Provider>
-        <AdaptableLayout.Consumer renderOnNarrow={<ThrowsError />} />
-      </AdaptableLayout.Provider>,
+      <Dimensions.Provider dimensions={{ width: 200, height: 500 }}>
+        <AdaptableLayout renderOnNarrow={<ThrowsError />} />
+      </Dimensions.Provider>,
     ),
   ).toMatchSnapshot();
 });
diff --git a/packages/shared/src/view/__tests__/__snapshots__/AdaptableLayout.test.js.snap b/packages/shared/src/view/__tests__/__snapshots__/AdaptableLayout.test.js.snap
index 82c03ff4..cf63eb57 100644
--- a/packages/shared/src/view/__tests__/__snapshots__/AdaptableLayout.test.js.snap
+++ b/packages/shared/src/view/__tests__/__snapshots__/AdaptableLayout.test.js.snap
@@ -11,4 +11,4 @@ exports[`renders empty element without props 1`] = `
 />
 `;
 
-exports[`throw error when called without provider 1`] = `"AdaptableLayout has been called in wrong context. You have to use \\"AdaptableLayout.Provider\\" on the root level first otherwise it won't work."`;
+exports[`throw error when called without provider 1`] = `"DimensionsConsumer has been called in wrong context. You have to use \\"DimensionsProvider\\" on the root level first otherwise it won't work."`;