two pane navigation successful build
|
@ -70,3 +70,7 @@ buck-out/
|
|||
# test files
|
||||
/coverage/
|
||||
|
||||
# generated files
|
||||
lib/
|
||||
|
||||
.read-snapshot.txt
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
![Microsoft Surface](https://assets.onestore.ms/cdnfiles/external/uhf/long/9a49a7e9d8e881327e81b9eb43dabc01de70a9bb/images/microsoft-gray.png)
|
||||
|
||||
# Duex v.1
|
||||
# TwoPane-Navigation v.1
|
||||
|
||||
## Introduction
|
||||
|
||||
Duex library is built for React Native developers working on
|
||||
TwoPane-Navigation library is built for React Native developers working on
|
||||
multi-screen phones and devices.
|
||||
|
||||
This library was built with the idea to work side by side with the react-navigation library or work on its own as a replacement. This allows you, the developer, to have a flexible and premium experience to help pioneer the new wave of multi-screen device applications.
|
||||
|
@ -146,7 +146,7 @@ and will call the appropriate action the current modes stack.
|
|||
|
||||
#### Hooks
|
||||
|
||||
- getDuexElementSelector - get the state of the element Store
|
||||
- getTwoPaneElementSelector - get the state of the element Store
|
||||
|
||||
- getHeaderSelector() - get the state of the header Store
|
||||
|
|
@ -1753,14 +1753,12 @@
|
|||
"@types/prop-types": {
|
||||
"version": "15.7.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz",
|
||||
"integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw=="
|
||||
},
|
||||
"@types/react": {
|
||||
"version": "16.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.0.tgz",
|
||||
"integrity": "sha512-eOct1hyZI9YZf/eqNlYu7jxA9qyTw1EGXruAJhHhBDBpc00W0C1vwlnh+hkOf7UFZkNK+UxnFBpwAZe3d7XJhQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/prop-types": "*",
|
||||
"csstype": "^2.2.0"
|
||||
|
@ -1770,7 +1768,6 @@
|
|||
"version": "0.60.31",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-native/-/react-native-0.60.31.tgz",
|
||||
"integrity": "sha512-Y0Q+nv50KHnLL+jM0UH68gQQv7Wt6v2KuNepiHKwK1DoWGVd1oYun/GJCnvUje+/V8pMQQWW6QuBvHZz1pV7tQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/prop-types": "*",
|
||||
"@types/react": "*"
|
||||
|
@ -1786,6 +1783,15 @@
|
|||
"@types/react-native": "*"
|
||||
}
|
||||
},
|
||||
"@types/react-native-vector-icons": {
|
||||
"version": "6.4.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-native-vector-icons/-/react-native-vector-icons-6.4.5.tgz",
|
||||
"integrity": "sha512-JBpcjWQE4n0GlE0p6HpDDclT+uXpFC453T5k4h+B38q0utlGJhvgNr8899BoJGc1xOktA2cgqFKmFMJd0h7YaA==",
|
||||
"requires": {
|
||||
"@types/react": "*",
|
||||
"@types/react-native": "*"
|
||||
}
|
||||
},
|
||||
"@types/react-navigation": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-navigation/-/react-navigation-3.4.0.tgz",
|
||||
|
@ -2937,8 +2943,7 @@
|
|||
"csstype": {
|
||||
"version": "2.6.13",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.13.tgz",
|
||||
"integrity": "sha512-ul26pfSQTZW8dcOnD2iiJssfXw0gdNVX9IJDH/X3K5DGPfj+fUYe3kB+swUY6BF3oZDxaID3AJt+9/ojSAE05A==",
|
||||
"dev": true
|
||||
"integrity": "sha512-ul26pfSQTZW8dcOnD2iiJssfXw0gdNVX9IJDH/X3K5DGPfj+fUYe3kB+swUY6BF3oZDxaID3AJt+9/ojSAE05A=="
|
||||
},
|
||||
"dashdash": {
|
||||
"version": "1.14.1",
|
|
@ -1,4 +1,73 @@
|
|||
{
|
||||
"private":"true",
|
||||
"workspaces": ["example", "twopane-navigation"]
|
||||
"name": "twopane-navigation",
|
||||
"Title": "twopane-navigation",
|
||||
"version": "1.0.0",
|
||||
"scripts": {
|
||||
"test": "jest",
|
||||
"coverage": "jest --coverage",
|
||||
"prepare": "npm run build",
|
||||
"build": "tsc"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/react-native-vector-icons": "^6.4.5",
|
||||
"lodash": "^4.17.15",
|
||||
"react": "^16.11.0",
|
||||
"react-native": "^0.62.2",
|
||||
"react-native-dualscreeninfo": "^0.1.1",
|
||||
"react-native-reanimated": "^1.9.0",
|
||||
"react-native-vector-icons": "^6.6.0",
|
||||
"react-redux": "^7.2.0",
|
||||
"redux": "^4.0.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/plugin-proposal-decorators": "^7.7.0",
|
||||
"@react-native-community/toolbar-android": "0.1.0-rc.2",
|
||||
"@babel/core": "^7.6.2",
|
||||
"@babel/preset-typescript": "^7.7.2",
|
||||
"@babel/runtime": "^7.6.2",
|
||||
"@react-native-community/eslint-config": "^0.0.5",
|
||||
"@testing-library/jest-native": "^3.1.0",
|
||||
"@testing-library/react-native": "^5.0.3",
|
||||
"@types/jest": "^24.0.18",
|
||||
"@types/lodash": "^4.14.145",
|
||||
"@types/react": "16.9.0",
|
||||
"@types/react-native": "^0.60.17",
|
||||
"@types/react-native-autocomplete-input": "^4.0.1",
|
||||
"@types/react-navigation": "^3.0.8",
|
||||
"@types/react-redux": "^7.1.7",
|
||||
"@types/react-test-renderer": "16.9.0",
|
||||
"babel-jest": "^24.9.0",
|
||||
"jest": "^24.9.0",
|
||||
"metro-react-native-babel-preset": "^0.58.0",
|
||||
"react-native-testing-library": "^1.14.0",
|
||||
"react-test-renderer": "16.9.0",
|
||||
"typescript": "^3.6.3"
|
||||
},
|
||||
"files": [
|
||||
"android",
|
||||
"ios",
|
||||
"src",
|
||||
"lib",
|
||||
"tslint.json",
|
||||
"*.md",
|
||||
"*.podspec",
|
||||
"LICENSE"
|
||||
],
|
||||
"jest": {
|
||||
"preset": "react-native",
|
||||
"moduleFileExtensions": [
|
||||
"ts",
|
||||
"tsx",
|
||||
"js",
|
||||
"jsx",
|
||||
"json",
|
||||
"node"
|
||||
],
|
||||
"transformIgnorePatterns": [
|
||||
"node_modules/(?!react-native|react-navigation)/"
|
||||
],
|
||||
"setupFiles": [
|
||||
"./testenv.js"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
import { ITwoPaneElementAction, ITwoPaneElementObject } from "../twoPaneElement.interface"
|
||||
import React, { ReactElement } from 'react';
|
||||
|
||||
export const twoPaneElementActionBuilder = (type: string, key: string, twoPaneElement: React.ReactElement): ITwoPaneElementAction => {
|
||||
return {
|
||||
type: type,
|
||||
payload: {
|
||||
key: key,
|
||||
twoPaneElement: twoPaneElement
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
export const twoPaneElementObjectBuilder = (key: string, twoPaneElement: ReactElement): ITwoPaneElementObject => {
|
||||
return {
|
||||
[key]: twoPaneElement
|
||||
}
|
||||
}
|
|
@ -1,35 +1,35 @@
|
|||
import { IDuexElementState } from "../duexElement.interface"
|
||||
import { duexElementObjectBuilder } from "./duexElement.methods.helpers"
|
||||
import { ITwoPaneElementState } from "../twoPaneElement.interface"
|
||||
import { twoPaneElementObjectBuilder } from "./twoPaneElement.methods.helpers"
|
||||
import React, { Fragment } from 'react';
|
||||
import { pushElement, replaceDuexElement, removeDuexElementByKey } from "../duexElement.action"
|
||||
import { pushElement, replacetwoPaneElement, removetwoPaneElementByKey } from "../twoPaneElement.action"
|
||||
import { store, resetApp } from "../../../../appStore";
|
||||
import { Text } from "react-native";
|
||||
|
||||
describe('duexElementStore tests', () => {
|
||||
describe('twoPaneElementStore tests', () => {
|
||||
beforeEach(() => {
|
||||
store.dispatch(resetApp())
|
||||
});
|
||||
|
||||
it('PUSH_DUEXELEMENT', () => {
|
||||
it('PUSH_TWOPANE_ELEMENT', () => {
|
||||
// Arrange
|
||||
const expectedState: IDuexElementState =
|
||||
const expectedState: ITwoPaneElementState =
|
||||
{
|
||||
duexElements: duexElementObjectBuilder('first', <Fragment />)
|
||||
twoPaneElements: twoPaneElementObjectBuilder('first', <Fragment />)
|
||||
}
|
||||
|
||||
// Act
|
||||
store.dispatch(pushElement('first', <Fragment />))
|
||||
const data = store.getState().duexElementReducer
|
||||
const data = store.getState().twoPaneElementReducer
|
||||
|
||||
// Assert
|
||||
expect(data).toStrictEqual(expectedState);
|
||||
})
|
||||
|
||||
it('PUSH_DUEXELEMENT Multiple', () => {
|
||||
it('PUSH_TWOPANE_ELEMENT Multiple', () => {
|
||||
// Arrange
|
||||
const expectedState: IDuexElementState =
|
||||
const expectedState: ITwoPaneElementState =
|
||||
{
|
||||
duexElements: {
|
||||
twoPaneElements: {
|
||||
'first': <Fragment />,
|
||||
'second': <Fragment />,
|
||||
'third': <Fragment />,
|
||||
|
@ -40,66 +40,66 @@ describe('duexElementStore tests', () => {
|
|||
store.dispatch(pushElement('first', <Fragment />))
|
||||
store.dispatch(pushElement('second', <Fragment />))
|
||||
store.dispatch(pushElement('third', <Fragment />))
|
||||
const data = store.getState().duexElementReducer
|
||||
const data = store.getState().twoPaneElementReducer
|
||||
|
||||
// Assert
|
||||
expect(data).toStrictEqual(expectedState);
|
||||
})
|
||||
|
||||
it('REPLACE_DUEXELEMENT', () => {
|
||||
it('REPLACE_TWOPANE_ELEMENT', () => {
|
||||
// Arrange
|
||||
const expectedState: IDuexElementState = {
|
||||
duexElements: duexElementObjectBuilder('first', <Text>second</Text>)
|
||||
const expectedState: ITwoPaneElementState = {
|
||||
twoPaneElements: twoPaneElementObjectBuilder('first', <Text>second</Text>)
|
||||
}
|
||||
|
||||
// Act
|
||||
store.dispatch(pushElement('first', <Text>first</Text>))
|
||||
store.dispatch(replaceDuexElement('first', <Text>second</Text>))
|
||||
const data = store.getState().duexElementReducer
|
||||
store.dispatch(replacetwoPaneElement('first', <Text>second</Text>))
|
||||
const data = store.getState().twoPaneElementReducer
|
||||
|
||||
// Assert
|
||||
expect(data).toStrictEqual(expectedState);
|
||||
|
||||
})
|
||||
|
||||
it('REPLACE_DUEXELEMENT Multiple', () => {
|
||||
it('REPLACE_TWOPANE_ELEMENT Multiple', () => {
|
||||
// Arrange
|
||||
const expectedState: IDuexElementState = {
|
||||
duexElements: duexElementObjectBuilder('first', <Text>fifth</Text>)
|
||||
const expectedState: ITwoPaneElementState = {
|
||||
twoPaneElements: twoPaneElementObjectBuilder('first', <Text>fifth</Text>)
|
||||
}
|
||||
|
||||
// Act
|
||||
store.dispatch(pushElement('first', <Text>first</Text>))
|
||||
store.dispatch(replaceDuexElement('first', <Text>second</Text>))
|
||||
store.dispatch(replaceDuexElement('first', <Text>third</Text>))
|
||||
store.dispatch(replaceDuexElement('first', <Text>fourth</Text>))
|
||||
store.dispatch(replaceDuexElement('first', <Text>fifth</Text>))
|
||||
const data = store.getState().duexElementReducer
|
||||
store.dispatch(replacetwoPaneElement('first', <Text>second</Text>))
|
||||
store.dispatch(replacetwoPaneElement('first', <Text>third</Text>))
|
||||
store.dispatch(replacetwoPaneElement('first', <Text>fourth</Text>))
|
||||
store.dispatch(replacetwoPaneElement('first', <Text>fifth</Text>))
|
||||
const data = store.getState().twoPaneElementReducer
|
||||
|
||||
// Assert
|
||||
expect(data).toStrictEqual(expectedState);
|
||||
})
|
||||
|
||||
it('REPLACE_DUEXELEMENT not found', () => {
|
||||
it('REPLACE_TWOPANE_ELEMENT not found', () => {
|
||||
// Arrange
|
||||
const expectedState: IDuexElementState = {
|
||||
duexElements: duexElementObjectBuilder('first', <Text>first</Text>)
|
||||
const expectedState: ITwoPaneElementState = {
|
||||
twoPaneElements: twoPaneElementObjectBuilder('first', <Text>first</Text>)
|
||||
}
|
||||
|
||||
// Act
|
||||
store.dispatch(pushElement('first', <Text>first</Text>))
|
||||
store.dispatch(replaceDuexElement('does not exist', <Text>second</Text>))
|
||||
const data = store.getState().duexElementReducer
|
||||
store.dispatch(replacetwoPaneElement('does not exist', <Text>second</Text>))
|
||||
const data = store.getState().twoPaneElementReducer
|
||||
|
||||
// Assert
|
||||
expect(data).toStrictEqual(expectedState);
|
||||
})
|
||||
|
||||
it('REMOVE_KEY_DUEXELEMENT', () => {
|
||||
it('REMOVE_KEY_TWOPANE_ELEMENT', () => {
|
||||
// Arrange
|
||||
const expectedState: IDuexElementState =
|
||||
const expectedState: ITwoPaneElementState =
|
||||
{
|
||||
duexElements: {
|
||||
twoPaneElements: {
|
||||
'first': <Text>first</Text>,
|
||||
'third': <Text>third</Text>,
|
||||
}
|
||||
|
@ -109,18 +109,18 @@ describe('duexElementStore tests', () => {
|
|||
store.dispatch(pushElement('first', <Text>first</Text>))
|
||||
store.dispatch(pushElement('second', <Text>second</Text>))
|
||||
store.dispatch(pushElement('third', <Text>third</Text>))
|
||||
store.dispatch(removeDuexElementByKey('second'))
|
||||
const data = store.getState().duexElementReducer
|
||||
store.dispatch(removetwoPaneElementByKey('second'))
|
||||
const data = store.getState().twoPaneElementReducer
|
||||
|
||||
// Assert
|
||||
expect(data).toStrictEqual(expectedState);
|
||||
})
|
||||
|
||||
it('REMOVE_KEY_DUEXELEMENT Multiple', () => {
|
||||
it('REMOVE_KEY_TWOPANE_ELEMENT Multiple', () => {
|
||||
// Arrange
|
||||
const expectedState: IDuexElementState =
|
||||
const expectedState: ITwoPaneElementState =
|
||||
{
|
||||
duexElements: {
|
||||
twoPaneElements: {
|
||||
'first': <Text>first</Text>,
|
||||
'third': <Text>third</Text>,
|
||||
'fifth': <Text>fifth</Text>,
|
||||
|
@ -133,19 +133,19 @@ describe('duexElementStore tests', () => {
|
|||
store.dispatch(pushElement('third', <Text>third</Text>,))
|
||||
store.dispatch(pushElement('fourth', <Text>fourth</Text>,))
|
||||
store.dispatch(pushElement('fifth', <Text>fifth</Text>,))
|
||||
store.dispatch(removeDuexElementByKey('second'))
|
||||
store.dispatch(removeDuexElementByKey('fourth'))
|
||||
const data = store.getState().duexElementReducer
|
||||
store.dispatch(removetwoPaneElementByKey('second'))
|
||||
store.dispatch(removetwoPaneElementByKey('fourth'))
|
||||
const data = store.getState().twoPaneElementReducer
|
||||
|
||||
// Assert
|
||||
expect(data).toStrictEqual(expectedState);
|
||||
})
|
||||
|
||||
it('REMOVE_KEY_DUEXELEMENT not found ', () => {
|
||||
it('REMOVE_KEY_TWOPANE_ELEMENT not found ', () => {
|
||||
// Arrange
|
||||
const expectedState: IDuexElementState =
|
||||
const expectedState: ITwoPaneElementState =
|
||||
{
|
||||
duexElements: {
|
||||
twoPaneElements: {
|
||||
'first': <Text>first</Text>,
|
||||
'second': <Text>second</Text>,
|
||||
'third': <Text>third</Text>,
|
||||
|
@ -156,8 +156,8 @@ describe('duexElementStore tests', () => {
|
|||
store.dispatch(pushElement('first', <Text>first</Text>,))
|
||||
store.dispatch(pushElement('second', <Text>second</Text>,))
|
||||
store.dispatch(pushElement('third', <Text>third</Text>,))
|
||||
store.dispatch(removeDuexElementByKey('does not exist'))
|
||||
const data = store.getState().duexElementReducer
|
||||
store.dispatch(removetwoPaneElementByKey('does not exist'))
|
||||
const data = store.getState().twoPaneElementReducer
|
||||
|
||||
// Assert
|
||||
expect(data).toStrictEqual(expectedState);
|
|
@ -0,0 +1,36 @@
|
|||
import { PUSH_TWOPANE_ELEMENT, REMOVE_KEY_TWOPANE_ELEMENT, REPLACE_TWOPANE_ELEMENT } from "./twoPaneElement.types";
|
||||
import { ReactElement } from "react";
|
||||
import { ITwoPaneElementAction } from "./twoPaneElement.interface";
|
||||
import { IKeyOnlyAction } from "../keyStore/key.interface";
|
||||
|
||||
export const pushElement = (
|
||||
key: string,
|
||||
twoPaneElement: ReactElement
|
||||
): ITwoPaneElementAction => ({
|
||||
type: PUSH_TWOPANE_ELEMENT,
|
||||
payload: {
|
||||
key: key,
|
||||
twoPaneElement: twoPaneElement
|
||||
}
|
||||
});
|
||||
|
||||
export const replacetwoPaneElement = (
|
||||
key: string,
|
||||
twoPaneElement: ReactElement
|
||||
): ITwoPaneElementAction => ({
|
||||
type: REPLACE_TWOPANE_ELEMENT,
|
||||
payload: {
|
||||
key: key,
|
||||
twoPaneElement: twoPaneElement
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
export const removetwoPaneElementByKey = (
|
||||
twoPaneElementKey: string
|
||||
): IKeyOnlyAction => ({
|
||||
type: REMOVE_KEY_TWOPANE_ELEMENT,
|
||||
payload: {
|
||||
key: twoPaneElementKey
|
||||
}
|
||||
});
|
|
@ -0,0 +1,17 @@
|
|||
import { ReactElement } from "react";
|
||||
|
||||
export interface ITwoPaneElementObject {
|
||||
[key: string]: ReactElement;
|
||||
}
|
||||
|
||||
export interface ITwoPaneElementState {
|
||||
twoPaneElements: ITwoPaneElementObject;
|
||||
}
|
||||
|
||||
export interface ITwoPaneElementAction {
|
||||
type: string;
|
||||
payload: {
|
||||
key: string
|
||||
twoPaneElement: ReactElement;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
|
||||
import { PUSH_TWOPANE_ELEMENT, REMOVE_KEY_TWOPANE_ELEMENT, REPLACE_TWOPANE_ELEMENT } from './twoPaneElement.types';
|
||||
import { ITwoPaneElementState, ITwoPaneElementAction } from './twoPaneElement.interface';
|
||||
|
||||
const initialState: ITwoPaneElementState = {
|
||||
twoPaneElements: {}
|
||||
};
|
||||
|
||||
const twoPaneElementReducer = (
|
||||
state: ITwoPaneElementState = initialState,
|
||||
action: ITwoPaneElementAction
|
||||
): ITwoPaneElementState => {
|
||||
switch (action.type) {
|
||||
case PUSH_TWOPANE_ELEMENT: {
|
||||
return {
|
||||
...state,
|
||||
twoPaneElements: {
|
||||
...state.twoPaneElements,
|
||||
[action.payload.key as string]: action.payload.twoPaneElement
|
||||
}
|
||||
};
|
||||
}
|
||||
case REPLACE_TWOPANE_ELEMENT: {
|
||||
const hasKey = action.payload.key in state.twoPaneElements;
|
||||
if (!hasKey) {
|
||||
return { ...state };
|
||||
}
|
||||
return {
|
||||
...state,
|
||||
twoPaneElements: {
|
||||
...state.twoPaneElements,
|
||||
[action.payload.key as string]: action.payload.twoPaneElement
|
||||
},
|
||||
};
|
||||
|
||||
}
|
||||
case REMOVE_KEY_TWOPANE_ELEMENT: {
|
||||
// using delete over lodash.omit to reduce dependencies on external libraries
|
||||
const newData = state;
|
||||
delete newData.twoPaneElements[action.payload.key];
|
||||
return { ...newData }
|
||||
}
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
export default twoPaneElementReducer;
|
|
@ -0,0 +1,7 @@
|
|||
import { useSelector } from "react-redux";
|
||||
import { rootReducerType } from "../../../appStore";
|
||||
import { ITwoPaneElementState } from "./twoPaneElement.interface";
|
||||
|
||||
export const getTwoPaneElementSelector = (): ITwoPaneElementState => {
|
||||
return useSelector((state: rootReducerType) => state.twoPaneElementReducer);
|
||||
};
|
|
@ -0,0 +1,7 @@
|
|||
export const PUSH_TWOPANE_ELEMENT: string = 'PUSH_TWOPANE_ELEMENT';
|
||||
|
||||
export const REMOVE_KEY_TWOPANE_ELEMENT: string = 'REMOVE_KEY_TWOPANE_ELEMENT';
|
||||
|
||||
export const REPLACE_TWOPANE_ELEMENT: string = 'REPLACE_TWOPANE_ELEMENT';
|
||||
|
||||
|
|
@ -1,9 +1,8 @@
|
|||
import { combineReducers, createStore } from 'redux';
|
||||
|
||||
import authReducer from './Shared/authStore/auth.reducer';
|
||||
import drawerReducer from './Shared/drawerStore/drawer.reducer';
|
||||
|
||||
import keyReducers from './Shared/screenStore/keyStore/key.reducer';
|
||||
import duexElementReducer from './Shared/screenStore/duexElementStore/duexElement.reducer';
|
||||
import twoPaneElementReducer from './Shared/screenStore/twoPaneElementStore/twoPaneElement.reducer';
|
||||
import headerReducer from './Shared/screenStore/headerStore/header.reducer';
|
||||
import utilityStoreReducer from './Shared/utilityStore/utilityStore.reducer';
|
||||
|
||||
|
@ -13,9 +12,7 @@ require('./utilities/extensionMethods');
|
|||
const rootReducer = combineReducers({
|
||||
KeyReducers: keyReducers,
|
||||
headerReducer,
|
||||
duexElementReducer,
|
||||
authReducer,
|
||||
drawerReducer,
|
||||
twoPaneElementReducer,
|
||||
utilityStoreReducer
|
||||
});
|
||||
|
|
@ -38,8 +38,8 @@ const DualApp = (props: IDualAppProps) => {
|
|||
|
||||
useEffect(() => {
|
||||
if (!hasSingle && !hasDual) {
|
||||
singleScreen.Add(props.singleScreen.key, props.singleScreen.duexElement, props?.singleScreen?.header!);
|
||||
dualScreen.Add(props.dualScreen.key, props.dualScreen.duexElement, props?.dualScreen?.header!);
|
||||
singleScreen.Add(props.singleScreen.key, props.singleScreen.twoPaneElement, props?.singleScreen?.header!);
|
||||
dualScreen.Add(props.dualScreen.key, props.dualScreen.twoPaneElement, props?.dualScreen?.header!);
|
||||
}
|
||||
}, []);
|
||||
|
|
@ -9,7 +9,7 @@ describe('DualApp Tests', () => {
|
|||
jest.useFakeTimers();
|
||||
const singleScreenDefault: IScreenComponent = {
|
||||
key: 'singleDefault',
|
||||
duexElement: <Fragment />,
|
||||
twoPaneElement: <Fragment />,
|
||||
header: {
|
||||
title: 'singleScreenDefaultTitle'
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ describe('DualApp Tests', () => {
|
|||
|
||||
const dualScreenDefault: IScreenComponent = {
|
||||
key: 'dualDefault',
|
||||
duexElement: <Fragment />,
|
||||
twoPaneElement: <Fragment />,
|
||||
header: {
|
||||
title: 'dualScreenDefaultTitle'
|
||||
}
|
|
@ -2,10 +2,10 @@ import React, { useMemo, useEffect } from 'react';
|
|||
import { View } from 'react-native';
|
||||
import { IScreenComponent } from '../../utilities/interfaces';
|
||||
|
||||
import { getDuexElementSelector } from '../../Shared/screenStore/duexElementStore/duexElement.selectors';
|
||||
import { getTwoPaneElementSelector } from '../../Shared/screenStore/twoPaneElementStore/twoPaneElement.selectors';
|
||||
import { getHeaderSelector } from '../../Shared/screenStore/headerStore/header.selector';
|
||||
import { IHeaderState } from '../../Shared/screenStore/headerStore/header.interface';
|
||||
import { IDuexElementState } from '../../Shared/screenStore/duexElementStore/duexElement.interface';
|
||||
import { ITwoPaneElementState } from '../../Shared/screenStore/twoPaneElementStore/twoPaneElement.interface';
|
||||
|
||||
import ScreenRenderer from '../screenRenderer/ScreenRenderer';
|
||||
import { getScreenKeyState } from '../../Shared/screenStore/keyStore/key.selector';
|
||||
|
@ -17,7 +17,7 @@ import dualScreen from '../../dualScreen/dualScreenStore/dualScreen.methods';
|
|||
|
||||
const DualHub = () => {
|
||||
|
||||
const duexElementState: IDuexElementState = getDuexElementSelector();
|
||||
const twoPaneElementState: ITwoPaneElementState = getTwoPaneElementSelector();
|
||||
const headerState: IHeaderState = getHeaderSelector();
|
||||
|
||||
const keyState = getScreenKeyState();
|
||||
|
@ -35,12 +35,12 @@ const DualHub = () => {
|
|||
return keyState.keys.map((val, index) => {
|
||||
return {
|
||||
key: val.key,
|
||||
duexElement: duexElementState.duexElements[val.key],
|
||||
twoPaneElement: twoPaneElementState.twoPaneElements[val.key],
|
||||
header: headerState.headers[val.key],
|
||||
screen: val.screen
|
||||
}
|
||||
})
|
||||
}, [keyState, duexElementState, headerState])
|
||||
}, [keyState, twoPaneElementState, headerState])
|
||||
|
||||
const _handleSpanningChanged = (update: DualScreenInfoPayload) => {
|
||||
utilityStore.isDualScreen(update.isSpanning)
|
|
@ -1,5 +1,4 @@
|
|||
import { IScreenComponent, screenType } from "../../utilities/interfaces";
|
||||
import Animated from "react-native-reanimated";
|
||||
import { StyleSheet, View, StyleProp, ViewStyle } from "react-native";
|
||||
import ScreenHeaderContainer from "../screenHeaderContainer/ScreenHeaderContainer";
|
||||
import singleScreen from "../../singleScreen/singleScreenStore/singleScreen.methods";
|
||||
|
@ -20,7 +19,7 @@ const ScreenRenderer = (props: IScreenRendererProps) => {
|
|||
<Fragment>
|
||||
{
|
||||
screenComponent.map((val: IScreenComponent) =>
|
||||
<Animated.View key={prependKey + val.key}
|
||||
<View key={prependKey + val.key}
|
||||
style={[ScreenRendererStyles.container, (val.screen === screenType.SINGLE ? ScreenRendererStyles.isSingle : ScreenRendererStyles.isDual)]}>
|
||||
<View style={ScreenRendererStyles.header}>
|
||||
<ScreenHeaderContainer
|
||||
|
@ -31,9 +30,9 @@ const ScreenRenderer = (props: IScreenRendererProps) => {
|
|||
</View>
|
||||
<View
|
||||
style={ScreenRendererStyles.body}>
|
||||
{val.duexElement}
|
||||
{val.twoPaneElement}
|
||||
</View>
|
||||
</View>
|
||||
</Animated.View>
|
||||
)
|
||||
}
|
||||
</Fragment >
|
До Ширина: | Высота: | Размер: 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 |
До Ширина: | Высота: | Размер: 29 KiB После Ширина: | Высота: | Размер: 29 KiB |
До Ширина: | Высота: | Размер: 7.2 KiB После Ширина: | Высота: | Размер: 7.2 KiB |
До Ширина: | Высота: | Размер: 7.8 KiB После Ширина: | Высота: | Размер: 7.8 KiB |
До Ширина: | Высота: | Размер: 18 KiB После Ширина: | Высота: | Размер: 18 KiB |
До Ширина: | Высота: | Размер: 20 KiB После Ширина: | Высота: | Размер: 20 KiB |
|
@ -4,10 +4,9 @@ import {
|
|||
} from '../../utilities/interfaces';
|
||||
import { pushKey, popToFront, popScreen, moveToFront, changeScreen } from '../../Shared/screenStore/keyStore/key.actions';
|
||||
import { pushHeader, replaceHeader, removeHeaderByKey } from '../../Shared/screenStore/headerStore/header.actions';
|
||||
import { pushElement, removeDuexElementByKey, replaceDuexElement } from '../../Shared/screenStore/duexElementStore/duexElement.action';
|
||||
import { pushElement, removetwoPaneElementByKey, replacetwoPaneElement } from '../../Shared/screenStore/twoPaneElementStore/twoPaneElement.action';
|
||||
import { IHeader } from '../../Shared/screenStore/headerStore/header.interface';
|
||||
import { IKeyState, IKeyObject } from '../../Shared/screenStore/keyStore/key.interface';
|
||||
import _ from 'lodash';
|
||||
|
||||
/**
|
||||
* Pushes element to the top of the dual screen stack.
|
||||
|
@ -58,7 +57,7 @@ const BackToHome = () => {
|
|||
|
||||
for (let i = 1; i < dualScreenState.length; i++) {
|
||||
store.dispatch(removeHeaderByKey(dualScreenState[i].key));
|
||||
store.dispatch(removeDuexElementByKey(dualScreenState[i].key));
|
||||
store.dispatch(removetwoPaneElementByKey(dualScreenState[i].key));
|
||||
}
|
||||
store.dispatch(popToFront(screenType.DUAL));
|
||||
};
|
||||
|
@ -71,7 +70,7 @@ const GoBack = () => {
|
|||
const dualScreenState: IKeyObject[] = keys.keys.filter(x => x.screen === screenType.DUAL)
|
||||
|
||||
store.dispatch(removeHeaderByKey(dualScreenState.peek().key));
|
||||
store.dispatch(removeDuexElementByKey(dualScreenState.peek().key));
|
||||
store.dispatch(removetwoPaneElementByKey(dualScreenState.peek().key));
|
||||
store.dispatch(popScreen(screenType.DUAL));
|
||||
|
||||
};
|
||||
|
@ -80,7 +79,7 @@ const GoBack = () => {
|
|||
* Replace the current element for this dual screen component
|
||||
*/
|
||||
const ReplaceScreen = (key: string, element: React.ReactElement) => {
|
||||
store.dispatch(replaceDuexElement(`${screenType.DUAL}_${key}`, element))
|
||||
store.dispatch(replacetwoPaneElement(`${screenType.DUAL}_${key}`, element))
|
||||
}
|
||||
|
||||
/**
|
|
@ -2,7 +2,7 @@ import React from 'react'
|
|||
import dualScreen from '../dualScreen.methods';
|
||||
import * as keyActions from '../../../Shared/screenStore/keyStore/key.actions';
|
||||
import * as headerActions from '../../../Shared/screenStore/headerStore/header.actions';
|
||||
import * as duexElementActions from '../../../Shared/screenStore/duexElementStore/duexElement.action';
|
||||
import * as twoPaneElementActions from '../../../Shared/screenStore/twoPaneElementStore/twoPaneElement.action';
|
||||
|
||||
import { Fragment } from 'react';
|
||||
import { IKeyAction, IKeyState } from '../../../Shared/screenStore/keyStore/key.interface';
|
||||
|
@ -10,9 +10,9 @@ import { screenType } from '../../../utilities/interfaces';
|
|||
import { PUSH_KEY } from '../../../Shared/screenStore/keyStore/key.types';
|
||||
import { IHeaderAction } from '../../../Shared/screenStore/headerStore/header.interface';
|
||||
import { PUSH_HEADER } from '../../../Shared/screenStore/headerStore/header.types';
|
||||
import { IDuexElementAction } from '../../../Shared/screenStore/duexElementStore/duexElement.interface';
|
||||
import { PUSH_DUEXELEMENT } from '../../../Shared/screenStore/duexElementStore/duexElement.types';
|
||||
import { duexElementActionBuilder } from '../../../Shared/screenStore/duexElementStore/tests/duexElement.methods.helpers';
|
||||
import { ITwoPaneElementAction } from '../../../Shared/screenStore/twoPaneElementStore/twoPaneElement.interface';
|
||||
import { PUSH_TWOPANE_ELEMENT } from '../../../Shared/screenStore/twoPaneElementStore/twoPaneElement.types';
|
||||
import { twoPaneElementActionBuilder } from '../../../Shared/screenStore/twoPaneElementStore/tests/twoPaneElement.methods.helpers';
|
||||
import { headerActionBuilder } from '../../../Shared/screenStore/headerStore/tests/header.methods.helpers';
|
||||
import { KeyActionBuilder, mockKeyState } from '../../../Shared/screenStore/keyStore/tests/key.methods.helpers';
|
||||
import { store } from '../../../appStore';
|
||||
|
@ -28,11 +28,11 @@ describe('dualScreen methods', () => {
|
|||
|
||||
const expectedHeader: IHeaderAction = headerActionBuilder(PUSH_HEADER, `${screenType.DUAL}_test1`, { title: 'test title' });
|
||||
|
||||
const expectedDuexElement: IDuexElementAction = duexElementActionBuilder(PUSH_DUEXELEMENT, `${screenType.DUAL}_test1`, <Fragment />);
|
||||
const expectedtwoPaneElement: ITwoPaneElementAction = twoPaneElementActionBuilder(PUSH_TWOPANE_ELEMENT, `${screenType.DUAL}_test1`, <Fragment />);
|
||||
|
||||
const pushKeySpy = jest.spyOn(keyActions, 'pushKey');
|
||||
const pushheaderSpy = jest.spyOn(headerActions, 'pushHeader');
|
||||
const pushduexElementsSpy = jest.spyOn(duexElementActions, 'pushElement');
|
||||
const pushtwoPaneElementsSpy = jest.spyOn(twoPaneElementActions, 'pushElement');
|
||||
|
||||
// Act
|
||||
const _dualScreenAdd = dualScreen.Add('test1', <Fragment />, { title: 'test title' }, true);
|
||||
|
@ -40,10 +40,10 @@ describe('dualScreen methods', () => {
|
|||
// Assert
|
||||
expect(pushKeySpy).toBeCalled();
|
||||
expect(pushheaderSpy).toBeCalled();
|
||||
expect(pushduexElementsSpy).toBeCalled();
|
||||
expect(pushtwoPaneElementsSpy).toBeCalled();
|
||||
expect(pushKeySpy.mock.results.find(x => x.value)?.value).toStrictEqual(expectedKey)
|
||||
expect(pushheaderSpy.mock.results.find(x => x.value)?.value).toStrictEqual(expectedHeader)
|
||||
expect(pushduexElementsSpy.mock.results.find(x => x.value)?.value).toStrictEqual(expectedDuexElement)
|
||||
expect(pushtwoPaneElementsSpy.mock.results.find(x => x.value)?.value).toStrictEqual(expectedtwoPaneElement)
|
||||
});
|
||||
|
||||
it('dualScreen Add with header with no merge', () => {
|
||||
|
@ -52,11 +52,11 @@ describe('dualScreen methods', () => {
|
|||
|
||||
const expectedHeader: IHeaderAction = headerActionBuilder(PUSH_HEADER, `${screenType.DUAL}_test2`, { title: 'test title' });
|
||||
|
||||
const expectedDuexElement: IDuexElementAction = duexElementActionBuilder(PUSH_DUEXELEMENT, `${screenType.DUAL}_test2`, <Fragment />);
|
||||
const expectedtwoPaneElement: ITwoPaneElementAction = twoPaneElementActionBuilder(PUSH_TWOPANE_ELEMENT, `${screenType.DUAL}_test2`, <Fragment />);
|
||||
|
||||
const pushKeySpy = jest.spyOn(keyActions, 'pushKey');
|
||||
const pushheaderSpy = jest.spyOn(headerActions, 'pushHeader');
|
||||
const pushduexElementsSpy = jest.spyOn(duexElementActions, 'pushElement');
|
||||
const pushtwoPaneElementsSpy = jest.spyOn(twoPaneElementActions, 'pushElement');
|
||||
|
||||
// Act
|
||||
const _dualScreenAdd = dualScreen.Add('test2', <Fragment />, { title: 'test title' });
|
||||
|
@ -64,22 +64,22 @@ describe('dualScreen methods', () => {
|
|||
// Assert
|
||||
expect(pushKeySpy).toBeCalled();
|
||||
expect(pushheaderSpy).toBeCalled();
|
||||
expect(pushduexElementsSpy).toBeCalled();
|
||||
expect(pushtwoPaneElementsSpy).toBeCalled();
|
||||
expect(pushKeySpy.mock.results.find(x => x.value)?.value).toStrictEqual(expectedKey)
|
||||
expect(pushheaderSpy.mock.results.find(x => x.value)?.value).toStrictEqual(expectedHeader)
|
||||
expect(pushduexElementsSpy.mock.results.find(x => x.value)?.value).toStrictEqual(expectedDuexElement)
|
||||
expect(pushtwoPaneElementsSpy.mock.results.find(x => x.value)?.value).toStrictEqual(expectedtwoPaneElement)
|
||||
});
|
||||
|
||||
it('dualScreen Add no header with merge', () => {
|
||||
// Arrange
|
||||
const expectedKey: IKeyAction = KeyActionBuilder(PUSH_KEY, screenType.DUAL, 'test3', true);
|
||||
|
||||
const expectedDuexElement: IDuexElementAction = duexElementActionBuilder(PUSH_DUEXELEMENT, `${screenType.DUAL}_test3`, <Fragment />);
|
||||
const expectedtwoPaneElement: ITwoPaneElementAction = twoPaneElementActionBuilder(PUSH_TWOPANE_ELEMENT, `${screenType.DUAL}_test3`, <Fragment />);
|
||||
|
||||
const pushKeySpy = jest.spyOn(keyActions, 'pushKey');
|
||||
const pushheaderSpy = jest.spyOn(headerActions, 'pushHeader');
|
||||
|
||||
const pushduexElementsSpy = jest.spyOn(duexElementActions, 'pushElement');
|
||||
const pushtwoPaneElementsSpy = jest.spyOn(twoPaneElementActions, 'pushElement');
|
||||
|
||||
// Act
|
||||
const _dualScreenAdd = dualScreen.Add('test3', <Fragment />, undefined, true);
|
||||
|
@ -87,31 +87,31 @@ describe('dualScreen methods', () => {
|
|||
// Assert
|
||||
expect(pushKeySpy).toBeCalled();
|
||||
expect(pushheaderSpy).not.toBeCalled();
|
||||
expect(pushduexElementsSpy).toBeCalled();
|
||||
expect(pushtwoPaneElementsSpy).toBeCalled();
|
||||
expect(pushKeySpy.mock.results.find(x => x.value)?.value).toStrictEqual(expectedKey)
|
||||
expect(pushduexElementsSpy.mock.results.find(x => x.value)?.value).toStrictEqual(expectedDuexElement)
|
||||
expect(pushtwoPaneElementsSpy.mock.results.find(x => x.value)?.value).toStrictEqual(expectedtwoPaneElement)
|
||||
});
|
||||
|
||||
it('dualScreen Add with no header with no merge', () => {
|
||||
// Arrange
|
||||
const expectedKey: IKeyAction = KeyActionBuilder(PUSH_KEY, screenType.DUAL, 'test4', false);
|
||||
|
||||
const expectedDuexElement: IDuexElementAction = duexElementActionBuilder(PUSH_DUEXELEMENT, `${screenType.DUAL}_test4`, <Fragment />);
|
||||
const expectedtwoPaneElement: ITwoPaneElementAction = twoPaneElementActionBuilder(PUSH_TWOPANE_ELEMENT, `${screenType.DUAL}_test4`, <Fragment />);
|
||||
|
||||
const pushKeySpy = jest.spyOn(keyActions, 'pushKey');
|
||||
const pushheaderSpy = jest.spyOn(headerActions, 'pushHeader');
|
||||
const pushduexElementsSpy = jest.spyOn(duexElementActions, 'pushElement');
|
||||
const pushtwoPaneElementsSpy = jest.spyOn(twoPaneElementActions, 'pushElement');
|
||||
|
||||
// Act
|
||||
const _dualScreenAdd = dualScreen.Add('test4', <Fragment />);
|
||||
|
||||
// Assert
|
||||
expect(pushKeySpy).toBeCalled();
|
||||
expect(pushduexElementsSpy).toBeCalled();
|
||||
expect(pushtwoPaneElementsSpy).toBeCalled();
|
||||
expect(pushheaderSpy).not.toBeCalled();
|
||||
|
||||
expect(pushKeySpy.mock.results.find(x => x.value)?.value).toStrictEqual(expectedKey)
|
||||
expect(pushduexElementsSpy.mock.results.find(x => x.value)?.value).toStrictEqual(expectedDuexElement)
|
||||
expect(pushtwoPaneElementsSpy.mock.results.find(x => x.value)?.value).toStrictEqual(expectedtwoPaneElement)
|
||||
});
|
||||
|
||||
|
||||
|
@ -120,7 +120,7 @@ describe('dualScreen methods', () => {
|
|||
|
||||
const pushKeySpy = jest.spyOn(keyActions, 'pushKey');
|
||||
const pushheaderSpy = jest.spyOn(headerActions, 'pushHeader');
|
||||
const pushduexElementsSpy = jest.spyOn(duexElementActions, 'pushElement');
|
||||
const pushtwoPaneElementsSpy = jest.spyOn(twoPaneElementActions, 'pushElement');
|
||||
const moveToFrontSpy = jest.spyOn(keyActions, 'moveToFront');
|
||||
|
||||
// Act
|
||||
|
@ -129,7 +129,7 @@ describe('dualScreen methods', () => {
|
|||
// Assert
|
||||
expect(pushKeySpy).toBeCalled();
|
||||
expect(pushheaderSpy).toBeCalled();
|
||||
expect(pushduexElementsSpy).toBeCalled();
|
||||
expect(pushtwoPaneElementsSpy).toBeCalled();
|
||||
expect(moveToFrontSpy).not.toBeCalled();
|
||||
});
|
||||
|
||||
|
@ -139,7 +139,7 @@ describe('dualScreen methods', () => {
|
|||
// Arrange
|
||||
const pushKeySpy = jest.spyOn(keyActions, 'pushKey');
|
||||
const pushheaderSpy = jest.spyOn(headerActions, 'pushHeader');
|
||||
const pushduexElementsSpy = jest.spyOn(duexElementActions, 'pushElement');
|
||||
const pushtwoPaneElementsSpy = jest.spyOn(twoPaneElementActions, 'pushElement');
|
||||
const moveToFrontSpy = jest.spyOn(keyActions, 'moveToFront');
|
||||
|
||||
// Act
|
||||
|
@ -148,7 +148,7 @@ describe('dualScreen methods', () => {
|
|||
// Assert
|
||||
expect(pushKeySpy).not.toBeCalled();
|
||||
expect(pushheaderSpy).not.toBeCalled();
|
||||
expect(pushduexElementsSpy).not.toBeCalled();
|
||||
expect(pushtwoPaneElementsSpy).not.toBeCalled();
|
||||
expect(moveToFrontSpy).toBeCalled();
|
||||
});
|
||||
|
||||
|
@ -176,7 +176,7 @@ describe('dualScreen methods', () => {
|
|||
|
||||
const popToFrontSpy = jest.spyOn(keyActions, 'popToFront')
|
||||
const removeHeaderKeyBySpy = jest.spyOn(headerActions, 'removeHeaderByKey');
|
||||
const remodeDuexElementBySpy = jest.spyOn(duexElementActions, 'removeDuexElementByKey');
|
||||
const remodetwoPaneElementBySpy = jest.spyOn(twoPaneElementActions, 'removetwoPaneElementByKey');
|
||||
|
||||
|
||||
// Act
|
||||
|
@ -189,8 +189,8 @@ describe('dualScreen methods', () => {
|
|||
expect(removeHeaderKeyBySpy).toBeCalled();
|
||||
expect(removeHeaderKeyBySpy).toBeCalledTimes(4);
|
||||
|
||||
expect(remodeDuexElementBySpy).toBeCalled();
|
||||
expect(remodeDuexElementBySpy).toBeCalledTimes(4);
|
||||
expect(remodetwoPaneElementBySpy).toBeCalled();
|
||||
expect(remodetwoPaneElementBySpy).toBeCalledTimes(4);
|
||||
});
|
||||
|
||||
it('dualScreenGoBack calls GoBack', () => {
|
||||
|
@ -210,7 +210,7 @@ describe('dualScreen methods', () => {
|
|||
|
||||
const popScreenSpy = jest.spyOn(keyActions, 'popScreen')
|
||||
const removeHeaderKeyBySpy = jest.spyOn(headerActions, 'removeHeaderByKey');
|
||||
const removeDuexElementBySpy = jest.spyOn(duexElementActions, 'removeDuexElementByKey');
|
||||
const removetwoPaneElementBySpy = jest.spyOn(twoPaneElementActions, 'removetwoPaneElementByKey');
|
||||
|
||||
|
||||
// Act
|
||||
|
@ -225,20 +225,20 @@ describe('dualScreen methods', () => {
|
|||
expect(removeHeaderKeyBySpy).toBeCalled();
|
||||
expect(removeHeaderKeyBySpy).toBeCalledTimes(1);
|
||||
|
||||
expect(removeDuexElementBySpy).toBeCalled();
|
||||
expect(removeDuexElementBySpy).toBeCalledTimes(1);
|
||||
expect(removetwoPaneElementBySpy).toBeCalled();
|
||||
expect(removetwoPaneElementBySpy).toBeCalledTimes(1);
|
||||
});
|
||||
|
||||
it('replaceScreen calls', () => {
|
||||
// Arrange
|
||||
const replaceDuexElementSpy = jest.spyOn(duexElementActions, 'replaceDuexElement');
|
||||
const replacetwoPaneElementSpy = jest.spyOn(twoPaneElementActions, 'replacetwoPaneElement');
|
||||
|
||||
// Act
|
||||
const _dualScreenBack = dualScreen.ReplaceScreen('test', <Fragment />);
|
||||
|
||||
// Assert
|
||||
expect(replaceDuexElementSpy).toBeCalled();
|
||||
expect(replaceDuexElementSpy).toBeCalledTimes(1);
|
||||
expect(replacetwoPaneElementSpy).toBeCalled();
|
||||
expect(replacetwoPaneElementSpy).toBeCalledTimes(1);
|
||||
});
|
||||
|
||||
it('ReplaceHeader calls', () => {
|
|
@ -0,0 +1,48 @@
|
|||
// components
|
||||
export * from './components/dualApp/DualApp'
|
||||
export * from './components/screenOverlay/ScreenOverlay'
|
||||
|
||||
// methods
|
||||
export * from './singleScreen/singleScreenStore/singleScreen.methods'
|
||||
export * from './dualScreen/dualScreenStore/dualScreen.methods'
|
||||
export * from './utilities/auto.methods'
|
||||
export * from './utilities/utility.methods'
|
||||
|
||||
/// STORES ///
|
||||
// header
|
||||
export * from './Shared/screenStore/headerStore/header.actions'
|
||||
export * from './Shared/screenStore/headerStore/header.interface'
|
||||
export * from './Shared/screenStore/headerStore/header.reducer'
|
||||
export * from './Shared/screenStore/headerStore/header.selector'
|
||||
export * from './Shared/screenStore/headerStore/header.types'
|
||||
|
||||
// key
|
||||
export * from './Shared/screenStore/keyStore/key.actions'
|
||||
export * from './Shared/screenStore/keyStore/key.interface'
|
||||
export * from './Shared/screenStore/keyStore/key.reducer'
|
||||
export * from './Shared/screenStore/keyStore/key.selector'
|
||||
export * from './Shared/screenStore/keyStore/key.types'
|
||||
|
||||
// element
|
||||
export * from './Shared/screenStore/twoPaneElementStore/twoPaneElement.action'
|
||||
export * from './Shared/screenStore/twoPaneElementStore/twoPaneElement.interface'
|
||||
export * from './Shared/screenStore/twoPaneElementStore/twoPaneElement.reducer'
|
||||
export * from './Shared/screenStore/twoPaneElementStore/twoPaneElement.selectors'
|
||||
export * from './Shared/screenStore/twoPaneElementStore/twoPaneElement.types'
|
||||
|
||||
// Utility
|
||||
export * from './Shared/utilityStore/utilityStore.actions'
|
||||
export * from './Shared/utilityStore/utilityStore.interfaces'
|
||||
export * from './Shared/utilityStore/utilityStore.methods'
|
||||
export * from './Shared/utilityStore/utilityStore.reducer'
|
||||
export * from './Shared/utilityStore/utilityStore.selectors'
|
||||
export * from './Shared/utilityStore/utilityStore.types'
|
||||
|
||||
|
||||
// misc
|
||||
|
||||
export * from './utilities/interfaces'
|
||||
|
||||
|
||||
|
||||
|
|
@ -4,7 +4,7 @@ import {
|
|||
} from '../../utilities/interfaces';
|
||||
import { pushKey, popToFront, popScreen, moveToFront, changeScreen } from '../../Shared/screenStore/keyStore/key.actions';
|
||||
import { pushHeader, replaceHeader, removeHeaderByKey } from '../../Shared/screenStore/headerStore/header.actions';
|
||||
import { pushElement, removeDuexElementByKey, replaceDuexElement } from '../../Shared/screenStore/duexElementStore/duexElement.action';
|
||||
import { pushElement, removetwoPaneElementByKey, replacetwoPaneElement } from '../../Shared/screenStore/twoPaneElementStore/twoPaneElement.action';
|
||||
import { ReactElement } from 'react';
|
||||
import { IHeader } from '../../Shared/screenStore/headerStore/header.interface';
|
||||
import { IKeyState, IKeyObject } from '../../Shared/screenStore/keyStore/key.interface';
|
||||
|
@ -58,7 +58,7 @@ const BackToHome = () => {
|
|||
|
||||
for (let i = 1; i < singleScreenState.length; i++) {
|
||||
store.dispatch(removeHeaderByKey(singleScreenState[i].key));
|
||||
store.dispatch(removeDuexElementByKey(singleScreenState[i].key));
|
||||
store.dispatch(removetwoPaneElementByKey(singleScreenState[i].key));
|
||||
}
|
||||
|
||||
store.dispatch(popToFront(screenType.SINGLE));
|
||||
|
@ -72,7 +72,7 @@ const GoBack = () => {
|
|||
const singleScreenState: IKeyObject[] = keys.keys.filter(x => x.screen === screenType.SINGLE)
|
||||
|
||||
store.dispatch(removeHeaderByKey(singleScreenState.peek().key));
|
||||
store.dispatch(removeDuexElementByKey(singleScreenState.peek().key));
|
||||
store.dispatch(removetwoPaneElementByKey(singleScreenState.peek().key));
|
||||
store.dispatch(popScreen(screenType.SINGLE));
|
||||
|
||||
};
|
||||
|
@ -82,7 +82,7 @@ const GoBack = () => {
|
|||
* Replace the current element for this single screen component
|
||||
*/
|
||||
const ReplaceScreen = (key: string, element: React.ReactElement) => {
|
||||
store.dispatch(replaceDuexElement(`${screenType.SINGLE}_${key}`, element))
|
||||
store.dispatch(replacetwoPaneElement(`${screenType.SINGLE}_${key}`, element))
|
||||
}
|
||||
|
||||
/**
|
|
@ -2,7 +2,7 @@ import React from 'react'
|
|||
import singleScreen from '../singleScreen.methods';
|
||||
import * as keyActions from '../../../Shared/screenStore/keyStore/key.actions';
|
||||
import * as headerActions from '../../../Shared/screenStore/headerStore/header.actions';
|
||||
import * as duexElementActions from '../../../Shared/screenStore/duexElementStore/duexElement.action';
|
||||
import * as twoPaneElementActions from '../../../Shared/screenStore/twoPaneElementStore/twoPaneElement.action';
|
||||
|
||||
import { Fragment } from 'react';
|
||||
import { IKeyAction, IKeyState } from '../../../Shared/screenStore/keyStore/key.interface';
|
||||
|
@ -10,9 +10,9 @@ import { screenType } from '../../../utilities/interfaces';
|
|||
import { PUSH_KEY } from '../../../Shared/screenStore/keyStore/key.types';
|
||||
import { IHeaderAction } from '../../../Shared/screenStore/headerStore/header.interface';
|
||||
import { PUSH_HEADER } from '../../../Shared/screenStore/headerStore/header.types';
|
||||
import { IDuexElementAction } from '../../../Shared/screenStore/duexElementStore/duexElement.interface';
|
||||
import { PUSH_DUEXELEMENT } from '../../../Shared/screenStore/duexElementStore/duexElement.types';
|
||||
import { duexElementActionBuilder } from '../../../Shared/screenStore/duexElementStore/tests/duexElement.methods.helpers';
|
||||
import { ITwoPaneElementAction } from '../../../Shared/screenStore/twoPaneElementStore/twoPaneElement.interface';
|
||||
import { PUSH_TWOPANE_ELEMENT } from '../../../Shared/screenStore/twoPaneElementStore/twoPaneElement.types';
|
||||
import { twoPaneElementActionBuilder } from '../../../Shared/screenStore/twoPaneElementStore/tests/twoPaneElement.methods.helpers';
|
||||
import { headerActionBuilder } from '../../../Shared/screenStore/headerStore/tests/header.methods.helpers';
|
||||
import { KeyActionBuilder, mockKeyState } from '../../../Shared/screenStore/keyStore/tests/key.methods.helpers';
|
||||
import { store } from '../../../appStore';
|
||||
|
@ -27,11 +27,11 @@ describe('singleScreen methods', () => {
|
|||
|
||||
const expectedHeader: IHeaderAction = headerActionBuilder(PUSH_HEADER, `${screenType.SINGLE}_test1`, { title: 'test title' });
|
||||
|
||||
const expectedDuexElement: IDuexElementAction = duexElementActionBuilder(PUSH_DUEXELEMENT, `${screenType.SINGLE}_test1`, <Fragment />);
|
||||
const expectedtwoPaneElement: ITwoPaneElementAction = twoPaneElementActionBuilder(PUSH_TWOPANE_ELEMENT, `${screenType.SINGLE}_test1`, <Fragment />);
|
||||
|
||||
const pushKeySpy = jest.spyOn(keyActions, 'pushKey');
|
||||
const pushheaderSpy = jest.spyOn(headerActions, 'pushHeader');
|
||||
const pushduexElementsSpy = jest.spyOn(duexElementActions, 'pushElement');
|
||||
const pushtwoPaneElementsSpy = jest.spyOn(twoPaneElementActions, 'pushElement');
|
||||
|
||||
// Act
|
||||
const _singleScreenAdd = singleScreen.Add('test1', <Fragment />, { title: 'test title' }, true);
|
||||
|
@ -39,10 +39,10 @@ describe('singleScreen methods', () => {
|
|||
// Assert
|
||||
expect(pushKeySpy).toBeCalled();
|
||||
expect(pushheaderSpy).toBeCalled();
|
||||
expect(pushduexElementsSpy).toBeCalled();
|
||||
expect(pushtwoPaneElementsSpy).toBeCalled();
|
||||
expect(pushKeySpy.mock.results.find(x => x.value)?.value).toStrictEqual(expectedKey)
|
||||
expect(pushheaderSpy.mock.results.find(x => x.value)?.value).toStrictEqual(expectedHeader)
|
||||
expect(pushduexElementsSpy.mock.results.find(x => x.value)?.value).toStrictEqual(expectedDuexElement)
|
||||
expect(pushtwoPaneElementsSpy.mock.results.find(x => x.value)?.value).toStrictEqual(expectedtwoPaneElement)
|
||||
});
|
||||
|
||||
it('singleScreen Add with header with no merge', () => {
|
||||
|
@ -51,11 +51,11 @@ describe('singleScreen methods', () => {
|
|||
|
||||
const expectedHeader: IHeaderAction = headerActionBuilder(PUSH_HEADER, `${screenType.SINGLE}_test2`, { title: 'test title' });
|
||||
|
||||
const expectedDuexElement: IDuexElementAction = duexElementActionBuilder(PUSH_DUEXELEMENT, `${screenType.SINGLE}_test2`, <Fragment />);
|
||||
const expectedtwoPaneElement: ITwoPaneElementAction = twoPaneElementActionBuilder(PUSH_TWOPANE_ELEMENT, `${screenType.SINGLE}_test2`, <Fragment />);
|
||||
|
||||
const pushKeySpy = jest.spyOn(keyActions, 'pushKey');
|
||||
const pushheaderSpy = jest.spyOn(headerActions, 'pushHeader');
|
||||
const pushduexElementsSpy = jest.spyOn(duexElementActions, 'pushElement');
|
||||
const pushtwoPaneElementsSpy = jest.spyOn(twoPaneElementActions, 'pushElement');
|
||||
|
||||
// Act
|
||||
const _singleScreenAdd = singleScreen.Add('test2', <Fragment />, { title: 'test title' });
|
||||
|
@ -63,22 +63,22 @@ describe('singleScreen methods', () => {
|
|||
// Assert
|
||||
expect(pushKeySpy).toBeCalled();
|
||||
expect(pushheaderSpy).toBeCalled();
|
||||
expect(pushduexElementsSpy).toBeCalled();
|
||||
expect(pushtwoPaneElementsSpy).toBeCalled();
|
||||
expect(pushKeySpy.mock.results.find(x => x.value)?.value).toStrictEqual(expectedKey)
|
||||
expect(pushheaderSpy.mock.results.find(x => x.value)?.value).toStrictEqual(expectedHeader)
|
||||
expect(pushduexElementsSpy.mock.results.find(x => x.value)?.value).toStrictEqual(expectedDuexElement)
|
||||
expect(pushtwoPaneElementsSpy.mock.results.find(x => x.value)?.value).toStrictEqual(expectedtwoPaneElement)
|
||||
});
|
||||
|
||||
it('singleScreen Add no header with merge', () => {
|
||||
// Arrange
|
||||
const expectedKey: IKeyAction = KeyActionBuilder(PUSH_KEY, screenType.SINGLE, 'test3', true);
|
||||
|
||||
const expectedDuexElement: IDuexElementAction = duexElementActionBuilder(PUSH_DUEXELEMENT, `${screenType.SINGLE}_test3`, <Fragment />);
|
||||
const expectedtwoPaneElement: ITwoPaneElementAction = twoPaneElementActionBuilder(PUSH_TWOPANE_ELEMENT, `${screenType.SINGLE}_test3`, <Fragment />);
|
||||
|
||||
const pushKeySpy = jest.spyOn(keyActions, 'pushKey');
|
||||
const pushheaderSpy = jest.spyOn(headerActions, 'pushHeader');
|
||||
|
||||
const pushduexElementsSpy = jest.spyOn(duexElementActions, 'pushElement');
|
||||
const pushtwoPaneElementsSpy = jest.spyOn(twoPaneElementActions, 'pushElement');
|
||||
|
||||
// Act
|
||||
const _singleScreenAdd = singleScreen.Add('test3', <Fragment />, undefined, true);
|
||||
|
@ -86,31 +86,31 @@ describe('singleScreen methods', () => {
|
|||
// Assert
|
||||
expect(pushKeySpy).toBeCalled();
|
||||
expect(pushheaderSpy).not.toBeCalled();
|
||||
expect(pushduexElementsSpy).toBeCalled();
|
||||
expect(pushtwoPaneElementsSpy).toBeCalled();
|
||||
expect(pushKeySpy.mock.results.find(x => x.value)?.value).toStrictEqual(expectedKey)
|
||||
expect(pushduexElementsSpy.mock.results.find(x => x.value)?.value).toStrictEqual(expectedDuexElement)
|
||||
expect(pushtwoPaneElementsSpy.mock.results.find(x => x.value)?.value).toStrictEqual(expectedtwoPaneElement)
|
||||
});
|
||||
|
||||
it('singleScreen Add with no header with no merge', () => {
|
||||
// Arrange
|
||||
const expectedKey: IKeyAction = KeyActionBuilder(PUSH_KEY, screenType.SINGLE, 'test4', false);
|
||||
|
||||
const expectedDuexElement: IDuexElementAction = duexElementActionBuilder(PUSH_DUEXELEMENT, `${screenType.SINGLE}_test4`, <Fragment />);
|
||||
const expectedtwoPaneElement: ITwoPaneElementAction = twoPaneElementActionBuilder(PUSH_TWOPANE_ELEMENT, `${screenType.SINGLE}_test4`, <Fragment />);
|
||||
|
||||
const pushKeySpy = jest.spyOn(keyActions, 'pushKey');
|
||||
const pushheaderSpy = jest.spyOn(headerActions, 'pushHeader');
|
||||
const pushduexElementsSpy = jest.spyOn(duexElementActions, 'pushElement');
|
||||
const pushtwoPaneElementsSpy = jest.spyOn(twoPaneElementActions, 'pushElement');
|
||||
|
||||
// Act
|
||||
const _singleScreenAdd = singleScreen.Add('test4', <Fragment />);
|
||||
|
||||
// Assert
|
||||
expect(pushKeySpy).toBeCalled();
|
||||
expect(pushduexElementsSpy).toBeCalled();
|
||||
expect(pushtwoPaneElementsSpy).toBeCalled();
|
||||
expect(pushheaderSpy).not.toBeCalled();
|
||||
|
||||
expect(pushKeySpy.mock.results.find(x => x.value)?.value).toStrictEqual(expectedKey)
|
||||
expect(pushduexElementsSpy.mock.results.find(x => x.value)?.value).toStrictEqual(expectedDuexElement)
|
||||
expect(pushtwoPaneElementsSpy.mock.results.find(x => x.value)?.value).toStrictEqual(expectedtwoPaneElement)
|
||||
});
|
||||
|
||||
|
||||
|
@ -119,7 +119,7 @@ describe('singleScreen methods', () => {
|
|||
|
||||
const pushKeySpy = jest.spyOn(keyActions, 'pushKey');
|
||||
const pushheaderSpy = jest.spyOn(headerActions, 'pushHeader');
|
||||
const pushduexElementsSpy = jest.spyOn(duexElementActions, 'pushElement');
|
||||
const pushtwoPaneElementsSpy = jest.spyOn(twoPaneElementActions, 'pushElement');
|
||||
const moveToFrontSpy = jest.spyOn(keyActions, 'moveToFront');
|
||||
|
||||
// Act
|
||||
|
@ -128,7 +128,7 @@ describe('singleScreen methods', () => {
|
|||
// Assert
|
||||
expect(pushKeySpy).toBeCalled();
|
||||
expect(pushheaderSpy).toBeCalled();
|
||||
expect(pushduexElementsSpy).toBeCalled();
|
||||
expect(pushtwoPaneElementsSpy).toBeCalled();
|
||||
expect(moveToFrontSpy).not.toBeCalled();
|
||||
});
|
||||
|
||||
|
@ -138,7 +138,7 @@ describe('singleScreen methods', () => {
|
|||
// Arrange
|
||||
const pushKeySpy = jest.spyOn(keyActions, 'pushKey');
|
||||
const pushheaderSpy = jest.spyOn(headerActions, 'pushHeader');
|
||||
const pushduexElementsSpy = jest.spyOn(duexElementActions, 'pushElement');
|
||||
const pushtwoPaneElementsSpy = jest.spyOn(twoPaneElementActions, 'pushElement');
|
||||
const moveToFrontSpy = jest.spyOn(keyActions, 'moveToFront');
|
||||
|
||||
// Act
|
||||
|
@ -147,7 +147,7 @@ describe('singleScreen methods', () => {
|
|||
// Assert
|
||||
expect(pushKeySpy).not.toBeCalled();
|
||||
expect(pushheaderSpy).not.toBeCalled();
|
||||
expect(pushduexElementsSpy).not.toBeCalled();
|
||||
expect(pushtwoPaneElementsSpy).not.toBeCalled();
|
||||
expect(moveToFrontSpy).toBeCalled();
|
||||
});
|
||||
|
||||
|
@ -175,7 +175,7 @@ describe('singleScreen methods', () => {
|
|||
|
||||
const popToFrontSpy = jest.spyOn(keyActions, 'popToFront')
|
||||
const removeHeaderKeyBySpy = jest.spyOn(headerActions, 'removeHeaderByKey');
|
||||
const remodeDuexElementBySpy = jest.spyOn(duexElementActions, 'removeDuexElementByKey');
|
||||
const remodetwoPaneElementBySpy = jest.spyOn(twoPaneElementActions, 'removetwoPaneElementByKey');
|
||||
|
||||
|
||||
// Act
|
||||
|
@ -188,8 +188,8 @@ describe('singleScreen methods', () => {
|
|||
expect(removeHeaderKeyBySpy).toBeCalled();
|
||||
expect(removeHeaderKeyBySpy).toBeCalledTimes(4);
|
||||
|
||||
expect(remodeDuexElementBySpy).toBeCalled();
|
||||
expect(remodeDuexElementBySpy).toBeCalledTimes(4);
|
||||
expect(remodetwoPaneElementBySpy).toBeCalled();
|
||||
expect(remodetwoPaneElementBySpy).toBeCalledTimes(4);
|
||||
});
|
||||
|
||||
it('singleScreenGoBack calls GoBack', () => {
|
||||
|
@ -209,7 +209,7 @@ describe('singleScreen methods', () => {
|
|||
|
||||
const popScreenSpy = jest.spyOn(keyActions, 'popScreen')
|
||||
const removeHeaderKeyBySpy = jest.spyOn(headerActions, 'removeHeaderByKey');
|
||||
const removeDuexElementBySpy = jest.spyOn(duexElementActions, 'removeDuexElementByKey');
|
||||
const removetwoPaneElementBySpy = jest.spyOn(twoPaneElementActions, 'removetwoPaneElementByKey');
|
||||
|
||||
|
||||
// Act
|
||||
|
@ -225,20 +225,20 @@ describe('singleScreen methods', () => {
|
|||
expect(removeHeaderKeyBySpy).toBeCalled();
|
||||
expect(removeHeaderKeyBySpy).toBeCalledTimes(1);
|
||||
|
||||
expect(removeDuexElementBySpy).toBeCalled();
|
||||
expect(removeDuexElementBySpy).toBeCalledTimes(1);
|
||||
expect(removetwoPaneElementBySpy).toBeCalled();
|
||||
expect(removetwoPaneElementBySpy).toBeCalledTimes(1);
|
||||
});
|
||||
|
||||
it('replaceScreen calls', () => {
|
||||
// Arrange
|
||||
const replaceDuexElementSpy = jest.spyOn(duexElementActions, 'replaceDuexElement');
|
||||
const replacetwoPaneElementSpy = jest.spyOn(twoPaneElementActions, 'replacetwoPaneElement');
|
||||
|
||||
// Act
|
||||
const _singleScreenBack = singleScreen.ReplaceScreen('test', <Fragment />);
|
||||
|
||||
// Assert
|
||||
expect(replaceDuexElementSpy).toBeCalled();
|
||||
expect(replaceDuexElementSpy).toBeCalledTimes(1);
|
||||
expect(replacetwoPaneElementSpy).toBeCalled();
|
||||
expect(replacetwoPaneElementSpy).toBeCalledTimes(1);
|
||||
});
|
||||
|
||||
it('ReplaceHeader calls', () => {
|
|
@ -78,11 +78,11 @@ const GoBack = () => {
|
|||
/**
|
||||
* Automatically replace element in the stack based on screen size
|
||||
*/
|
||||
const ReplaceScreen = (key: string, duexElement: React.ReactElement) => {
|
||||
const ReplaceScreen = (key: string, twoPaneElement: React.ReactElement) => {
|
||||
if (utility.isDualScreen()) {
|
||||
dualScreen.ReplaceScreen(key, duexElement);
|
||||
dualScreen.ReplaceScreen(key, twoPaneElement);
|
||||
} else {
|
||||
singleScreen.ReplaceScreen(key, duexElement);
|
||||
singleScreen.ReplaceScreen(key, twoPaneElement);
|
||||
}
|
||||
};
|
||||
|
|
@ -1,10 +1,11 @@
|
|||
|
||||
|
||||
interface Array<T> {
|
||||
declare global {
|
||||
interface Array<T> {
|
||||
/**
|
||||
* Returns the last element from an array.
|
||||
*/
|
||||
peek(): T;
|
||||
}
|
||||
}
|
||||
|
||||
Array.prototype.peek = function () {
|
||||
|
@ -15,3 +16,5 @@ Array.prototype.peek = function () {
|
|||
return undefined; // or another default value...
|
||||
};
|
||||
|
||||
|
||||
export {}
|
|
@ -3,7 +3,7 @@ import { IHeader } from '../Shared/screenStore/headerStore/header.interface';
|
|||
|
||||
export interface IScreenComponent {
|
||||
key: string;
|
||||
duexElement: ReactElement;
|
||||
twoPaneElement: ReactElement;
|
||||
header?: IHeader;
|
||||
screen?: screenType;
|
||||
}
|
|
@ -5,17 +5,8 @@ const isDualScreen = (): boolean => {
|
|||
return store.getState().utilityStoreReducer.isDualScreen
|
||||
};
|
||||
|
||||
export const usePrevious = <T extends {}>(value: T): T | undefined => {
|
||||
const ref = useRef<T>();
|
||||
useEffect(() => {
|
||||
ref.current = value;
|
||||
});
|
||||
return ref.current;
|
||||
};
|
||||
|
||||
const _utilityFunctions = {
|
||||
isDualScreen,
|
||||
usePrevious
|
||||
};
|
||||
|
||||
type utilityFunctions = typeof _utilityFunctions;
|
|
@ -2,5 +2,3 @@ jest.mock('react-native/Libraries/EventEmitter/NativeEventEmitter.js', () => {
|
|||
const { EventEmitter } = require('events');
|
||||
return EventEmitter;
|
||||
});
|
||||
|
||||
jest.mock("react-native-reanimated", () => require("react-native-reanimated/mock"))
|
|
@ -1,28 +1,26 @@
|
|||
{
|
||||
"include": ["src/**/*.ts"],
|
||||
"compilerOptions": {
|
||||
/* Basic Options */
|
||||
"target": "esnext" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */,
|
||||
"module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */,
|
||||
"lib": [
|
||||
"es6",
|
||||
"dom"
|
||||
] /* Specify library files to be included in the compilation. */,
|
||||
"allowJs": true /* Allow javascript files to be compiled. */,
|
||||
"target": "esnext", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */
|
||||
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
|
||||
"lib": ["es6"], /* Specify library files to be included in the compilation. */
|
||||
"allowJs": true, /* Allow javascript files to be compiled. */
|
||||
// "checkJs": true, /* Report errors in .js files. */
|
||||
"jsx": "react-native" /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */,
|
||||
"jsx": "react-native", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
|
||||
// "declaration": true, /* Generates corresponding '.d.ts' file. */
|
||||
// "sourceMap": true /* Generates corresponding '.map' file. */,
|
||||
// "sourceMap": true, /* Generates corresponding '.map' file. */
|
||||
// "outFile": "./", /* Concatenate and emit output to single file. */
|
||||
// "outDir": "./", /* Redirect output structure to the directory. */
|
||||
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
||||
// "removeComments": true, /* Do not emit comments to output. */
|
||||
"noEmit": true /* Do not emit outputs. */,
|
||||
//"incremental": true, /* Enable incremental compilation */
|
||||
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
|
||||
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
|
||||
"isolatedModules": true /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */,
|
||||
"isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
|
||||
|
||||
/* Strict Type-Checking Options */
|
||||
"strict": true /* Enable all strict type-checking options. */,
|
||||
"strict": true, /* Enable all strict type-checking options. */
|
||||
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
|
||||
// "strictNullChecks": true, /* Enable strict null checks. */
|
||||
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
|
||||
|
@ -37,30 +35,27 @@
|
|||
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
||||
|
||||
/* Module Resolution Options */
|
||||
"moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */,
|
||||
"baseUrl": "./" /* Base directory to resolve non-absolute module names. */,
|
||||
"moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
|
||||
"baseUrl": "./", /* Base directory to resolve non-absolute module names. */
|
||||
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
|
||||
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
|
||||
// "typeRoots": [], /* List of folders to include type definitions from. */
|
||||
// "types": [], /* Type declaration files to be included in compilation. */
|
||||
"allowSyntheticDefaultImports": true /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */,
|
||||
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
|
||||
"allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
|
||||
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
|
||||
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
|
||||
|
||||
/* Source Map Options */
|
||||
// "sourceRoot": "./", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
|
||||
// "mapRoot": "./", /* Specify the location where debugger should locate map files instead of generated locations. */
|
||||
"inlineSourceMap": true /* Emit a single file with source maps instead of having a separate file. */,
|
||||
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
|
||||
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
|
||||
|
||||
/* Experimental Options */
|
||||
"experimentalDecorators": true /* Enables experimental support for ES7 decorators. */
|
||||
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
|
||||
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"babel.config.js",
|
||||
"metro.config.js",
|
||||
"jest.config.js"
|
||||
"node_modules", "babel.config.js", "metro.config.js", "jest.config.js"
|
||||
]
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
import { IAuthAction } from './auth.interfaces';
|
||||
import { SIGNED_IN, SIGNED_OUT, LOADING } from './auth.types';
|
||||
|
||||
export const signedIn = (): IAuthAction => ({
|
||||
type: SIGNED_IN
|
||||
});
|
||||
|
||||
export const signedOut = (): IAuthAction => ({
|
||||
type: SIGNED_OUT
|
||||
});
|
||||
|
||||
export const loading = (): IAuthAction => ({
|
||||
type: LOADING
|
||||
});
|
|
@ -1,8 +0,0 @@
|
|||
export interface IAuthAction {
|
||||
type: string;
|
||||
}
|
||||
|
||||
export interface IAuthState {
|
||||
isSignedOut: boolean;
|
||||
isLoading: boolean;
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
import { store } from '../../appStore';
|
||||
|
||||
import { signedOut, signedIn, loading } from './auth.actions';
|
||||
|
||||
export const signIn = () => {
|
||||
store.dispatch(signedIn());
|
||||
};
|
||||
export const signOut = () => {
|
||||
store.dispatch(signedOut());
|
||||
};
|
||||
export const startLoading = () => {
|
||||
store.dispatch(loading());
|
||||
};
|
|
@ -1,31 +0,0 @@
|
|||
import { IAuthAction, IAuthState } from './auth.interfaces';
|
||||
import { SIGNED_IN, SIGNED_OUT, LOADING } from './auth.types';
|
||||
|
||||
const initialState: IAuthState = {
|
||||
isLoading: false,
|
||||
isSignedOut: true
|
||||
};
|
||||
|
||||
const authReducer = (state: IAuthState = initialState, action: IAuthAction) => {
|
||||
switch (action.type) {
|
||||
case SIGNED_IN:
|
||||
return {
|
||||
isSignedOut: false,
|
||||
isLoading: false
|
||||
};
|
||||
case LOADING:
|
||||
return {
|
||||
...state,
|
||||
isLoading: true
|
||||
};
|
||||
case SIGNED_OUT:
|
||||
return {
|
||||
isSignedOut: true,
|
||||
isLoading: false
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
export default authReducer;
|
|
@ -1,7 +0,0 @@
|
|||
import { useSelector } from 'react-redux';
|
||||
import { rootReducerType } from '../../appStore';
|
||||
import { IAuthState } from './auth.interfaces';
|
||||
|
||||
export const authState = (): IAuthState => {
|
||||
return useSelector((state: rootReducerType) => state.authReducer);
|
||||
};
|
|
@ -1,3 +0,0 @@
|
|||
export const SIGNED_IN: string = 'SIGNED_IN';
|
||||
export const SIGNED_OUT: string = 'SIGNED_OUT';
|
||||
export const LOADING: string = 'LOADING';
|
|
@ -1,51 +0,0 @@
|
|||
import * as actionsMethods from '../auth.actions';
|
||||
import * as types from '../auth.types';
|
||||
import { IAuthAction } from '../auth.interfaces';
|
||||
|
||||
describe('auth actions', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
describe('loading', () => {
|
||||
it('should create action to show loading screen', () => {
|
||||
// Arrange
|
||||
const expectedAction: IAuthAction = {
|
||||
type: types.LOADING
|
||||
};
|
||||
|
||||
// Act
|
||||
const callAction = actionsMethods.loading();
|
||||
|
||||
// Assert
|
||||
expect(callAction).toEqual(expectedAction);
|
||||
});
|
||||
});
|
||||
describe('signedIn', () => {
|
||||
it('should create action to set user as signed in', () => {
|
||||
// Arrange
|
||||
const expectedAction: IAuthAction = {
|
||||
type: types.SIGNED_IN
|
||||
};
|
||||
|
||||
// Act
|
||||
const callAction = actionsMethods.signedIn();
|
||||
|
||||
// Assert
|
||||
expect(callAction).toEqual(expectedAction);
|
||||
});
|
||||
});
|
||||
describe('signedOut', () => {
|
||||
it('should create action to set user as signed out', () => {
|
||||
// Arrange
|
||||
const expectedAction: IAuthAction = {
|
||||
type: types.SIGNED_OUT
|
||||
};
|
||||
|
||||
// Act
|
||||
const callAction = actionsMethods.signedOut();
|
||||
|
||||
// Assert
|
||||
expect(callAction).toEqual(expectedAction);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,27 +0,0 @@
|
|||
import * as actions from '../auth.actions';
|
||||
import { signIn, signOut, startLoading } from '../auth.methods';
|
||||
|
||||
describe('auth methods', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('signIn calls signedIn', () => {
|
||||
const signedInSpy = jest.spyOn(actions, 'signedIn');
|
||||
const _signIn = signIn();
|
||||
|
||||
expect(signedInSpy).toBeCalledTimes(1);
|
||||
});
|
||||
it('startLoading calls loading', () => {
|
||||
const loadingSpy = jest.spyOn(actions, 'loading');
|
||||
const _startLoading = startLoading();
|
||||
|
||||
expect(loadingSpy).toBeCalledTimes(1);
|
||||
});
|
||||
it('signOut calls signedOut', () => {
|
||||
const signedOutSpy = jest.spyOn(actions, 'signedOut');
|
||||
const _signOut = signOut();
|
||||
|
||||
expect(signedOutSpy).toBeCalledTimes(1);
|
||||
});
|
||||
});
|
|
@ -1,66 +0,0 @@
|
|||
import authReducer from '../auth.reducer';
|
||||
import { IAuthState } from '../auth.interfaces';
|
||||
import { SIGNED_IN, LOADING, SIGNED_OUT } from '../auth.types';
|
||||
|
||||
const initialState: IAuthState = {
|
||||
isLoading: false,
|
||||
isSignedOut: true
|
||||
};
|
||||
|
||||
describe('auth reducer', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
it('should return initial state', () => {
|
||||
// Act
|
||||
const reducer = authReducer(undefined, { type: '' });
|
||||
|
||||
// Assert
|
||||
expect(reducer).toEqual(initialState);
|
||||
});
|
||||
it('SIGNED_IN', () => {
|
||||
// Arrange
|
||||
const signedIn = { type: SIGNED_IN };
|
||||
|
||||
const finalState: IAuthState = {
|
||||
isSignedOut: false,
|
||||
isLoading: false
|
||||
};
|
||||
|
||||
// Act
|
||||
const reducer = authReducer(initialState, signedIn);
|
||||
|
||||
// Assert
|
||||
expect(reducer).toEqual(finalState);
|
||||
});
|
||||
it('LOADING', () => {
|
||||
// Arrange
|
||||
const loading = { type: LOADING };
|
||||
|
||||
const finalState: IAuthState = {
|
||||
isSignedOut: true,
|
||||
isLoading: true
|
||||
};
|
||||
|
||||
// Act
|
||||
const reducer = authReducer(initialState, loading);
|
||||
|
||||
// Assert
|
||||
expect(reducer).toEqual(finalState);
|
||||
});
|
||||
it('SIGNED_OUT', () => {
|
||||
// Arrange
|
||||
const signOut = { type: SIGNED_OUT };
|
||||
|
||||
const finalState: IAuthState = {
|
||||
...initialState,
|
||||
isLoading: false
|
||||
};
|
||||
|
||||
// Act
|
||||
const reducer = authReducer(initialState, signOut);
|
||||
|
||||
// Assert
|
||||
expect(reducer).toEqual(finalState);
|
||||
});
|
||||
});
|
|
@ -1,12 +0,0 @@
|
|||
import { IDrawerAction } from './drawer.interfaces';
|
||||
import { PUSH_TO_DRAWER } from './drawer.types';
|
||||
|
||||
/**
|
||||
* Add an element to the drawer.
|
||||
*/
|
||||
export const pushToDrawer = (elements: JSX.Element[]): IDrawerAction => ({
|
||||
type: PUSH_TO_DRAWER,
|
||||
payload: {
|
||||
elements
|
||||
}
|
||||
});
|
|
@ -1,10 +0,0 @@
|
|||
export interface IDrawerState {
|
||||
drawerItems: JSX.Element[];
|
||||
}
|
||||
|
||||
export interface IDrawerAction {
|
||||
type: string;
|
||||
payload: {
|
||||
elements: JSX.Element[];
|
||||
};
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
import { store } from '../../appStore';
|
||||
import { pushToDrawer } from './drawer.actions';
|
||||
|
||||
export const addToDrawer = (elements: JSX.Element[]) => {
|
||||
store.dispatch(pushToDrawer(elements));
|
||||
};
|
|
@ -1,28 +0,0 @@
|
|||
import { PUSH_TO_DRAWER } from './drawer.types';
|
||||
import { IDrawerState, IDrawerAction } from './drawer.interfaces';
|
||||
|
||||
const initialState: IDrawerState = {
|
||||
drawerItems: []
|
||||
};
|
||||
|
||||
const drawerReducer = (
|
||||
state: IDrawerState = initialState,
|
||||
action: IDrawerAction
|
||||
) => {
|
||||
switch (action.type) {
|
||||
case PUSH_TO_DRAWER: {
|
||||
const newItems = state.drawerItems;
|
||||
action.payload.elements.forEach(element => {
|
||||
newItems.push(element);
|
||||
});
|
||||
return {
|
||||
...state,
|
||||
drawerItems: newItems
|
||||
};
|
||||
}
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
export default drawerReducer;
|
|
@ -1,9 +0,0 @@
|
|||
import { useSelector } from 'react-redux';
|
||||
import { rootReducerType } from '../../appStore';
|
||||
import { IDrawerState } from './drawer.interfaces';
|
||||
|
||||
export const getDrawerItems = (): JSX.Element[] => {
|
||||
return useSelector(
|
||||
(state: rootReducerType) => state.drawerReducer.drawerItems
|
||||
);
|
||||
};
|
|
@ -1 +0,0 @@
|
|||
export const PUSH_TO_DRAWER: string = 'PUSH_TO_DRAWER';
|
|
@ -1,36 +0,0 @@
|
|||
import { PUSH_DUEXELEMENT, REMOVE_KEY_DUEXELEMENT, REPLACE_DUEXELEMENT } from "./duexElement.types";
|
||||
import { ReactElement } from "react";
|
||||
import { IDuexElementAction } from "./duexElement.interface";
|
||||
import { IKeyOnlyAction } from "../keyStore/key.interface";
|
||||
|
||||
export const pushElement = (
|
||||
key: string,
|
||||
duexElement: ReactElement
|
||||
): IDuexElementAction => ({
|
||||
type: PUSH_DUEXELEMENT,
|
||||
payload: {
|
||||
key: key,
|
||||
duexElement: duexElement
|
||||
}
|
||||
});
|
||||
|
||||
export const replaceDuexElement = (
|
||||
key: string,
|
||||
duexElement: ReactElement
|
||||
): IDuexElementAction => ({
|
||||
type: REPLACE_DUEXELEMENT,
|
||||
payload: {
|
||||
key: key,
|
||||
duexElement: duexElement
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
export const removeDuexElementByKey = (
|
||||
duexElementKey: string
|
||||
): IKeyOnlyAction => ({
|
||||
type: REMOVE_KEY_DUEXELEMENT,
|
||||
payload: {
|
||||
key: duexElementKey
|
||||
}
|
||||
});
|
|
@ -1,17 +0,0 @@
|
|||
import { ReactElement } from "react";
|
||||
|
||||
export interface IDuexElementObject {
|
||||
[key: string]: ReactElement;
|
||||
}
|
||||
|
||||
export interface IDuexElementState {
|
||||
duexElements: IDuexElementObject;
|
||||
}
|
||||
|
||||
export interface IDuexElementAction {
|
||||
type: string;
|
||||
payload: {
|
||||
key: string
|
||||
duexElement: ReactElement;
|
||||
};
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
|
||||
import { PUSH_DUEXELEMENT, REMOVE_KEY_DUEXELEMENT, REPLACE_DUEXELEMENT } from './duexElement.types';
|
||||
import { IDuexElementState, IDuexElementAction } from './duexElement.interface';
|
||||
|
||||
const initialState: IDuexElementState = {
|
||||
duexElements: {}
|
||||
};
|
||||
|
||||
const duexElementReducer = (
|
||||
state: IDuexElementState = initialState,
|
||||
action: IDuexElementAction
|
||||
): IDuexElementState => {
|
||||
switch (action.type) {
|
||||
case PUSH_DUEXELEMENT: {
|
||||
return {
|
||||
...state,
|
||||
duexElements: {
|
||||
...state.duexElements,
|
||||
[action.payload.key as string]: action.payload.duexElement
|
||||
}
|
||||
};
|
||||
}
|
||||
case REPLACE_DUEXELEMENT: {
|
||||
const hasKey = action.payload.key in state.duexElements;
|
||||
if (!hasKey) {
|
||||
return { ...state };
|
||||
}
|
||||
return {
|
||||
...state,
|
||||
duexElements: {
|
||||
...state.duexElements,
|
||||
[action.payload.key as string]: action.payload.duexElement
|
||||
},
|
||||
};
|
||||
|
||||
}
|
||||
case REMOVE_KEY_DUEXELEMENT: {
|
||||
// using delete over lodash.omit to reduce dependencies on external libraries
|
||||
const newData = state;
|
||||
delete newData.duexElements[action.payload.key];
|
||||
return { ...newData }
|
||||
}
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
export default duexElementReducer;
|
|
@ -1,7 +0,0 @@
|
|||
import { useSelector } from "react-redux";
|
||||
import { rootReducerType } from "../../../appStore";
|
||||
import { IDuexElementState } from "./duexElement.interface";
|
||||
|
||||
export const getDuexElementSelector = (): IDuexElementState => {
|
||||
return useSelector((state: rootReducerType) => state.duexElementReducer);
|
||||
};
|
|
@ -1,7 +0,0 @@
|
|||
export const PUSH_DUEXELEMENT: string = 'PUSH_DUEXELEMENT';
|
||||
|
||||
export const REMOVE_KEY_DUEXELEMENT: string = 'REMOVE_KEY_DUEXELEMENT';
|
||||
|
||||
export const REPLACE_DUEXELEMENT: string = 'REPLACE_DUEXELEMENT';
|
||||
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
import { IDuexElementAction, IDuexElementObject } from "../duexElement.interface"
|
||||
import React, { ReactElement } from 'react';
|
||||
|
||||
export const duexElementActionBuilder = (type: string, key: string, duexElement: React.ReactElement): IDuexElementAction => {
|
||||
return {
|
||||
type: type,
|
||||
payload: {
|
||||
key: key,
|
||||
duexElement: duexElement
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
export const duexElementObjectBuilder = (key: string, duexElement: ReactElement): IDuexElementObject => {
|
||||
return {
|
||||
[key]: duexElement
|
||||
}
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
{
|
||||
"name": "twopane-navigation",
|
||||
"Title": "twopane-navigation",
|
||||
"version": "1.0.0",
|
||||
"scripts": {
|
||||
"test": "jest",
|
||||
"coverage": "jest --coverage"
|
||||
},
|
||||
"dependencies": {
|
||||
"react": "^16.11.0",
|
||||
"react-native": "^0.62.2",
|
||||
"react-native-dualscreeninfo": "^0.1.1",
|
||||
"react-native-reanimated": "^1.9.0",
|
||||
"react-native-vector-icons": "^6.6.0",
|
||||
"react-redux": "^7.2.0",
|
||||
"redux": "^4.0.5",
|
||||
"lodash": "^4.17.15"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/plugin-proposal-decorators": "^7.7.0",
|
||||
"@react-native-community/toolbar-android": "0.1.0-rc.2",
|
||||
"@babel/core": "^7.6.2",
|
||||
"@babel/preset-typescript": "^7.7.2",
|
||||
"@babel/runtime": "^7.6.2",
|
||||
"@react-native-community/eslint-config": "^0.0.5",
|
||||
"@testing-library/jest-native": "^3.1.0",
|
||||
"@testing-library/react-native": "^5.0.3",
|
||||
"@types/jest": "^24.0.18",
|
||||
"@types/lodash": "^4.14.145",
|
||||
"@types/react": "16.9.0",
|
||||
"@types/react-native": "^0.60.17",
|
||||
"@types/react-native-autocomplete-input": "^4.0.1",
|
||||
"@types/react-navigation": "^3.0.8",
|
||||
"@types/react-redux": "^7.1.7",
|
||||
"@types/react-test-renderer": "16.9.0",
|
||||
"babel-jest": "^24.9.0",
|
||||
"jest": "^24.9.0",
|
||||
"metro-react-native-babel-preset": "^0.58.0",
|
||||
"react-native-testing-library": "^1.14.0",
|
||||
"react-test-renderer": "16.9.0",
|
||||
"typescript": "^3.6.3"
|
||||
},
|
||||
"jest": {
|
||||
"preset": "react-native",
|
||||
"moduleFileExtensions": [
|
||||
"ts",
|
||||
"tsx",
|
||||
"js",
|
||||
"jsx",
|
||||
"json",
|
||||
"node"
|
||||
],
|
||||
"transformIgnorePatterns": [
|
||||
"node_modules/(?!react-native|react-navigation)/"
|
||||
],
|
||||
"setupFiles": [
|
||||
"./testenv.js"
|
||||
]
|
||||
}
|
||||
}
|