@fto-consult/expo-ui 8.12.7 → 8.13.1
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/package.json
CHANGED
package/src/AppEntry/index.js
CHANGED
@@ -15,6 +15,7 @@ import {set as setSession,get as getSession} from "$session";
|
|
15
15
|
import { showConfirm } from "$ecomponents/Dialog";
|
16
16
|
import {close as closePreloader, isVisible as isPreloaderVisible} from "$epreloader";
|
17
17
|
import SplashScreen from "$ecomponents/SplashScreen";
|
18
|
+
import {useAppComponent} from "$econtext/hooks";
|
18
19
|
import {decycle} from "$cutils/json";
|
19
20
|
import { setIsInitialized} from "$capp/utils";
|
20
21
|
import {isObj,defaultObj,defaultStr} from "$cutils";
|
@@ -60,6 +61,7 @@ const NAVIGATION_PERSISTENCE_KEY = 'NAVIGATION_STATE';
|
|
60
61
|
*/
|
61
62
|
function App({init:initApp,initialRouteName:appInitialRouteName,children}) {
|
62
63
|
AppStateService.init();
|
64
|
+
const SplashScreenComponent = useAppComponent("SplashScreen");
|
63
65
|
const {FontsIconsFilter,beforeExit,AppWrapper,preferences:appPreferences,navigation,getStartedRouteName,components:{MainProvider}} = useContext();
|
64
66
|
const {containerProps} = navigation;
|
65
67
|
const [initialState, setInitialState] = React.useState(undefined);
|
@@ -284,7 +286,7 @@ function App({init:initApp,initialRouteName:appInitialRouteName,children}) {
|
|
284
286
|
<DropdownAlert ref={notificationRef}/>
|
285
287
|
<ErrorBoundary>
|
286
288
|
<StatusBar/>
|
287
|
-
<SplashScreen isLoaded={isLoaded}>
|
289
|
+
<SplashScreen Component={SplashScreenComponent} isLoaded={isLoaded}>
|
288
290
|
<PreferencesContext.Provider value={preferences}>
|
289
291
|
{React.isValidElement(content) && content || child}
|
290
292
|
</PreferencesContext.Provider>
|
@@ -0,0 +1,75 @@
|
|
1
|
+
import { StyleSheet, Dimensions } from "react-native"
|
2
|
+
|
3
|
+
const { width, height } = Dimensions.get("screen")
|
4
|
+
|
5
|
+
export const _staticBackground = (logoOpacity, backgroundColor) => [
|
6
|
+
logoOpacity,
|
7
|
+
StyleSheet.absoluteFill,
|
8
|
+
{ backgroundColor: backgroundColor || null },
|
9
|
+
]
|
10
|
+
|
11
|
+
export const _dynamicImageBackground = (
|
12
|
+
imageScale,
|
13
|
+
logoOpacity,
|
14
|
+
backgroundColor
|
15
|
+
) => [
|
16
|
+
imageScale,
|
17
|
+
logoOpacity,
|
18
|
+
{
|
19
|
+
...StyleSheet.absoluteFill,
|
20
|
+
width,
|
21
|
+
height,
|
22
|
+
top: 0,
|
23
|
+
alignItems: "center",
|
24
|
+
justifyContent: "center",
|
25
|
+
tintColor: backgroundColor || null,
|
26
|
+
},
|
27
|
+
]
|
28
|
+
|
29
|
+
export const _dynamicLogoStyle = (
|
30
|
+
logoScale,
|
31
|
+
logoOpacity,
|
32
|
+
logoWidth,
|
33
|
+
logoHeight
|
34
|
+
) => [
|
35
|
+
logoScale,
|
36
|
+
logoOpacity,
|
37
|
+
{
|
38
|
+
width: logoWidth || 150,
|
39
|
+
height: logoHeight || 150,
|
40
|
+
},
|
41
|
+
]
|
42
|
+
|
43
|
+
export const _dynamicCustomComponentStyle = (
|
44
|
+
logoScale,
|
45
|
+
logoOpacity,
|
46
|
+
logoWidth,
|
47
|
+
logoHeight
|
48
|
+
) => [
|
49
|
+
logoScale,
|
50
|
+
logoOpacity,
|
51
|
+
{
|
52
|
+
width: logoWidth || 150,
|
53
|
+
height: logoHeight || 150,
|
54
|
+
alignItems: "center",
|
55
|
+
justifyContent: "center",
|
56
|
+
},
|
57
|
+
]
|
58
|
+
|
59
|
+
export default {
|
60
|
+
container: {
|
61
|
+
flex: 1,
|
62
|
+
},
|
63
|
+
containerGlue: {
|
64
|
+
flex: 1,
|
65
|
+
alignContent: "center",
|
66
|
+
justifyContent: "center",
|
67
|
+
},
|
68
|
+
flex: {
|
69
|
+
flex: 1,
|
70
|
+
},
|
71
|
+
logoStyle: {
|
72
|
+
alignItems: "center",
|
73
|
+
justifyContent: "center",
|
74
|
+
},
|
75
|
+
}
|
@@ -1,98 +1,138 @@
|
|
1
|
+
//@see : https://www.npmjs.com/package/react-native-animated-splash-screen
|
2
|
+
|
1
3
|
/* @flow */
|
2
|
-
/*** fork of https://www.npmjs.com/package/react-native-animated-splash-screen */
|
3
4
|
import PropTypes from "prop-types"
|
4
|
-
import React from "
|
5
|
-
import {Animated, StyleSheet } from "react-native"
|
6
|
-
import View from "$ecomponents/View";
|
7
|
-
import {isNativeMobile} from "$cplatform";
|
8
|
-
import {defaultDecimal} from "$cutils";
|
9
|
-
import {LogoProgress} from "$ecomponents/Logo";
|
10
|
-
import { Portal } from "react-native-paper";
|
11
|
-
import {defaultStr} from "$cutils";
|
5
|
+
import * as React from "react"
|
6
|
+
import { Animated, StatusBar, StyleSheet } from "react-native"
|
12
7
|
import styles, {
|
13
|
-
_solidBackground,
|
14
8
|
_staticBackground,
|
15
9
|
_dynamicLogoStyle,
|
16
10
|
_dynamicCustomComponentStyle,
|
17
11
|
_dynamicImageBackground,
|
18
12
|
_dynamicBackgroundOpacity,
|
19
|
-
} from "./
|
20
|
-
import
|
13
|
+
} from "./AnimatedSplash.style";
|
14
|
+
import View from "$ecomponents/View";
|
15
|
+
import {isNativeMobile} from "$cplatform";
|
16
|
+
import {defaultDecimal} from "$cutils";
|
17
|
+
import {LogoProgress} from "$ecomponents/Logo";
|
18
|
+
import { Portal } from "react-native-paper";
|
19
|
+
import {defaultStr} from "$cutils";
|
21
20
|
|
22
|
-
|
23
|
-
|
24
|
-
|
21
|
+
class AnimatedSplash extends React.Component {
|
22
|
+
static defaultProps = {
|
23
|
+
isLoaded: false,
|
24
|
+
}
|
25
|
+
|
26
|
+
state = {
|
25
27
|
animationDone: false,
|
26
28
|
loadingProgress: new Animated.Value(0),
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
29
|
+
showStatusBar: true,
|
30
|
+
}
|
31
|
+
|
32
|
+
componentDidUpdate(prevProps) {
|
33
|
+
const { isLoaded , duration, delay } = this.props
|
34
|
+
const { loadingProgress } = this.state
|
35
|
+
if (isLoaded && !prevProps.isLoaded) {
|
33
36
|
Animated.timing(loadingProgress, {
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
37
|
+
toValue: 100,
|
38
|
+
duration: duration || 1000,
|
39
|
+
delay: delay || 0,
|
40
|
+
useNativeDriver: isNativeMobile(),
|
38
41
|
}).start(() => {
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
})
|
42
|
+
this.setState({
|
43
|
+
animationDone: true,
|
44
|
+
})
|
43
45
|
})
|
44
|
-
} else if(isLoaded){
|
45
|
-
clearTimeout(timerRef.current);
|
46
|
-
timerRef.current = setTimeout(()=>{
|
47
|
-
if(isLoaded && !animationDone){
|
48
|
-
setState({...state,animationDone:true});
|
49
|
-
}
|
50
|
-
clearTimeout(timerRef.current);
|
51
|
-
},delay|2000);
|
52
46
|
}
|
53
|
-
},[isLoaded,prevIsLoaded,animationDone]);
|
54
|
-
testID = defaultStr(testID,"RN_SplashscreenComponent")
|
55
|
-
logoWidth = defaultDecimal(logoWidth,150);
|
56
|
-
logoHeight = defaultDecimal(logoHeight,250);
|
57
|
-
const Component = useAppComponent("SplashScreen");
|
58
|
-
|
59
|
-
const logoScale = {
|
60
|
-
transform: [
|
61
|
-
{
|
62
|
-
scale: loadingProgress.interpolate({
|
63
|
-
inputRange: [0, 10, 100],
|
64
|
-
outputRange: [1, 0.8, 10],
|
65
|
-
}),
|
66
|
-
},
|
67
|
-
],
|
68
47
|
}
|
69
48
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
}
|
77
|
-
if(isLoaded && animationDone){
|
78
|
-
return React.isValidElement(children)?children:null;
|
49
|
+
renderChildren() {
|
50
|
+
const { children, preload, isLoaded } = this.props
|
51
|
+
if (isLoaded) {
|
52
|
+
return children
|
53
|
+
}
|
54
|
+
return null
|
79
55
|
}
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
56
|
+
|
57
|
+
render() {
|
58
|
+
const { loadingProgress, animationDone } = this.state
|
59
|
+
const {
|
60
|
+
logoImage,
|
61
|
+
logoWidth,
|
62
|
+
logoHeight,
|
63
|
+
backgroundColor,
|
64
|
+
customComponent,
|
65
|
+
disableAppScale,
|
66
|
+
} = this.props
|
67
|
+
|
68
|
+
const opacityClearToVisible = {
|
69
|
+
opacity: loadingProgress.interpolate({
|
70
|
+
inputRange: [0, 15, 30],
|
71
|
+
outputRange: [0, 0, 1],
|
72
|
+
extrapolate: "clamp",
|
73
|
+
}),
|
74
|
+
}
|
75
|
+
|
76
|
+
const imageScale = {
|
77
|
+
transform: [
|
78
|
+
{
|
79
|
+
scale: loadingProgress.interpolate({
|
80
|
+
inputRange: [0, 10, 100],
|
81
|
+
outputRange: [1, 1, 65],
|
82
|
+
}),
|
83
|
+
},
|
84
|
+
],
|
85
|
+
}
|
86
|
+
|
87
|
+
const logoScale = {
|
88
|
+
transform: [
|
89
|
+
{
|
90
|
+
scale: loadingProgress.interpolate({
|
91
|
+
inputRange: [0, 10, 100],
|
92
|
+
outputRange: [1, 0.8, 10],
|
93
|
+
}),
|
94
|
+
},
|
95
|
+
],
|
96
|
+
}
|
97
|
+
|
98
|
+
const logoOpacity = {
|
99
|
+
opacity: loadingProgress.interpolate({
|
100
|
+
inputRange: [0, 20, 100],
|
101
|
+
outputRange: [1, 0, 0],
|
102
|
+
extrapolate: "clamp",
|
103
|
+
}),
|
104
|
+
}
|
105
|
+
|
106
|
+
const appScale = {
|
107
|
+
transform: [
|
108
|
+
{
|
109
|
+
scale: loadingProgress.interpolate({
|
110
|
+
inputRange: [0, 7, 100],
|
111
|
+
outputRange: [1.1, 1.05, 1],
|
112
|
+
}),
|
113
|
+
},
|
114
|
+
],
|
115
|
+
}
|
116
|
+
const testID = defaultStr(testID,"RN_MainSplashScreen");
|
117
|
+
const {Component} = this.props;
|
118
|
+
return (
|
119
|
+
<View testID={testID} style={[styles.container]}>
|
120
|
+
{!animationDone && <View style={StyleSheet.absoluteFill} testID={`${testID}_AbsoluteFill`} />}
|
121
|
+
<View style={styles.containerGlue} testID={`${testID}_ContainerGlue`}>
|
122
|
+
{!animationDone && (
|
123
|
+
<Animated.View
|
124
|
+
testID={`${testID}_StaticBackground`}
|
125
|
+
style={_staticBackground(logoOpacity, backgroundColor)}
|
126
|
+
/>
|
127
|
+
)}
|
128
|
+
<Animated.View testID={`${testID}_ChildrenContainer`} style={[!disableAppScale && appScale, opacityClearToVisible, styles.flex]}>
|
129
|
+
{this.renderChildren()}
|
130
|
+
</Animated.View>
|
131
|
+
{!animationDone && (React.isComponent(Component)? <Component testID={testID+"_CustomSplashComponent"}/> :
|
132
|
+
<View testID={`${testID}_AbsoluteFillContainer`} style={[StyleSheet.absoluteFill, styles.logoStyle]}>
|
133
|
+
{<View testID={testID+"_LogoContainer"} style={[StyleSheet.absoluteFill,{backgroundColor}, styles.logoStyle]}>
|
94
134
|
<Animated.View
|
95
|
-
testID={testID+"
|
135
|
+
testID={testID+"_LogoProgressContainer"}
|
96
136
|
style={_dynamicCustomComponentStyle(
|
97
137
|
logoScale,
|
98
138
|
logoOpacity,
|
@@ -101,32 +141,27 @@ const SplashScreenComponent = ({isLoaded,children , duration, delay,logoWidth,lo
|
|
101
141
|
)}>
|
102
142
|
{<LogoProgress />}
|
103
143
|
</Animated.View>
|
104
|
-
</View>
|
105
|
-
)}
|
144
|
+
</View>}
|
106
145
|
</View>
|
107
|
-
|
108
|
-
|
109
|
-
|
146
|
+
)}
|
147
|
+
</View>
|
148
|
+
</View>
|
149
|
+
)
|
150
|
+
}
|
110
151
|
}
|
111
152
|
|
112
|
-
|
113
|
-
SplashScreenComponent.propTypes = {
|
153
|
+
AnimatedSplash.propTypes = {
|
114
154
|
preload: PropTypes.bool,
|
115
155
|
logoWidth: PropTypes.number,
|
116
156
|
children: PropTypes.element,
|
117
157
|
logoHeight: PropTypes.number,
|
118
158
|
backgroundColor: PropTypes.string,
|
119
159
|
isLoaded: PropTypes.bool.isRequired,
|
120
|
-
|
121
|
-
|
122
|
-
PropTypes.string,
|
123
|
-
PropTypes.number,
|
124
|
-
PropTypes.object,
|
125
|
-
]),
|
160
|
+
translucent: PropTypes.bool,
|
161
|
+
customComponent: PropTypes.element,
|
126
162
|
disableAppScale: PropTypes.bool,
|
127
163
|
duration: PropTypes.number,
|
128
164
|
delay: PropTypes.number,
|
129
165
|
}
|
130
166
|
|
131
|
-
|
132
|
-
export default SplashScreenComponent;
|
167
|
+
export default AnimatedSplash
|
@@ -0,0 +1,132 @@
|
|
1
|
+
/* @flow */
|
2
|
+
/*** fork of https://www.npmjs.com/package/react-native-animated-splash-screen */
|
3
|
+
import PropTypes from "prop-types"
|
4
|
+
import React from "$react"
|
5
|
+
import {Animated, StyleSheet } from "react-native";
|
6
|
+
import View from "$ecomponents/View";
|
7
|
+
import {isNativeMobile} from "$cplatform";
|
8
|
+
import {defaultDecimal} from "$cutils";
|
9
|
+
import {LogoProgress} from "$ecomponents/Logo";
|
10
|
+
import { Portal } from "react-native-paper";
|
11
|
+
import {defaultStr} from "$cutils";
|
12
|
+
import styles, {
|
13
|
+
_solidBackground,
|
14
|
+
_staticBackground,
|
15
|
+
_dynamicLogoStyle,
|
16
|
+
_dynamicCustomComponentStyle,
|
17
|
+
_dynamicImageBackground,
|
18
|
+
_dynamicBackgroundOpacity,
|
19
|
+
} from "./styles"
|
20
|
+
import {useAppComponent} from "$econtext/hooks";
|
21
|
+
|
22
|
+
const SplashScreenComponent = ({isLoaded,children , duration, delay,logoWidth,logoHeight,backgroundColor,imageBackgroundSource,imageBackgroundResizeMode,
|
23
|
+
testID})=>{
|
24
|
+
const [state,setState] = React.useState({
|
25
|
+
animationDone: false,
|
26
|
+
loadingProgress: new Animated.Value(0),
|
27
|
+
});
|
28
|
+
const { loadingProgress, animationDone} = state;
|
29
|
+
const prevIsLoaded = React.usePrevious(isLoaded);
|
30
|
+
const timerRef = React.useRef(null);
|
31
|
+
React.useEffect(()=>{
|
32
|
+
if(isLoaded && !prevIsLoaded){
|
33
|
+
Animated.timing(loadingProgress, {
|
34
|
+
toValue: 100,
|
35
|
+
duration: duration || 100,
|
36
|
+
delay: delay || 0,
|
37
|
+
useNativeDriver: isNativeMobile(),
|
38
|
+
}).start(() => {
|
39
|
+
setState({
|
40
|
+
...state,
|
41
|
+
animationDone:true,
|
42
|
+
})
|
43
|
+
})
|
44
|
+
} else if(isLoaded){
|
45
|
+
clearTimeout(timerRef.current);
|
46
|
+
timerRef.current = setTimeout(()=>{
|
47
|
+
if(isLoaded && !animationDone){
|
48
|
+
setState({...state,animationDone:true});
|
49
|
+
}
|
50
|
+
clearTimeout(timerRef.current);
|
51
|
+
},delay|2000);
|
52
|
+
}
|
53
|
+
},[isLoaded,prevIsLoaded,animationDone]);
|
54
|
+
testID = defaultStr(testID,"RN_SplashscreenComponent")
|
55
|
+
logoWidth = defaultDecimal(logoWidth,150);
|
56
|
+
logoHeight = defaultDecimal(logoHeight,250);
|
57
|
+
const Component = useAppComponent("SplashScreen");
|
58
|
+
|
59
|
+
const logoScale = {
|
60
|
+
transform: [
|
61
|
+
{
|
62
|
+
scale: loadingProgress.interpolate({
|
63
|
+
inputRange: [0, 10, 100],
|
64
|
+
outputRange: [1, 0.8, 10],
|
65
|
+
}),
|
66
|
+
},
|
67
|
+
],
|
68
|
+
}
|
69
|
+
|
70
|
+
const logoOpacity = {
|
71
|
+
opacity: loadingProgress.interpolate({
|
72
|
+
inputRange: [0, 20, 100],
|
73
|
+
outputRange: [1, 0, 0],
|
74
|
+
extrapolate: "clamp",
|
75
|
+
}),
|
76
|
+
}
|
77
|
+
if(isLoaded && animationDone){
|
78
|
+
return React.isValidElement(children)?children:null;
|
79
|
+
}
|
80
|
+
return <>
|
81
|
+
{!animationDone || !isLoaded ? <Portal>
|
82
|
+
<View style={[styles.container,{backgroundColor}]} testID={testID} id={testID}>
|
83
|
+
{<View style={[StyleSheet.absoluteFill,{backgroundColor}]} testID={testID+"_Animation"}/>}
|
84
|
+
<View style={styles.containerGlue} testID={testID+"_ContainerGlue"}>
|
85
|
+
{(
|
86
|
+
<Animated.View
|
87
|
+
style={_staticBackground(logoOpacity, backgroundColor)}
|
88
|
+
testID={testID+"_AnimationDone"}
|
89
|
+
/>
|
90
|
+
)}
|
91
|
+
{(
|
92
|
+
React.isComponent(Component)? <Component testID={testID+"_CustomSplashComponent"}/> :
|
93
|
+
<View testID={testID+"_LogoContainer"} style={[StyleSheet.absoluteFill,{backgroundColor}, styles.logoStyle]}>
|
94
|
+
<Animated.View
|
95
|
+
testID={testID+"_Logo"}
|
96
|
+
style={_dynamicCustomComponentStyle(
|
97
|
+
logoScale,
|
98
|
+
logoOpacity,
|
99
|
+
logoWidth,
|
100
|
+
logoHeight
|
101
|
+
)}>
|
102
|
+
{<LogoProgress />}
|
103
|
+
</Animated.View>
|
104
|
+
</View>
|
105
|
+
)}
|
106
|
+
</View>
|
107
|
+
</View>
|
108
|
+
</Portal> : null}
|
109
|
+
</>
|
110
|
+
}
|
111
|
+
|
112
|
+
|
113
|
+
SplashScreenComponent.propTypes = {
|
114
|
+
preload: PropTypes.bool,
|
115
|
+
logoWidth: PropTypes.number,
|
116
|
+
children: PropTypes.element,
|
117
|
+
logoHeight: PropTypes.number,
|
118
|
+
backgroundColor: PropTypes.string,
|
119
|
+
isLoaded: PropTypes.bool.isRequired,
|
120
|
+
disableBackgroundImage: PropTypes.bool,
|
121
|
+
logoImage: PropTypes.oneOfType([
|
122
|
+
PropTypes.string,
|
123
|
+
PropTypes.number,
|
124
|
+
PropTypes.object,
|
125
|
+
]),
|
126
|
+
disableAppScale: PropTypes.bool,
|
127
|
+
duration: PropTypes.number,
|
128
|
+
delay: PropTypes.number,
|
129
|
+
}
|
130
|
+
|
131
|
+
SplashScreenComponent.displayName = "SplashScreenComponent";
|
132
|
+
export default SplashScreenComponent;
|