@fto-consult/expo-ui 1.1.2 → 1.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/babel.config.alias.js +12 -0
- package/babel.config.js +13 -4
- package/package.json +2 -3
- package/parent-package.js +2 -2
- package/src/App.js +2 -1
- package/src/auth/Login.js +26 -20
- package/src/components/AutoLink/index.js +4 -0
- package/src/components/Logo/Logo.js +15 -22
- package/src/components/Logo/defaultComponent.js +5 -0
- package/src/layouts/Screen/Screen.js +14 -169
- package/src/layouts/Screen/ScreenWithOrWithoutAuthContainer.js +179 -0
- package/src/layouts/Screen/ScreenWithoutAuthContainer.js +18 -0
- package/src/layouts/Screen/index.js +2 -1
- package/src/navigation/Drawer/index.js +5 -1
- package/src/screens/Auth/index.js +2 -3
- package/src/screens/index.js +3 -4
- package/src/screens/Auth/routes.js +0 -9
package/babel.config.alias.js
CHANGED
|
@@ -18,7 +18,12 @@ module.exports = (opts)=>{
|
|
|
18
18
|
r["$enavigation"] = path.resolve(expo,"navigation");
|
|
19
19
|
r["$escreens"] = path.resolve(expo,"screens");
|
|
20
20
|
r["$escreen"] = path.resolve(expo,"layouts/Screen");
|
|
21
|
+
r["$eassets"] = path.resolve(dir,"assets");
|
|
22
|
+
|
|
23
|
+
///pour personnaliser les écrans de l'application, il suffit de redefinir l'alis $screens, pointant vers le repertoire racine des écrans personnalisés
|
|
24
|
+
///cependant, ce repertoire doit contenir un fichier mainScreens.js qui contient la liste de tous les écrans de lapplicaiton
|
|
21
25
|
r["$screens"] = r["$screens"] || r["$escreens"];
|
|
26
|
+
|
|
22
27
|
r["$expo"] = r["$expo-ui"] = expo;
|
|
23
28
|
r["$epreloader"] = path.resolve(expo,"components/Preloader");
|
|
24
29
|
r["$eform"] = path.resolve(expo,"components","Form");
|
|
@@ -56,6 +61,13 @@ module.exports = (opts)=>{
|
|
|
56
61
|
if(r["$loginComponent"] == r["$cloginComponent"]){
|
|
57
62
|
r["$loginComponent"] = path.resolve(expo,"auth","Login");
|
|
58
63
|
}
|
|
64
|
+
|
|
65
|
+
/*** alias pour le composant logo par défaut : */
|
|
66
|
+
r["$elogoComponent"] = path.resolve(expo,"components","Logo","defaultComponent");
|
|
67
|
+
if(!r["$logoComponent"]){
|
|
68
|
+
r["$logoComponent"] = r["$elogoComponent"];
|
|
69
|
+
}
|
|
70
|
+
|
|
59
71
|
if(typeof opts.mutator =='function'){
|
|
60
72
|
opts.mutator(r);
|
|
61
73
|
}
|
package/babel.config.js
CHANGED
|
@@ -3,8 +3,19 @@ module.exports = function(api,opts) {
|
|
|
3
3
|
///les chemin vers la variable d'environnement, le chemin du fichier .env,@see : https://github.com/brysgo/babel-plugin-inline-dotenv
|
|
4
4
|
const environmentPath = opts.environmentPath || opts.envPath;
|
|
5
5
|
const path = require("path");
|
|
6
|
+
const fs = require("fs");
|
|
6
7
|
const dir = path.resolve(__dirname);
|
|
7
8
|
api.cache(true);
|
|
9
|
+
const inlineDovOptions = {};
|
|
10
|
+
if(environmentPath && typeof environmentPath =='string' && fs.existsSync(environmentPath)){
|
|
11
|
+
// File ".env" will be created or overwritten by default.
|
|
12
|
+
try {
|
|
13
|
+
fs.copyFileSync(environmentPath, path.resolve(dir,'.env'));
|
|
14
|
+
}
|
|
15
|
+
catch (e){
|
|
16
|
+
inlineDovOptions.path = environmentPath;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
8
19
|
const alias = require("./babel.config.alias")({base:dir,...opts,platform:"expo"});
|
|
9
20
|
return {
|
|
10
21
|
presets: [
|
|
@@ -12,12 +23,10 @@ module.exports = function(api,opts) {
|
|
|
12
23
|
["@babel/preset-react", {"runtime": "automatic"}],
|
|
13
24
|
],
|
|
14
25
|
plugins : [
|
|
26
|
+
["inline-dotenv",inlineDovOptions],
|
|
15
27
|
['babel-plugin-root-import', {"paths": alias}],
|
|
16
28
|
['react-native-reanimated/plugin'],
|
|
17
29
|
['transform-inline-environment-variables'],
|
|
18
|
-
|
|
19
|
-
...(environmentPath?{path:environmentPath} : {})
|
|
20
|
-
}]
|
|
21
|
-
]
|
|
30
|
+
],
|
|
22
31
|
};
|
|
23
32
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fto-consult/expo-ui",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.4",
|
|
4
4
|
"description": "Bibliothèque de composants UI Expo,react-native",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"@emotion/native": "^11.10.0",
|
|
61
61
|
"@expo/metro-config": "^0.4.0",
|
|
62
62
|
"@expo/webpack-config": "^0.17.2",
|
|
63
|
-
"@fto-consult/common": "^1.1.
|
|
63
|
+
"@fto-consult/common": "^1.1.24",
|
|
64
64
|
"@gorhom/portal": "^1.0.14",
|
|
65
65
|
"@react-native-async-storage/async-storage": "~1.17.3",
|
|
66
66
|
"@react-native-community/netinfo": "9.3.0",
|
|
@@ -70,7 +70,6 @@
|
|
|
70
70
|
"babel-plugin-inline-dotenv": "^1.7.0",
|
|
71
71
|
"babel-plugin-root-import": "^6.6.0",
|
|
72
72
|
"babel-plugin-transform-inline-environment-variables": "^0.4.4",
|
|
73
|
-
"dotenv": "^16.0.3",
|
|
74
73
|
"expo": "^46.0.15",
|
|
75
74
|
"expo-camera": "~12.3.0",
|
|
76
75
|
"expo-linking": "~3.2.2",
|
package/parent-package.js
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
// license that can be found in the LICENSE file.
|
|
4
4
|
|
|
5
5
|
/**** cette fonction a pour rôle de retourner le package parent à celui ci */
|
|
6
|
-
module.
|
|
7
|
-
const pathToParent = require("parent-package-json"); // Will return false if no parent exists
|
|
6
|
+
module.exports = ()=>{
|
|
7
|
+
const pathToParent = require("parent-package-json")(); // Will return false if no parent exists
|
|
8
8
|
if (pathToParent !== false) {
|
|
9
9
|
return pathToParent.path;
|
|
10
10
|
}
|
package/src/App.js
CHANGED
|
@@ -20,6 +20,7 @@ import {GestureHandlerRootView} from "react-native-gesture-handler";
|
|
|
20
20
|
import StatusBar from "$ecomponents/StatusBar";
|
|
21
21
|
import SimpleSelect from '$ecomponents/SimpleSelect';
|
|
22
22
|
import {Provider as AlertProvider} from '$ecomponents/Dialog/confirm/Alert';
|
|
23
|
+
import APP from "$app";
|
|
23
24
|
|
|
24
25
|
export default function getIndex(options){
|
|
25
26
|
const {App} = defaultObj(options);
|
|
@@ -35,7 +36,7 @@ export default function getIndex(options){
|
|
|
35
36
|
theme,
|
|
36
37
|
}),[theme]);
|
|
37
38
|
const child = <Index theme={theme}/>;
|
|
38
|
-
const children = typeof App =='function'? App({children:child}) : child;
|
|
39
|
+
const children = typeof App =='function'? App({children:child,APP}) : child;
|
|
39
40
|
return (
|
|
40
41
|
<GestureHandlerRootView style={{ flex: 1 }}>
|
|
41
42
|
<PaperProvider theme={theme}>
|
package/src/auth/Login.js
CHANGED
|
@@ -15,10 +15,12 @@ import View from "$ecomponents/View";
|
|
|
15
15
|
import Avatar from "$ecomponents/Avatar";
|
|
16
16
|
import Surface from "$ecomponents/Surface";
|
|
17
17
|
import {Provider as DialogProvider} from "$ecomponents/Dialog";
|
|
18
|
-
import
|
|
18
|
+
import ScreenWithoutAuthContainer from "$escreen/ScreenWithoutAuthContainer";
|
|
19
19
|
import {getTitle} from "$escreens/Auth/utils";
|
|
20
20
|
import {isWeb} from "$cplatform";
|
|
21
|
+
|
|
21
22
|
import getLoginProps from "$getLoginProps";
|
|
23
|
+
const getProps = typeof getLoginProps =='function'? getLoginProps : x=>null;
|
|
22
24
|
|
|
23
25
|
const WIDTH = 400;
|
|
24
26
|
|
|
@@ -28,26 +30,27 @@ export default function LoginComponent(props){
|
|
|
28
30
|
testID = defaultStr(testID,"RN_Auth.LoginComponent");
|
|
29
31
|
formName = React.useRef(uniqid(defaultStr(formName,"login-formname"))).current;
|
|
30
32
|
const nextButtonRef = React.useRef(null);
|
|
33
|
+
const previousButtonRef = React.useRef(null);
|
|
31
34
|
const dialogProviderRef = React.useRef(null);
|
|
32
35
|
const backgroundColor = theme.colors.surface;
|
|
33
|
-
const Wrapper = withPortal ?
|
|
36
|
+
const Wrapper = withPortal ? ScreenWithoutAuthContainer : View;
|
|
37
|
+
const _getForm = x=> getForm(formName);
|
|
34
38
|
|
|
35
39
|
const auth = useAuth();
|
|
36
40
|
const notifyUser = (message)=> notify.error({message,position:'top'})
|
|
37
41
|
const [state,setState] = React.useState({
|
|
38
42
|
step : defaultNumber(step,1),
|
|
43
|
+
data : defaultObj(props.data),
|
|
39
44
|
});
|
|
40
|
-
const _getForm = x=> getForm(formName);
|
|
41
45
|
const getData = ()=>{
|
|
42
46
|
const form = _getForm();
|
|
43
47
|
if(form && form.getData){
|
|
44
|
-
return form.getData();
|
|
48
|
+
return extendObj({},state.data,form.getData());
|
|
45
49
|
}
|
|
46
50
|
return defaultObj(props.data);
|
|
47
51
|
}
|
|
48
52
|
const goToFirstStep = ()=>{
|
|
49
|
-
|
|
50
|
-
setState({...state,step:1,data});
|
|
53
|
+
setState({...state,step:1,data:getData()});
|
|
51
54
|
}
|
|
52
55
|
const focusField = (fieldName)=>{
|
|
53
56
|
const form = _getForm();
|
|
@@ -71,14 +74,15 @@ export default function LoginComponent(props){
|
|
|
71
74
|
},1000)
|
|
72
75
|
}
|
|
73
76
|
},[withPortal])
|
|
74
|
-
const
|
|
75
|
-
const {header,children,data:loginData,validate,keyboardEvents,onSuccess:onLoginSuccess,canSubmit:canSubmitForm,onStepChange,...loginProps} = defaultObj(getProps({
|
|
77
|
+
const {header,children,data:loginData,canGoToNext,keyboardEvents,onSuccess:onLoginSuccess,canSubmit:canSubmitForm,onStepChange,...loginProps} = defaultObj(getProps({
|
|
76
78
|
...state,
|
|
77
|
-
data : getData(),
|
|
78
79
|
state,
|
|
80
|
+
getForm,
|
|
81
|
+
getData,
|
|
82
|
+
focusField,
|
|
79
83
|
formName,
|
|
80
|
-
setState,
|
|
81
84
|
nextButtonRef,
|
|
85
|
+
previousButtonRef,
|
|
82
86
|
}));
|
|
83
87
|
React.useEffect(()=>{
|
|
84
88
|
Preloader.closeAll();
|
|
@@ -87,7 +91,7 @@ export default function LoginComponent(props){
|
|
|
87
91
|
React.useEffect(()=>{
|
|
88
92
|
/*** lorsque le state du composant change */
|
|
89
93
|
if(typeof onStepChange =='function'){
|
|
90
|
-
return onStepChange({...state,previousStep:prevStep,focusField,nextButtonRef
|
|
94
|
+
return onStepChange({...state,previousStep:prevStep,focusField,nextButtonRef})
|
|
91
95
|
}
|
|
92
96
|
},[state.step]);
|
|
93
97
|
/****la fonction à utiliser pour vérifier si l'on peut envoyer les données pour connextion
|
|
@@ -96,16 +100,18 @@ export default function LoginComponent(props){
|
|
|
96
100
|
const canSubmit = typeof canSubmitForm =='function'? canSubmitForm : ({step})=>step >= 2;
|
|
97
101
|
const goToNext = ()=>{
|
|
98
102
|
let step = state.step;
|
|
99
|
-
|
|
100
|
-
data.code = defaultStr(data.code, state.code);
|
|
103
|
+
const data = getData();
|
|
101
104
|
const form = _getForm();
|
|
102
105
|
if(!form){
|
|
103
106
|
notifyUser("Impossible de valider le formulaire car celui-ci semble invalide")
|
|
104
107
|
return;
|
|
105
108
|
}
|
|
106
|
-
const args = {data,form,step,nextButtonRef};
|
|
107
|
-
if(
|
|
108
|
-
|
|
109
|
+
const args = {data,form,state,step,nextButtonRef,previousButtonRef};
|
|
110
|
+
if(nextButtonRef.current && nextButtonRef.current.isDisabled()){
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
if(typeof canGoToNext =='function'){
|
|
114
|
+
const s = canGoToNext(args);
|
|
109
115
|
if(s === false) return;
|
|
110
116
|
if(isNonNullString(s)){
|
|
111
117
|
notifyUser(s);
|
|
@@ -117,7 +123,7 @@ export default function LoginComponent(props){
|
|
|
117
123
|
return auth.signIn(data).then((a)=>{
|
|
118
124
|
if(typeof onLoginSuccess =='function' && onLoginSuccess(a)=== false) return;
|
|
119
125
|
if(isFunction(onSuccess)){
|
|
120
|
-
onSuccess(
|
|
126
|
+
onSuccess(data);
|
|
121
127
|
} else {
|
|
122
128
|
navigate("Home");
|
|
123
129
|
}
|
|
@@ -125,7 +131,7 @@ export default function LoginComponent(props){
|
|
|
125
131
|
Preloader.close();
|
|
126
132
|
})
|
|
127
133
|
} else {
|
|
128
|
-
setState({...state,step:step+1
|
|
134
|
+
setState({...state,step:step+1,data})
|
|
129
135
|
}
|
|
130
136
|
}
|
|
131
137
|
|
|
@@ -155,7 +161,7 @@ export default function LoginComponent(props){
|
|
|
155
161
|
}
|
|
156
162
|
}
|
|
157
163
|
}}
|
|
158
|
-
data = {extendObj(
|
|
164
|
+
data = {extendObj(state.data,loginData)}
|
|
159
165
|
>
|
|
160
166
|
<View testID={testID+"_ButtonsContainer"} style={[styles.buttonWrapper]}>
|
|
161
167
|
<Button
|
|
@@ -167,12 +173,12 @@ export default function LoginComponent(props){
|
|
|
167
173
|
onPress = {goToNext}
|
|
168
174
|
icon = {state.step == 1? 'arrow-right':'login'}
|
|
169
175
|
surface
|
|
170
|
-
disabled = {!isNonNullString(state.code)}
|
|
171
176
|
>
|
|
172
177
|
{state.step == 1? 'Suivant' : 'Connexion' }
|
|
173
178
|
</Button>
|
|
174
179
|
{state.step>=2 ? <Button
|
|
175
180
|
onPress = {goToFirstStep}
|
|
181
|
+
ref = {previousButtonRef}
|
|
176
182
|
mode = "contained"
|
|
177
183
|
rounded
|
|
178
184
|
raised
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
// Copyright 2022 @fto-consult/Boris Fouomene. All rights reserved.
|
|
2
|
+
// Use of this source code is governed by a BSD-style
|
|
3
|
+
// license that can be found in the LICENSE file.
|
|
4
|
+
|
|
1
5
|
import * as Linking from 'expo-linking';
|
|
2
6
|
import { Pressable } from 'react-native';
|
|
3
7
|
import {isValidUrl,isValidEmail,defaultStr,isSms} from "$utils";
|
|
@@ -3,17 +3,18 @@ import { Component } from "react";
|
|
|
3
3
|
import {isNativeMobile} from "$cplatform";
|
|
4
4
|
import {Image} from "react-native";
|
|
5
5
|
import View from "$ecomponents/View";
|
|
6
|
-
import
|
|
6
|
+
import React from "$react";
|
|
7
7
|
import theme,{remToPixel,Colors,flattenStyle} from '$theme';
|
|
8
8
|
import {StyleSheet} from "react-native";
|
|
9
9
|
import source from "$assets/logo.png";
|
|
10
10
|
import {defaultStr} from "$utils";
|
|
11
|
+
import LogoComponent from "$logoComponent";
|
|
11
12
|
|
|
12
13
|
export const height = 150;
|
|
13
14
|
export const width = undefined;//300;
|
|
14
15
|
export default class Logo extends Component {
|
|
15
16
|
render(props){
|
|
16
|
-
let {icon,color,style,testID,text} = this.props;
|
|
17
|
+
let {icon,color,style,testID,logo,text} = this.props;
|
|
17
18
|
testID = defaultStr(testID,"RN_LogoComponent");
|
|
18
19
|
const styles = getStyle(style,color);
|
|
19
20
|
return <View testID={testID} style={styles.container}>
|
|
@@ -28,12 +29,7 @@ export default class Logo extends Component {
|
|
|
28
29
|
)}
|
|
29
30
|
/>}
|
|
30
31
|
</View> : null}
|
|
31
|
-
{text !== false ? <
|
|
32
|
-
<Label style={styles.firstText}>XPose</Label>
|
|
33
|
-
<Label style={styles.secondText}>F</Label>
|
|
34
|
-
<Label style={styles.thirdText}>T</Label>
|
|
35
|
-
<Label style={styles.fourthText}>C</Label>
|
|
36
|
-
</View> : null}
|
|
32
|
+
{text !== false && logo !== false ? (React.isValidElement(LogoComponent)? LogoComponent : React.isComponent(LogoComponent)? <LogoComponent {...props} style={styles.logoContent} testID={testID+"_Content"} styles={styles}/> : null) : null}
|
|
37
33
|
</View>
|
|
38
34
|
}
|
|
39
35
|
|
|
@@ -44,10 +40,9 @@ const getStyle = (style,color)=>{
|
|
|
44
40
|
return {
|
|
45
41
|
...styles,
|
|
46
42
|
container : flattenStyle([styles.container,cColor,style]),
|
|
47
|
-
firstText : flattenStyle([styles.
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
fourthText : flattenStyle([styles.text,cColor])
|
|
43
|
+
firstText : flattenStyle([styles.medium,cColor]),
|
|
44
|
+
large : flattenStyle([styles.medium,styles.large,cColor]),
|
|
45
|
+
small : flattenStyle([styles.medium,cColor,styles.small]),
|
|
51
46
|
};
|
|
52
47
|
}
|
|
53
48
|
|
|
@@ -73,25 +68,23 @@ const styles = StyleSheet.create({
|
|
|
73
68
|
},
|
|
74
69
|
logoContent : {
|
|
75
70
|
position:"relative",
|
|
76
|
-
//width : 160,
|
|
77
|
-
//flex : 2,
|
|
78
71
|
flexDirection : "row",
|
|
79
72
|
alignItems : "center",
|
|
80
73
|
justifyContent : "flex-start"
|
|
81
74
|
},
|
|
82
|
-
|
|
83
|
-
fontSize : remToPixel(5),
|
|
84
|
-
alignItems : "flex-start",
|
|
85
|
-
justifyContent : "center",
|
|
86
|
-
marginTop: 0//isNativeMobile() ? -5 : 0
|
|
87
|
-
},
|
|
88
|
-
thirdText : {
|
|
75
|
+
small : {
|
|
89
76
|
fontSize:remToPixel(2.5),
|
|
90
77
|
marginLeft:isNativeMobile()? -25 : -20
|
|
91
78
|
},
|
|
92
|
-
|
|
79
|
+
medium : {
|
|
93
80
|
fontSize:remToPixel(3),
|
|
94
81
|
},
|
|
82
|
+
large : {
|
|
83
|
+
fontSize : remToPixel(5),
|
|
84
|
+
alignItems : "flex-start",
|
|
85
|
+
justifyContent : "center",
|
|
86
|
+
marginTop: 0
|
|
87
|
+
},
|
|
95
88
|
})
|
|
96
89
|
|
|
97
90
|
Logo.height = height;
|
|
@@ -1,172 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import PropTypes from "prop-types";
|
|
5
|
-
import {defaultObj,defaultStr,defaultNumber,defaultBool} from "$utils";
|
|
6
|
-
import ScrollView from '$ecomponents/ScrollView';
|
|
7
|
-
import View from "$ecomponents/View";
|
|
8
|
-
import { useNavigation,getScreenProps } from '$cnavigation';
|
|
9
|
-
import Fab from "$elayouts/Fab";
|
|
10
|
-
import APP from "$capp";
|
|
11
|
-
import AppBar,{createAppBarRef} from "$elayouts/AppBar";
|
|
12
|
-
import ErrorBoundary from "$ecomponents/ErrorBoundary";
|
|
13
|
-
import Portal from "$ecomponents/Portal";
|
|
14
|
-
import theme from "$theme";
|
|
15
|
-
import StatusBar from "$ecomponents/StatusBar";
|
|
16
|
-
import Auth from "$cauth";
|
|
1
|
+
// Copyright 2022 @fto-consult/Boris Fouomene. All rights reserved.
|
|
2
|
+
// Use of this source code is governed by a BSD-style
|
|
3
|
+
// license that can be found in the LICENSE file.
|
|
17
4
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
if(!titleStr){
|
|
21
|
-
titleStr = APP.getName();
|
|
22
|
-
}
|
|
23
|
-
const dbLabel = "";
|
|
24
|
-
if(!titleStr.toLowerCase().contains(dbLabel.toLowerCase())){
|
|
25
|
-
titleStr += " ["+dbLabel+"]";
|
|
26
|
-
}
|
|
27
|
-
if(returnStr) return titleStr;
|
|
28
|
-
return typeof nTitle =='string' ? titleStr : nTitle;
|
|
29
|
-
}
|
|
5
|
+
import Container from "$cauth/Container";
|
|
6
|
+
import ScreenWithOrWithoutAuthContainer from "./ScreenWithOrWithoutAuthContainer";
|
|
30
7
|
|
|
31
|
-
export default function
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
appBarProps,
|
|
41
|
-
authProps,
|
|
42
|
-
elevation,
|
|
43
|
-
withFab,
|
|
44
|
-
appBar,
|
|
45
|
-
authRequired,
|
|
46
|
-
withDrawer,
|
|
47
|
-
allowDrawer,
|
|
48
|
-
title,
|
|
49
|
-
subtitle,
|
|
50
|
-
modal,
|
|
51
|
-
fabProps,
|
|
52
|
-
screenName,
|
|
53
|
-
containerProps,
|
|
54
|
-
testID,
|
|
55
|
-
...rest
|
|
56
|
-
} = getScreenProps(props);
|
|
57
|
-
const insets = useSafeAreaInsets();
|
|
58
|
-
testID = defaultStr(testID,"RN_MainScreenLayoutComponent")
|
|
59
|
-
containerProps = defaultObj(containerProps);
|
|
60
|
-
const backgroundColor = theme.colors.background;
|
|
61
|
-
const containerStyle = [
|
|
62
|
-
styles.container,
|
|
63
|
-
{
|
|
64
|
-
backgroundColor,
|
|
65
|
-
paddingBottom: insets.bottom,
|
|
66
|
-
paddingLeft: insets.left,
|
|
67
|
-
paddingRight: insets.right,
|
|
68
|
-
},
|
|
69
|
-
];
|
|
70
|
-
options = defaultObj(options);
|
|
71
|
-
appBarProps = defaultObj(appBarProps)
|
|
72
|
-
title = defaultVal(appBarProps.title,options.title,title);
|
|
73
|
-
subtitle = defaultVal(appBarProps.subtitle,options.subtitle,subtitle);
|
|
74
|
-
const appBarRef = createAppBarRef();
|
|
75
|
-
const navigation = useNavigation();
|
|
76
|
-
authProps = Object.assign({},authProps),
|
|
77
|
-
fabProps = defaultObj(fabProps);
|
|
78
|
-
authRequired = defaultBool(authProps.required,authRequired,false);
|
|
79
|
-
withDrawer = typeof withDrawer =='boolean'? withDrawer : authRequired;
|
|
80
|
-
if(allowDrawer === false){
|
|
81
|
-
withDrawer = false;
|
|
82
|
-
}
|
|
83
|
-
if(authRequired === false){
|
|
84
|
-
withFab = false;
|
|
85
|
-
}
|
|
86
|
-
if(typeof withFab !=='boolean'){
|
|
87
|
-
withFab = withDrawer;
|
|
88
|
-
}
|
|
89
|
-
React.useEffect(() => {
|
|
90
|
-
if((title||subtitle) && navigation && navigation.setOptions){
|
|
91
|
-
const appName = APP.getName().toUpperCase();
|
|
92
|
-
subtitle = React.getTextContent(subtitle);
|
|
93
|
-
let screenTitle = getDefaultTitle(title,true);
|
|
94
|
-
if(subtitle){
|
|
95
|
-
screenTitle += " | "+subtitle;
|
|
96
|
-
}
|
|
97
|
-
if(!screenTitle.toUpperCase().contains(appName)){
|
|
98
|
-
screenTitle+=" | "+appName;
|
|
99
|
-
}
|
|
100
|
-
navigation.setOptions({
|
|
101
|
-
...options,
|
|
102
|
-
appBarProps:{...options.appBarProps,...appBarProps,title,subtitle},
|
|
103
|
-
subtitle :subtitle,
|
|
104
|
-
title : screenTitle,
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
}, [title,subtitle]);
|
|
108
|
-
const Wrapper = modal ? Portal : React.Fragment;
|
|
109
|
-
const fab = withFab !== false ? <Fab
|
|
110
|
-
{...fabProps}
|
|
111
|
-
screenName={screenName}
|
|
112
|
-
/> : null;
|
|
113
|
-
return <Wrapper>
|
|
114
|
-
<Auth.Container {...authProps} required ={authRequired}>
|
|
115
|
-
{withStatusBar !== false ? <StatusBar/> : null}
|
|
116
|
-
<ErrorBoundary testID={testID+"_ScreenLayoutErrorBoundary"}>
|
|
117
|
-
<View testID={testID} {...containerProps} style={[styles.container,{backgroundColor},modal && styles.modal]}>
|
|
118
|
-
{appBar === false ? null : React.isValidElement(appBar)? state.AppBar : <AppBar testID={testID+'_AppBar'} {...appBarProps} backAction = {defaultVal(appBarProps.backAction,backAction)} elevation={defaultNumber(appBarProps.elevation,elevation)} withDrawer={withDrawer} options={options} ref={appBarRef} title={title} subtitle={subtitle}/>}
|
|
119
|
-
{withScrollView !== false ? (
|
|
120
|
-
<ScrollView
|
|
121
|
-
testID = {testID+'_ScreenContentScrollView'}
|
|
122
|
-
{...rest}
|
|
123
|
-
contentContainerStyle={[contentContainerStyle]}
|
|
124
|
-
style={[containerStyle,styles.container, style]}
|
|
125
|
-
>
|
|
126
|
-
{children}
|
|
127
|
-
{fab}
|
|
128
|
-
</ScrollView>
|
|
129
|
-
) : (
|
|
130
|
-
<View testID={testID+'_ScreenContent'} {...rest} style={[containerStyle,styles.wrapper,styles.container, style]}>
|
|
131
|
-
{children}
|
|
132
|
-
{fab}
|
|
133
|
-
</View>
|
|
134
|
-
)}
|
|
135
|
-
</View>
|
|
136
|
-
</ErrorBoundary>
|
|
137
|
-
</Auth.Container>
|
|
138
|
-
</Wrapper>
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
const styles = StyleSheet.create({
|
|
142
|
-
container: {
|
|
143
|
-
flex: 1,
|
|
144
|
-
},
|
|
145
|
-
wrapper : {
|
|
146
|
-
flexDirection:'column',
|
|
147
|
-
/*flex : 1,
|
|
148
|
-
flexGrow : 1,
|
|
149
|
-
alignItems:'center'*/
|
|
150
|
-
},
|
|
151
|
-
modal : {
|
|
152
|
-
...StyleSheet.absoluteFillObject,
|
|
153
|
-
top : 0,
|
|
154
|
-
left:0,
|
|
155
|
-
flex:1,
|
|
156
|
-
width : '100%',
|
|
157
|
-
height : '100%'
|
|
158
|
-
}
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
MainScreenLayoutComponent.propTypes = {
|
|
162
|
-
children: PropTypes.any,
|
|
163
|
-
withScrollView : PropTypes.bool,
|
|
164
|
-
style:PropTypes.object,
|
|
165
|
-
appBarProps : PropTypes.object,
|
|
166
|
-
elevation : PropTypes.number,
|
|
167
|
-
//appBar : PropTypes.bool,
|
|
168
|
-
contentContainerStyle : PropTypes.object,
|
|
169
|
-
withFab : PropTypes.bool,
|
|
170
|
-
withDrawer : PropTypes.bool,//si l'on doit afficher un drawer dans le contenu
|
|
171
|
-
fabProps : PropTypes.object,
|
|
8
|
+
export default function MainScreenComponent(props){
|
|
9
|
+
return <ScreenWithOrWithoutAuthContainer
|
|
10
|
+
{...props}
|
|
11
|
+
renderChildren = {({containerProps,children})=>{
|
|
12
|
+
return <Container {...containerProps}>
|
|
13
|
+
{children}
|
|
14
|
+
</Container>
|
|
15
|
+
}}
|
|
16
|
+
/>
|
|
172
17
|
}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import React from '$react';
|
|
2
|
+
import {StyleSheet} from 'react-native';
|
|
3
|
+
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
4
|
+
import PropTypes from "prop-types";
|
|
5
|
+
import {defaultObj,defaultStr,defaultNumber,defaultBool} from "$utils";
|
|
6
|
+
import ScrollView from '$ecomponents/ScrollView';
|
|
7
|
+
import View from "$ecomponents/View";
|
|
8
|
+
import { useNavigation,getScreenProps } from '$cnavigation';
|
|
9
|
+
import Fab from "$elayouts/Fab";
|
|
10
|
+
import APP from "$capp";
|
|
11
|
+
import AppBar,{createAppBarRef} from "$elayouts/AppBar";
|
|
12
|
+
import ErrorBoundary from "$ecomponents/ErrorBoundary";
|
|
13
|
+
import Portal from "$ecomponents/Portal";
|
|
14
|
+
import theme from "$theme";
|
|
15
|
+
import StatusBar from "$ecomponents/StatusBar";
|
|
16
|
+
|
|
17
|
+
const getDefaultTitle = (nTitle,returnStr)=>{
|
|
18
|
+
let titleStr = React.getTextContent(nTitle);
|
|
19
|
+
if(!titleStr){
|
|
20
|
+
titleStr = APP.getName();
|
|
21
|
+
}
|
|
22
|
+
const dbLabel = "";
|
|
23
|
+
if(!titleStr.toLowerCase().contains(dbLabel.toLowerCase())){
|
|
24
|
+
titleStr += " ["+dbLabel+"]";
|
|
25
|
+
}
|
|
26
|
+
if(returnStr) return titleStr;
|
|
27
|
+
return typeof nTitle =='string' ? titleStr : nTitle;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export default function MainScreenScreenWithOrWithoutAuthContainer(props) {
|
|
31
|
+
let {
|
|
32
|
+
children,
|
|
33
|
+
withScrollView = false,
|
|
34
|
+
withStatusBar = true,
|
|
35
|
+
style,
|
|
36
|
+
contentContainerStyle,
|
|
37
|
+
options,
|
|
38
|
+
backAction,
|
|
39
|
+
appBarProps,
|
|
40
|
+
authProps,
|
|
41
|
+
elevation,
|
|
42
|
+
withFab,
|
|
43
|
+
appBar,
|
|
44
|
+
authRequired,
|
|
45
|
+
withDrawer,
|
|
46
|
+
allowDrawer,
|
|
47
|
+
title,
|
|
48
|
+
subtitle,
|
|
49
|
+
modal,
|
|
50
|
+
fabProps,
|
|
51
|
+
screenName,
|
|
52
|
+
containerProps,
|
|
53
|
+
testID,
|
|
54
|
+
renderChildren,
|
|
55
|
+
...rest
|
|
56
|
+
} = getScreenProps(props);
|
|
57
|
+
const insets = useSafeAreaInsets();
|
|
58
|
+
testID = defaultStr(testID,"RN_MainScreenScreenWithOrWithoutAuthContainer")
|
|
59
|
+
containerProps = defaultObj(containerProps);
|
|
60
|
+
const backgroundColor = theme.colors.background;
|
|
61
|
+
const containerStyle = [
|
|
62
|
+
styles.container,
|
|
63
|
+
{
|
|
64
|
+
backgroundColor,
|
|
65
|
+
paddingBottom: insets.bottom,
|
|
66
|
+
paddingLeft: insets.left,
|
|
67
|
+
paddingRight: insets.right,
|
|
68
|
+
},
|
|
69
|
+
];
|
|
70
|
+
options = defaultObj(options);
|
|
71
|
+
appBarProps = defaultObj(appBarProps)
|
|
72
|
+
title = defaultVal(appBarProps.title,options.title,title);
|
|
73
|
+
subtitle = defaultVal(appBarProps.subtitle,options.subtitle,subtitle);
|
|
74
|
+
const appBarRef = createAppBarRef();
|
|
75
|
+
const navigation = useNavigation();
|
|
76
|
+
authProps = Object.assign({},authProps),
|
|
77
|
+
fabProps = defaultObj(fabProps);
|
|
78
|
+
authRequired = defaultBool(authProps.required,authRequired,false);
|
|
79
|
+
withDrawer = typeof withDrawer =='boolean'? withDrawer : authRequired;
|
|
80
|
+
if(allowDrawer === false){
|
|
81
|
+
withDrawer = false;
|
|
82
|
+
}
|
|
83
|
+
if(authRequired === false){
|
|
84
|
+
withFab = false;
|
|
85
|
+
}
|
|
86
|
+
if(typeof withFab !=='boolean'){
|
|
87
|
+
withFab = withDrawer;
|
|
88
|
+
}
|
|
89
|
+
React.useEffect(() => {
|
|
90
|
+
if((title||subtitle) && navigation && navigation.setOptions){
|
|
91
|
+
const appName = APP.getName().toUpperCase();
|
|
92
|
+
subtitle = React.getTextContent(subtitle);
|
|
93
|
+
let screenTitle = getDefaultTitle(title,true);
|
|
94
|
+
if(subtitle){
|
|
95
|
+
screenTitle += " | "+subtitle;
|
|
96
|
+
}
|
|
97
|
+
if(!screenTitle.toUpperCase().contains(appName)){
|
|
98
|
+
screenTitle+=" | "+appName;
|
|
99
|
+
}
|
|
100
|
+
navigation.setOptions({
|
|
101
|
+
...options,
|
|
102
|
+
appBarProps:{...options.appBarProps,...appBarProps,title,subtitle},
|
|
103
|
+
subtitle :subtitle,
|
|
104
|
+
title : screenTitle,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
}, [title,subtitle]);
|
|
108
|
+
const Wrapper = modal ? Portal : React.Fragment;
|
|
109
|
+
const fab = withFab !== false ? <Fab
|
|
110
|
+
{...fabProps}
|
|
111
|
+
screenName={screenName}
|
|
112
|
+
/> : null;
|
|
113
|
+
const child = <>
|
|
114
|
+
{withStatusBar !== false ? <StatusBar/> : null}
|
|
115
|
+
<ErrorBoundary testID={testID+"_ScreenLayoutErrorBoundary"}>
|
|
116
|
+
<View testID={testID} {...containerProps} style={[styles.container,{backgroundColor},modal && styles.modal]}>
|
|
117
|
+
{appBar === false ? null : React.isValidElement(appBar)? state.AppBar : <AppBar testID={testID+'_AppBar'} {...appBarProps} backAction = {defaultVal(appBarProps.backAction,backAction)} elevation={defaultNumber(appBarProps.elevation,elevation)} withDrawer={withDrawer} options={options} ref={appBarRef} title={title} subtitle={subtitle}/>}
|
|
118
|
+
{withScrollView !== false ? (
|
|
119
|
+
<ScrollView
|
|
120
|
+
testID = {testID+'_ScreenContentScrollView'}
|
|
121
|
+
{...rest}
|
|
122
|
+
contentContainerStyle={[contentContainerStyle]}
|
|
123
|
+
style={[containerStyle,styles.container, style]}
|
|
124
|
+
>
|
|
125
|
+
{children}
|
|
126
|
+
{fab}
|
|
127
|
+
</ScrollView>
|
|
128
|
+
) : (
|
|
129
|
+
<View testID={testID+'_ScreenContent'} {...rest} style={[containerStyle,styles.wrapper,styles.container, style]}>
|
|
130
|
+
{children}
|
|
131
|
+
{fab}
|
|
132
|
+
</View>
|
|
133
|
+
)}
|
|
134
|
+
</View>
|
|
135
|
+
</ErrorBoundary>
|
|
136
|
+
</>
|
|
137
|
+
return <Wrapper>
|
|
138
|
+
{renderChildren({
|
|
139
|
+
containerProps : {
|
|
140
|
+
...authProps,
|
|
141
|
+
required : authRequired,
|
|
142
|
+
},
|
|
143
|
+
children : child,
|
|
144
|
+
})}
|
|
145
|
+
</Wrapper>
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const styles = StyleSheet.create({
|
|
149
|
+
container: {
|
|
150
|
+
flex: 1,
|
|
151
|
+
},
|
|
152
|
+
wrapper : {
|
|
153
|
+
flexDirection:'column',
|
|
154
|
+
/*flex : 1,
|
|
155
|
+
flexGrow : 1,
|
|
156
|
+
alignItems:'center'*/
|
|
157
|
+
},
|
|
158
|
+
modal : {
|
|
159
|
+
...StyleSheet.absoluteFillObject,
|
|
160
|
+
top : 0,
|
|
161
|
+
left:0,
|
|
162
|
+
flex:1,
|
|
163
|
+
width : '100%',
|
|
164
|
+
height : '100%'
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
MainScreenScreenWithOrWithoutAuthContainer.propTypes = {
|
|
169
|
+
children: PropTypes.any,
|
|
170
|
+
withScrollView : PropTypes.bool,
|
|
171
|
+
style:PropTypes.object,
|
|
172
|
+
appBarProps : PropTypes.object,
|
|
173
|
+
elevation : PropTypes.number,
|
|
174
|
+
//appBar : PropTypes.bool,
|
|
175
|
+
contentContainerStyle : PropTypes.object,
|
|
176
|
+
withFab : PropTypes.bool,
|
|
177
|
+
withDrawer : PropTypes.bool,//si l'on doit afficher un drawer dans le contenu
|
|
178
|
+
fabProps : PropTypes.object,
|
|
179
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// Copyright 2022 @fto-consult/Boris Fouomene. All rights reserved.
|
|
2
|
+
// Use of this source code is governed by a BSD-style
|
|
3
|
+
// license that can be found in the LICENSE file.
|
|
4
|
+
|
|
5
|
+
/*** afin d'éviter les redondances cycliques avec le module $loginComponent, ce composant doit être utiliser pour
|
|
6
|
+
* le rendu de tous les composants implémentés définis dans le fichier $loginComponent car ne necessite pas de test sur
|
|
7
|
+
le fait que l'utilisateur soit connecté où pas
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import ScreenWithOrWithoutAuthContainer from "./ScreenWithOrWithoutAuthContainer";
|
|
11
|
+
export default function ScreenWithoutAuthContainer(props){
|
|
12
|
+
return <ScreenWithOrWithoutAuthContainer
|
|
13
|
+
{...props}
|
|
14
|
+
renderChildren = {({children})=>{
|
|
15
|
+
return children
|
|
16
|
+
}}
|
|
17
|
+
/>
|
|
18
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import Screen from "./Screen";
|
|
2
|
+
import ScreenWithoutAuthContainer from "./ScreenWithoutAuthContainer";
|
|
2
3
|
import FormData from "./FormData";
|
|
3
4
|
import List from "./FormData/List";
|
|
4
5
|
|
|
@@ -8,4 +9,4 @@ Screen.List = List;
|
|
|
8
9
|
|
|
9
10
|
export default Screen;
|
|
10
11
|
|
|
11
|
-
export {FormData,List};
|
|
12
|
+
export {FormData,List,ScreenWithoutAuthContainer};
|
|
@@ -47,7 +47,11 @@ const DrawerNavigator = React.forwardRef(({content,children,state,...props},ref)
|
|
|
47
47
|
navigate("Home");
|
|
48
48
|
},[isLoggedIn])
|
|
49
49
|
if(!isLoggedIn) {
|
|
50
|
-
return <Login withPortal
|
|
50
|
+
return <Login withPortal
|
|
51
|
+
onSuccess = {(data)=>{
|
|
52
|
+
setIsLoggedIn(true);
|
|
53
|
+
}}
|
|
54
|
+
/>
|
|
51
55
|
}
|
|
52
56
|
return <Drawer
|
|
53
57
|
isItemActive = {isItemActive}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
|
|
2
|
-
import {SIGN_IN} from "
|
|
2
|
+
import {SIGN_IN} from "$cauth/routes"
|
|
3
3
|
import Screen from "$escreen";
|
|
4
|
-
import {GROUP_NAMES} from "$escreens/utils";
|
|
5
4
|
import Login from "$eauth/Login";
|
|
6
5
|
import {getScreenProps} from "$cnavigation";
|
|
7
6
|
import {getTitle} from "./utils";
|
|
@@ -24,7 +23,7 @@ function AuthSignInScreen(_props){
|
|
|
24
23
|
}
|
|
25
24
|
|
|
26
25
|
AuthSignInScreen.screenName = SIGN_IN;
|
|
27
|
-
AuthSignInScreen.
|
|
26
|
+
AuthSignInScreen.authRequired = false;
|
|
28
27
|
AuthSignInScreen.modal = true;
|
|
29
28
|
AuthSignInScreen.allowDrawer = false;
|
|
30
29
|
|
package/src/screens/index.js
CHANGED
|
@@ -12,7 +12,6 @@ export * from "./utils";
|
|
|
12
12
|
export const SCREEN_OPTIONS = {};
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
|
|
16
15
|
export const handleScreen = ({Screen,Factory,ModalFactory,result,useTheme,filter,index})=>{
|
|
17
16
|
result = defaultObj(result);
|
|
18
17
|
result.screens = defaultObj(result.screens);
|
|
@@ -41,9 +40,9 @@ export const handleScreen = ({Screen,Factory,ModalFactory,result,useTheme,filter
|
|
|
41
40
|
return null;
|
|
42
41
|
}
|
|
43
42
|
///le groupe d'écran par défaut
|
|
44
|
-
let groupName =
|
|
43
|
+
let groupName = Screen.Start ||Screen.start ? GROUP_NAMES.START : authRequired === false ? GROUP_NAMES.PUBLIC : GROUP_NAMES.PRIVATE;
|
|
45
44
|
if(!GROUP_NAMES[groupName]){
|
|
46
|
-
groupName = GROUP_NAMES.
|
|
45
|
+
groupName = GROUP_NAMES.PRIVATE;
|
|
47
46
|
}
|
|
48
47
|
if(!authRequired){
|
|
49
48
|
groupName = groupName || GROUP_NAMES.PUBLIC;
|
|
@@ -179,7 +178,7 @@ export const handleContent = ({screens,hasGetStarted,state,Factory})=>{
|
|
|
179
178
|
Object.map(screens,(screens,groupName)=>{
|
|
180
179
|
if(!Array.isArray(screens)) return null;
|
|
181
180
|
if(hasGetStarted === false){
|
|
182
|
-
if(groupName == GROUP_NAMES.
|
|
181
|
+
if(groupName == GROUP_NAMES.START){
|
|
183
182
|
content.push(<Factory.Group key={groupName}>
|
|
184
183
|
{screens}
|
|
185
184
|
</Factory.Group>)
|