base product
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"name": "twopane-navigation-workspaces",
|
||||
"private": true,
|
||||
"version": "0.0.1",
|
||||
"workspaces":{
|
||||
"packages": [
|
||||
"packages/*"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
import * as React from 'react';
|
||||
import { IRestaurantDetails } from './interfaces';
|
||||
import { Text } from 'react-native';
|
||||
|
||||
export interface ILocationInformationProps {
|
||||
details: IRestaurantDetails;
|
||||
}
|
||||
|
||||
const LocationInformation = (props: ILocationInformationProps) =>{
|
||||
const { details } = props;
|
||||
return (
|
||||
<Text>{details.name}</Text>
|
||||
);
|
||||
}
|
||||
|
||||
export default LocationInformation;
|
|
@ -1,24 +0,0 @@
|
|||
import react, { Fragment } from 'react';
|
||||
import { IRestaurantDetails } from './interfaces';
|
||||
import { FlatList, Text } from 'react-native';
|
||||
|
||||
export interface ILocationsList {
|
||||
listItems: IRestaurantDetails[];
|
||||
}
|
||||
|
||||
const LocationsList = (props: ILocationsList) => {
|
||||
const {listItems} = props;
|
||||
return (
|
||||
<FlatList
|
||||
data={listItems}
|
||||
renderItem={({ item }) => (
|
||||
<Fragment>
|
||||
<Text>{item.name}</Text>
|
||||
</Fragment>
|
||||
)}
|
||||
keyExtractor={item => item.name}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default LocationsList;
|
|
@ -1,8 +0,0 @@
|
|||
import { StyleSheet } from 'react-native';
|
||||
|
||||
export const paneHeaderContainerStyles = StyleSheet.create({
|
||||
HeaderDefault: {
|
||||
paddingHorizontal: 25,
|
||||
backgroundColor: '#212121'
|
||||
}
|
||||
});
|
|
@ -1,65 +0,0 @@
|
|||
import { IPaneComponent, paneType } from "../../utilities/interfaces";
|
||||
import { StyleSheet, View} from "react-native";
|
||||
import ScreenHeaderContainer from "../paneHeaderContainer/PaneHeaderContainer";
|
||||
import onePane from "../../onePane/onePaneStore/onePane.methods";
|
||||
import React, { Fragment } from "react";
|
||||
import twoPane from "../../twoPane/twoPaneStore/twoPane.methods";
|
||||
|
||||
interface IScreenRendererProps {
|
||||
prependKey: string;
|
||||
screenComponent: IPaneComponent[];
|
||||
}
|
||||
|
||||
const ScreenRenderer = (props: IScreenRendererProps) => {
|
||||
const { prependKey, screenComponent } = props;
|
||||
|
||||
const isGoBackONE = screenComponent.filter(x => x.screen === paneType.ONE).length > 1;
|
||||
const isGoBackTWO = screenComponent.filter(x => x.screen === paneType.TWO).length > 1;
|
||||
return (
|
||||
<Fragment>
|
||||
{
|
||||
screenComponent.map((val: IPaneComponent) =>
|
||||
<View key={prependKey + val.key}
|
||||
style={[ScreenRendererStyles.container, (val.screen === paneType.ONE ? ScreenRendererStyles.isONE : ScreenRendererStyles.isTWO)]}>
|
||||
<View style={ScreenRendererStyles.header}>
|
||||
<ScreenHeaderContainer
|
||||
isGoBack={(val.screen === paneType.ONE ? isGoBackONE : isGoBackTWO)}
|
||||
screenHeader={val.header}
|
||||
goBack={() => (val.screen === paneType.ONE ? onePane.GoBack() : twoPane.GoBack())}
|
||||
/>
|
||||
</View>
|
||||
<View
|
||||
style={ScreenRendererStyles.body}>
|
||||
{val.paneElement}
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
</Fragment >
|
||||
)
|
||||
}
|
||||
|
||||
const ScreenRendererStyles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
...StyleSheet.absoluteFillObject,
|
||||
height: 720,
|
||||
width: 540,
|
||||
backgroundColor: 'black',
|
||||
},
|
||||
isONE: {
|
||||
left: 0,
|
||||
},
|
||||
isTWO: {
|
||||
left: 570,
|
||||
},
|
||||
|
||||
header: {
|
||||
height: '10%'
|
||||
},
|
||||
body: {
|
||||
height: '85%'
|
||||
}
|
||||
});
|
||||
|
||||
export default ScreenRenderer;
|
|
@ -1,10 +0,0 @@
|
|||
import { IUtilityStoreAction } from "./utilityStore.interfaces";
|
||||
import { IS_TWOPANE } from "./utilityStore.types";
|
||||
|
||||
export const isTwoPaneAction = (isTwoPane: boolean):
|
||||
IUtilityStoreAction => ({
|
||||
type: IS_TWOPANE,
|
||||
payload: {
|
||||
isTwoPane: isTwoPane
|
||||
}
|
||||
});
|
|
@ -1,10 +0,0 @@
|
|||
export interface IUtilityStoreState {
|
||||
isTwoPane: boolean;
|
||||
}
|
||||
|
||||
export interface IUtilityStoreAction {
|
||||
type: string;
|
||||
payload: {
|
||||
isTwoPane: boolean;
|
||||
};
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
export const IS_TWOPANE: string = 'IS_TWOPANE';
|
|
@ -13,7 +13,7 @@
|
|||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:label="@string/app_name"
|
||||
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
|
||||
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|smallestScreenSize|screenLayout"
|
||||
android:launchMode="singleTask"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<intent-filter>
|
До Ширина: | Высота: | Размер: 3.0 KiB После Ширина: | Высота: | Размер: 3.0 KiB |
До Ширина: | Высота: | Размер: 4.9 KiB После Ширина: | Высота: | Размер: 4.9 KiB |
До Ширина: | Высота: | Размер: 2.0 KiB После Ширина: | Высота: | Размер: 2.0 KiB |
До Ширина: | Высота: | Размер: 2.8 KiB После Ширина: | Высота: | Размер: 2.8 KiB |
До Ширина: | Высота: | Размер: 4.5 KiB После Ширина: | Высота: | Размер: 4.5 KiB |
До Ширина: | Высота: | Размер: 6.9 KiB После Ширина: | Высота: | Размер: 6.9 KiB |
До Ширина: | Высота: | Размер: 6.3 KiB После Ширина: | Высота: | Размер: 6.3 KiB |
До Ширина: | Высота: | Размер: 10 KiB После Ширина: | Высота: | Размер: 10 KiB |
До Ширина: | Высота: | Размер: 9.0 KiB После Ширина: | Высота: | Размер: 9.0 KiB |
До Ширина: | Высота: | Размер: 15 KiB После Ширина: | Высота: | Размер: 15 KiB |
|
@ -6,6 +6,8 @@ buildscript {
|
|||
minSdkVersion = 16
|
||||
compileSdkVersion = 29
|
||||
targetSdkVersion = 29
|
||||
kotlinVersion = "1.3.50"
|
||||
|
||||
}
|
||||
repositories {
|
||||
google()
|
||||
|
@ -13,6 +15,7 @@ buildscript {
|
|||
}
|
||||
dependencies {
|
||||
classpath("com.android.tools.build:gradle:3.5.3")
|
||||
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}")
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
}
|
|
@ -8,17 +8,7 @@ const path = require('path');
|
|||
|
||||
module.exports = {
|
||||
// WatchFolders is only needed due to the yarn workspace layout of node_modules, we need to watch the symlinked locations separately
|
||||
watchFolders: [
|
||||
// Include hoisted modules
|
||||
path.resolve(__dirname, '../../node_modules'),
|
||||
],
|
||||
resolver: {
|
||||
extraNodeModules: {
|
||||
// Redirect react-native-dualscreeninfo to avoid symlink (metro doesn't like symlinks)
|
||||
'react-native-dualscreeninfo': path.resolve(__dirname, '../../dualscreeninfo'),
|
||||
'twopane-navigation': path.resolve(__dirname, '../twopane-navigation'),
|
||||
}
|
||||
},
|
||||
|
||||
transformer: {
|
||||
getTransformOptions: async () => ({
|
||||
transform: {
|
|
@ -4,15 +4,18 @@
|
|||
"private": true,
|
||||
"scripts": {
|
||||
"android": "react-native run-android",
|
||||
"android:clean": "cd android && gradlew clean",
|
||||
"ios": "react-native run-ios",
|
||||
"start": "react-native start --reset-cache",
|
||||
"start": "react-native start",
|
||||
"start:clean": "react-native start --reset-cache",
|
||||
"test": "jest",
|
||||
"lint": "eslint . --ext .js,.jsx,.ts,.tsx"
|
||||
},
|
||||
"dependencies": {
|
||||
"react": "16.13.1",
|
||||
"react-native": "0.63.2",
|
||||
"twopane-navigation": "1.0.0"
|
||||
"react-native-dualscreeninfo": "^0.1.3",
|
||||
"twopane-navigation": "^1.0.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.8.4",
|
||||
|
@ -41,8 +44,5 @@
|
|||
"json",
|
||||
"node"
|
||||
]
|
||||
},
|
||||
"workspaces": {
|
||||
"nohoist": ["react-native", "react-native/**"]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,9 +8,10 @@
|
|||
* @format
|
||||
*/
|
||||
|
||||
import react from 'react';
|
||||
import React from 'react';
|
||||
|
||||
import { TwoPaneApp, ITwoPaneAppProps } from 'twopane-navigation';
|
||||
|
||||
import {TwoPaneApp, ITwoPaneAppProps} from "twopane-navigation"
|
||||
import { IRestaurantDetails } from './interfaces';
|
||||
import LocationsList from './locationsList';
|
||||
import LocationInformation from './locationInformation';
|
||||
|
@ -19,59 +20,69 @@ const RestaurantDetails: IRestaurantDetails[] =
|
|||
[
|
||||
{
|
||||
name: 'ContosoPizza Seattle Center',
|
||||
address: '2928 1st Ave',
|
||||
phoneNumber: '206-555-4437',
|
||||
storeHours: '10am-11pm daily',
|
||||
deliveryHours: '10am-11pm daily'
|
||||
},
|
||||
{
|
||||
name: 'ContosoPizza Westlake',
|
||||
address: '714 Taylor Ave N',
|
||||
phoneNumber: '206-555-4437',
|
||||
storeHours: '10am-11pm daily',
|
||||
deliveryHours: '10am-11pm daily'
|
||||
},
|
||||
{
|
||||
name: 'ContosoPizza Pioneer Square',
|
||||
address: '112 1st Ave S #100',
|
||||
phoneNumber: '206-555-4437',
|
||||
storeHours: '10am-11pm daily',
|
||||
deliveryHours: '10am-11pm daily'
|
||||
},
|
||||
{
|
||||
name: 'ContosoPizza Capitol Hill',
|
||||
address: '1427 Broadway',
|
||||
phoneNumber: '206-555-4437',
|
||||
storeHours: '10am-11pm daily',
|
||||
deliveryHours: '10am-11pm daily'
|
||||
},
|
||||
{
|
||||
name: 'ContosoPizza Capitol Hill East',
|
||||
address: 'Mount 2928 1st Ave',
|
||||
phoneNumber: '206-555-4437',
|
||||
storeHours: '10am-11pm daily',
|
||||
deliveryHours: '10am-11pm daily'
|
||||
},
|
||||
{
|
||||
name: 'ContosoPizza Bellevue',
|
||||
address: '2928 1st Ave',
|
||||
phoneNumber: '206-555-4437',
|
||||
storeHours: '10am-11pm daily',
|
||||
deliveryHours: '10am-11pm daily'
|
||||
},
|
||||
{
|
||||
name: 'ContosoPizza Redmond',
|
||||
address: '2928 1st Ave',
|
||||
phoneNumber: '206-555-4437',
|
||||
storeHours: '10am-11pm daily',
|
||||
deliveryHours: '10am-11pm daily'
|
||||
},
|
||||
{
|
||||
name: 'ContosoPizza Bothell',
|
||||
address: '2928 1st Ave',
|
||||
phoneNumber: '206-555-4437',
|
||||
storeHours: '10am-11pm daily',
|
||||
deliveryHours: '10am-11pm daily'
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
const App = () => {
|
||||
return (
|
||||
<TwoPaneApp
|
||||
onePaneDefault={TwoPaneAppDefaultComponents.onePaneDefault}
|
||||
twoPaneDefault={TwoPaneAppDefaultComponents.twoPaneDefault}
|
||||
config ={TwoPaneAppDefaultComponents.config}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
@ -80,14 +91,35 @@ const TwoPaneAppDefaultComponents: ITwoPaneAppProps = {
|
|||
|
||||
onePaneDefault:{
|
||||
key: 'restaurantLocations',
|
||||
paneElement: <LocationsList listItems={RestaurantDetails}/>
|
||||
paneElement: <LocationsList listItems={RestaurantDetails}/>,
|
||||
header: {
|
||||
title: 'ContosoPizza'
|
||||
}
|
||||
|
||||
},
|
||||
twoPaneDefault: {
|
||||
key: 'restaurantDetails',
|
||||
paneElement: <LocationInformation details={RestaurantDetails[0]} />
|
||||
}
|
||||
paneElement: <LocationInformation details={RestaurantDetails[0]} />,
|
||||
},
|
||||
config: {
|
||||
onePane: {
|
||||
paneHeader: {
|
||||
backgroundColor: '#D26441'
|
||||
},
|
||||
paneBody: {
|
||||
backgroundColor: '#f2f2f2'
|
||||
}
|
||||
},
|
||||
twoPane: {
|
||||
paneHeader: {
|
||||
backgroundColor: '#D26441',
|
||||
|
||||
},
|
||||
paneBody: {
|
||||
backgroundColor: '#f2f2f2'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export default App;
|
После Ширина: | Высота: | Размер: 459 B |
После Ширина: | Высота: | Размер: 909 KiB |
|
@ -2,9 +2,8 @@
|
|||
export interface IRestaurantDetails {
|
||||
|
||||
name: string;
|
||||
address: string;
|
||||
phoneNumber: string;
|
||||
storeHours: string;
|
||||
deliveryHours: string;
|
||||
//TODO: SPECIALS
|
||||
//TODO: create new interface for MasterView
|
||||
}
|
|
@ -0,0 +1,142 @@
|
|||
import React from 'react';
|
||||
import { IRestaurantDetails } from './interfaces';
|
||||
import { Text, View, Image, StyleSheet, ScrollView, Button } from 'react-native';
|
||||
|
||||
export interface ILocationInformationProps {
|
||||
details: IRestaurantDetails;
|
||||
}
|
||||
|
||||
const LocationInformation = (props: ILocationInformationProps) =>{
|
||||
const { details } = props;
|
||||
return (
|
||||
<ScrollView
|
||||
contentInsetAdjustmentBehavior="automatic"
|
||||
style={locationInformationStyles.scrollView}
|
||||
>
|
||||
<View style={locationInformationStyles.informationContainer}>
|
||||
<Image source={require('./images/pizza.png')} style={locationInformationStyles.pizzaImage}/>
|
||||
<Text style={locationInformationStyles.informationTitle}>{details.name}</Text>
|
||||
<View style={locationInformationStyles.columns}>
|
||||
<View style={locationInformationStyles.rows}>
|
||||
<View style={locationInformationStyles.columnLeftItem}>
|
||||
<Text style={locationInformationStyles.subSectionContainer}>
|
||||
<Text style={locationInformationStyles.subSectionTitle}>Address: </Text>
|
||||
<Text style={locationInformationStyles.subSectionDescription}>
|
||||
{details.address}
|
||||
</Text>
|
||||
</Text>
|
||||
<Text style={locationInformationStyles.subSectionContainer}>
|
||||
<Text style={locationInformationStyles.subSectionTitle}>Phone: </Text>
|
||||
<Text style={locationInformationStyles.subSectionDescription}>
|
||||
{details.phoneNumber}
|
||||
</Text>
|
||||
</Text>
|
||||
<Text style={locationInformationStyles.subSectionContainer}>
|
||||
<Text style={locationInformationStyles.subSectionTitle}>Store Hours: </Text>
|
||||
<Text style={locationInformationStyles.subSectionDescription}>
|
||||
{details.storeHours}
|
||||
</Text>
|
||||
</Text>
|
||||
<Text style={locationInformationStyles.subSectionContainer}>
|
||||
<Text style={locationInformationStyles.subSectionTitle}>Delivery Hours: </Text>
|
||||
<Text style={locationInformationStyles.subSectionDescription}>
|
||||
{details.deliveryHours}
|
||||
</Text>
|
||||
</Text>
|
||||
</View>
|
||||
<View style={locationInformationStyles.columnRightItem}>
|
||||
<View>
|
||||
<View>
|
||||
<Button title='Order now' color='#D26441' onPress={()=> {console.log('works');}}/>
|
||||
</View>
|
||||
<View style={locationInformationStyles.getDirectionsView}>
|
||||
<Image source={require('./images/directions.png')} style={locationInformationStyles.directionsImage}/>
|
||||
<Text style={locationInformationStyles.getDirections}>Get directions</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</ScrollView>
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
const locationInformationStyles = StyleSheet.create({
|
||||
scrollView: {
|
||||
width: '100%',
|
||||
height: '100%'
|
||||
},
|
||||
informationContainer: {
|
||||
paddingHorizontal: 48,
|
||||
marginTop: 32,
|
||||
marginBottom: 24
|
||||
},
|
||||
pizzaImage:{
|
||||
width: '100%',
|
||||
height: undefined,
|
||||
aspectRatio: 2.066666666666667,
|
||||
resizeMode: 'contain',
|
||||
},
|
||||
informationTitle: {
|
||||
marginTop: 24,
|
||||
fontSize: 28,
|
||||
fontWeight: '600',
|
||||
color: 'black',
|
||||
},
|
||||
columns: {
|
||||
marginTop: 24,
|
||||
flex: 1,
|
||||
flexDirection: 'column',
|
||||
},
|
||||
rows: {
|
||||
width: '50%',
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
},
|
||||
columnLeftItem: {
|
||||
flexDirection: 'column',
|
||||
paddingRight: 30,
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
alignItems: 'stretch'
|
||||
},
|
||||
columnRightItem: {
|
||||
flexDirection: 'column',
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
alignItems: 'stretch'
|
||||
},
|
||||
subSectionContainer: {
|
||||
marginBottom: 8,
|
||||
},
|
||||
subSectionTitle: {
|
||||
fontSize: 13,
|
||||
fontWeight: '600',
|
||||
color: 'black',
|
||||
},
|
||||
subSectionDescription: {
|
||||
fontSize: 12,
|
||||
fontWeight: '200',
|
||||
color: 'black',
|
||||
},
|
||||
getDirectionsView: {
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
height: 60,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center'
|
||||
},
|
||||
getDirections: {
|
||||
fontSize: 12,
|
||||
color: "#4794CC"
|
||||
},
|
||||
directionsImage: {
|
||||
width: 24,
|
||||
height: 24,
|
||||
marginRight: 10
|
||||
}
|
||||
})
|
||||
|
||||
export default LocationInformation;
|
|
@ -0,0 +1,56 @@
|
|||
import React, { Fragment } from 'react';
|
||||
import { IRestaurantDetails } from './interfaces';
|
||||
import { FlatList, Text, View, StyleSheet, TouchableHighlight, TouchableOpacity } from 'react-native';
|
||||
import { autoPane } from 'twopane-navigation';
|
||||
import LocationInformation from './locationInformation';
|
||||
|
||||
export interface ILocationsList {
|
||||
listItems: IRestaurantDetails[];
|
||||
}
|
||||
|
||||
const LocationsList = (props: ILocationsList) => {
|
||||
const {listItems} = props;
|
||||
return (
|
||||
<FlatList
|
||||
data={listItems}
|
||||
renderItem={({ item }) => (
|
||||
<TouchableOpacity onPress={ () =>
|
||||
autoPane.AddOrMoveToFront(`${item.name}`,
|
||||
<LocationInformation details={item}/>
|
||||
)} >
|
||||
<View style={locationListStyles.listItemContainer} >
|
||||
<Text style={locationListStyles.listItemTitle}>{item.name}</Text>
|
||||
<Text style={locationListStyles.listItemAddress}>{item.address}</Text>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
|
||||
)}
|
||||
keyExtractor={item => item.name}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const locationListStyles = StyleSheet.create({
|
||||
listItemContainer: {
|
||||
borderBottomWidth: 1,
|
||||
borderColor: '#E1E1E1',
|
||||
marginLeft: 20,
|
||||
marginRight: 20,
|
||||
paddingTop: 8,
|
||||
paddingBottom: 16,
|
||||
},
|
||||
listItemTitle: {
|
||||
fontSize: 18,
|
||||
fontWeight: '600',
|
||||
color: 'black',
|
||||
},
|
||||
listItemAddress: {
|
||||
marginTop: 2,
|
||||
fontSize: 12,
|
||||
fontWeight: '400',
|
||||
color: '#777777',
|
||||
},
|
||||
|
||||
})
|
||||
|
||||
export default LocationsList;
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "twopane-navigation",
|
||||
"Title": "twopane-navigation",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.7",
|
||||
"description": "React Native package for dual screen devices navigation support (Surface Duo)",
|
||||
"react-native": "src/index.ts",
|
||||
"types": "lib/typescript/index.d.ts",
|
||||
|
@ -72,7 +72,9 @@
|
|||
],
|
||||
"jest": {
|
||||
"preset": "react-native",
|
||||
"modulePathIgnorePatterns": ["<rootDir>/lib/"],
|
||||
"modulePathIgnorePatterns": [
|
||||
"<rootDir>/lib/"
|
||||
],
|
||||
"moduleFileExtensions": [
|
||||
"ts",
|
||||
"tsx",
|
|
@ -1,27 +1,28 @@
|
|||
import React from 'react';
|
||||
import { View } from 'react-native';
|
||||
import { View, StyleSheet, StyleProp, ViewStyle } from 'react-native';
|
||||
import Icon from 'react-native-vector-icons/MaterialIcons';
|
||||
import ScreenHeader from '../paneHeader/PaneHeader';
|
||||
import { paneHeaderContainerStyles } from './PaneHeaderContainer.style';
|
||||
import { IHeader } from '../../shared/screenStore/headerStore/header.interface';
|
||||
import { Style } from '../../utilities/interfaces';
|
||||
|
||||
interface IPaneHeaderContainerProps {
|
||||
isGoBack: boolean;
|
||||
screenHeader: IHeader | undefined;
|
||||
goBack: () => any;
|
||||
configDefaultHeader: Style;
|
||||
}
|
||||
|
||||
const PaneHeaderContainer = (props: IPaneHeaderContainerProps) => {
|
||||
|
||||
const { isGoBack, screenHeader, goBack } = props;
|
||||
|
||||
const { isGoBack, screenHeader, goBack, configDefaultHeader } = props;
|
||||
|
||||
return (
|
||||
<View style={{ flex: 1 }}>
|
||||
{isGoBack ? (
|
||||
<ScreenHeader
|
||||
style={{
|
||||
...paneHeaderContainerStyles.HeaderDefault //look into header
|
||||
}}
|
||||
style={[
|
||||
paneHeaderContainerStyles.HeaderDefault, configDefaultHeader!
|
||||
]}
|
||||
title={screenHeader?.title}
|
||||
leftIcon={
|
||||
screenHeader?.leftIcon ? (
|
||||
|
@ -39,9 +40,9 @@ const PaneHeaderContainer = (props: IPaneHeaderContainerProps) => {
|
|||
) : (
|
||||
//</View>
|
||||
<ScreenHeader
|
||||
style={{
|
||||
...paneHeaderContainerStyles.HeaderDefault
|
||||
}}
|
||||
style={[
|
||||
paneHeaderContainerStyles.HeaderDefault, configDefaultHeader!
|
||||
]}
|
||||
title={screenHeader?.title}
|
||||
leftIcon={
|
||||
screenHeader?.leftIcon &&
|
||||
|
@ -57,4 +58,11 @@ const PaneHeaderContainer = (props: IPaneHeaderContainerProps) => {
|
|||
)
|
||||
}
|
||||
|
||||
const paneHeaderContainerStyles = StyleSheet.create({
|
||||
HeaderDefault: {
|
||||
paddingHorizontal: 25,
|
||||
backgroundColor: '#212121',
|
||||
}
|
||||
});
|
||||
|
||||
export default PaneHeaderContainer;
|
|
@ -0,0 +1,79 @@
|
|||
import { IPaneComponent, paneType, IConfig } from "../../utilities/interfaces";
|
||||
import { StyleSheet, View, StyleProp, ViewStyle} from "react-native";
|
||||
import PaneHeaderContainer from "../paneHeaderContainer/PaneHeaderContainer";
|
||||
import onePane from "../../onePane/onePaneStore/onePane.methods";
|
||||
import React, { Fragment } from "react";
|
||||
import twoPane from "../../twoPane/twoPaneStore/twoPane.methods";
|
||||
import { WindowRect } from "react-native-dualscreeninfo";
|
||||
import { getUtilityStore } from "../../shared/utilityStore/utilityStore.selectors";
|
||||
|
||||
interface IPaneRendererProps {
|
||||
prependKey: string;
|
||||
paneComponent: IPaneComponent[];
|
||||
paneRects: WindowRect[];
|
||||
}
|
||||
|
||||
const PaneRenderer = (props: IPaneRendererProps) => {
|
||||
const defaultConfig = getUtilityStore().config;
|
||||
const { prependKey, paneComponent, paneRects } = props;
|
||||
|
||||
const isGoBackOne = paneComponent.filter(x => x.pane === paneType.ONE).length > 1;
|
||||
const isGoBackTwo = paneComponent.filter(x => x.pane === paneType.TWO).length > 1;
|
||||
return (
|
||||
<Fragment>
|
||||
{
|
||||
paneComponent.map((val: IPaneComponent) =>
|
||||
<View key={prependKey + val.key}
|
||||
style={[generalStyles.container, ((val.pane === paneType.TWO && paneRects.length > 1) ?
|
||||
Object.assign({},twoPaneStyles(paneRects[1]).twoPane, defaultConfig?.twoPane?.paneBody!) :
|
||||
Object.assign({},onePaneStyles(paneRects[0]).onePane, defaultConfig?.onePane?.paneBody!))]}>
|
||||
<View style={generalStyles.header}>
|
||||
<PaneHeaderContainer
|
||||
isGoBack={(val.pane === paneType.ONE ? isGoBackOne : isGoBackTwo)}
|
||||
screenHeader={val.header}
|
||||
goBack={() => (val.pane === paneType.ONE ? onePane.GoBack() : twoPane.GoBack())}
|
||||
configDefaultHeader={val.pane === paneType.ONE ? defaultConfig.onePane?.paneHeader! : defaultConfig.twoPane?.paneHeader!}
|
||||
/>
|
||||
</View>
|
||||
<View
|
||||
style={generalStyles.body}>
|
||||
{val.paneElement}
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
</Fragment >
|
||||
)
|
||||
}
|
||||
|
||||
const generalStyles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
...StyleSheet.absoluteFillObject,
|
||||
color: 'black'
|
||||
},
|
||||
header: {
|
||||
height: '10%'
|
||||
},
|
||||
body: {
|
||||
height: '85%'
|
||||
}
|
||||
})
|
||||
|
||||
const onePaneStyles = (paneRects : WindowRect) => StyleSheet.create({
|
||||
onePane: {
|
||||
left: paneRects.x,
|
||||
height: paneRects.height,
|
||||
width: paneRects.width
|
||||
}
|
||||
});
|
||||
|
||||
const twoPaneStyles = (paneRects : WindowRect) => StyleSheet.create({
|
||||
twoPane: {
|
||||
left: paneRects.x,
|
||||
height: paneRects.height,
|
||||
width: paneRects.width,
|
||||
},
|
||||
});
|
||||
|
||||
export default PaneRenderer;
|
|
@ -6,6 +6,7 @@ import { ITwoPaneAppProps } from '../../utilities/interfaces';
|
|||
import TwoPaneHub from '../twoPaneHub/TwoPaneHub';
|
||||
import onePane from '../../onePane/onePaneStore/onePane.methods';
|
||||
import twoPane from '../../twoPane/twoPaneStore/twoPane.methods';
|
||||
import utilityStore from '../../shared/utilityStore/utilityStore.methods';
|
||||
|
||||
|
||||
const TwoPaneApp = (props: ITwoPaneAppProps) => {
|
||||
|
@ -19,6 +20,11 @@ const TwoPaneApp = (props: ITwoPaneAppProps) => {
|
|||
if (!hasOnePaneDefault && !hasTwoPaneDefault) {
|
||||
onePane.Add(props.onePaneDefault.key, props.onePaneDefault.paneElement, props?.onePaneDefault?.header!);
|
||||
twoPane.Add(props.twoPaneDefault.key, props.twoPaneDefault.paneElement, props?.twoPaneDefault?.header!);
|
||||
|
||||
if(props.config !== undefined)
|
||||
{
|
||||
utilityStore.pushConfig(props.config);
|
||||
}
|
||||
}
|
||||
}, []);
|
||||
|
|
@ -7,9 +7,10 @@ describe('DualApp Tests', () => {
|
|||
it('should render singleScreen', () => {
|
||||
// Arrange
|
||||
jest.useFakeTimers();
|
||||
|
||||
const _onePaneDefault: IPaneComponent = {
|
||||
key: 'singleDefault',
|
||||
twoPaneElement: <Fragment />,
|
||||
paneElement: <Fragment />,
|
||||
header: {
|
||||
title: 'singleScreenDefaultTitle'
|
||||
}
|
||||
|
@ -17,7 +18,7 @@ describe('DualApp Tests', () => {
|
|||
|
||||
const _twoPaneDefault: IPaneComponent = {
|
||||
key: 'dualDefault',
|
||||
twoPaneElement: <Fragment />,
|
||||
paneElement: <Fragment />,
|
||||
header: {
|
||||
title: 'onePaneDefaultTitle'
|
||||
}
|
||||
|
@ -30,7 +31,7 @@ describe('DualApp Tests', () => {
|
|||
twoPaneDefault={_twoPaneDefault}
|
||||
/>
|
||||
);
|
||||
|
||||
// TODO MOCK TEST
|
||||
// Assert
|
||||
expect(toJSON(container)).toMatchSnapshot();
|
||||
});
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useMemo, useEffect } from 'react';
|
||||
import React, { useMemo, useEffect, useState } from 'react';
|
||||
import { View } from 'react-native';
|
||||
import { IPaneComponent } from '../../utilities/interfaces';
|
||||
|
||||
|
@ -7,20 +7,20 @@ import { getHeaderSelector } from '../../shared/screenStore/headerStore/header.s
|
|||
import { IHeaderState } from '../../shared/screenStore/headerStore/header.interface';
|
||||
import { IPaneElementState } from '../../shared/screenStore/paneElementStore/paneElement.interface';
|
||||
|
||||
import ScreenRenderer from '../paneRenderer/PaneRenderer';
|
||||
import PaneRenderer from '../paneRenderer/PaneRenderer';
|
||||
import { getScreenKeyState } from '../../shared/screenStore/keyStore/key.selector';
|
||||
import { DualScreenInfo, DualScreenInfoPayload } from 'react-native-dualscreeninfo';
|
||||
import { DualScreenInfo, DualScreenInfoPayload, WindowRect } from 'react-native-dualscreeninfo';
|
||||
import utilityStore from '../../shared/utilityStore/utilityStore.methods';
|
||||
import onePane from '../../onePane/onePaneStore/onePane.methods';
|
||||
import twoPane from '../../twoPane/twoPaneStore/twoPane.methods';
|
||||
|
||||
|
||||
const TwoPaneHub = () => {
|
||||
|
||||
const twoPaneElementState: IPaneElementState = getPaneElementSelector();
|
||||
const headerState: IHeaderState = getHeaderSelector();
|
||||
|
||||
const keyState = getScreenKeyState();
|
||||
const [paneRects, setPaneRects] = useState<WindowRect[]>(DualScreenInfo.windowRects);
|
||||
|
||||
useEffect(() => {
|
||||
utilityStore.isTwoPane(DualScreenInfo.isSpanning)
|
||||
|
@ -37,7 +37,7 @@ const TwoPaneHub = () => {
|
|||
key: val.key,
|
||||
paneElement: twoPaneElementState.PaneElements[val.key],
|
||||
header: headerState.headers[val.key],
|
||||
screen: val.screen
|
||||
pane: val.screen
|
||||
}
|
||||
})
|
||||
}, [keyState, twoPaneElementState, headerState])
|
||||
|
@ -45,17 +45,39 @@ const TwoPaneHub = () => {
|
|||
const _handleSpanningChanged = (update: DualScreenInfoPayload) => {
|
||||
utilityStore.isTwoPane(update.isSpanning)
|
||||
if (update.isSpanning) {
|
||||
if(paneRects.length < 2)
|
||||
{
|
||||
setPaneRects(DualScreenInfo.windowRects)
|
||||
}
|
||||
onePane.mergeToOppositeScreen();
|
||||
} else {
|
||||
twoPane.mergeToOppositeScreen();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const fakeWindowRect: WindowRect[] = [
|
||||
{
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 540,
|
||||
height: 720
|
||||
},
|
||||
{
|
||||
x: 573.6,
|
||||
y: 0,
|
||||
width: 540,
|
||||
height: 720
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
return (
|
||||
<View>
|
||||
<ScreenRenderer
|
||||
<PaneRenderer
|
||||
prependKey={''}
|
||||
screenComponent={screenStack} />
|
||||
paneComponent={screenStack}
|
||||
paneRects={fakeWindowRect}/>
|
||||
</View>
|
||||
|
||||
);
|
До Ширина: | Высота: | Размер: 6.9 KiB После Ширина: | Высота: | Размер: 6.9 KiB |
До Ширина: | Высота: | Размер: 18 KiB После Ширина: | Высота: | Размер: 18 KiB |
До Ширина: | Высота: | Размер: 17 KiB После Ширина: | Высота: | Размер: 17 KiB |
До Ширина: | Высота: | Размер: 6.6 KiB После Ширина: | Высота: | Размер: 6.6 KiB |
До Ширина: | Высота: | Размер: 4.9 KiB После Ширина: | Высота: | Размер: 4.9 KiB |
До Ширина: | Высота: | Размер: 44 KiB После Ширина: | Высота: | Размер: 44 KiB |
До Ширина: | Высота: | Размер: 12 KiB После Ширина: | Высота: | Размер: 12 KiB |
До Ширина: | Высота: | Размер: 4.9 KiB После Ширина: | Высота: | Размер: 4.9 KiB |