fix(app-expo): use brand splash icon on logout replay overlay
Replace Expo template logo and blue gradient with splash-icon.png and Co-authored-by: Cursor <cursoragent@cursor.com> #E6F4FE so post-logout splash matches the native cold-start screen.
This commit is contained in:
@@ -1,6 +0,0 @@
|
||||
.expoLogoBackground {
|
||||
background-image: linear-gradient(180deg, #3c9ffe, #0274df);
|
||||
border-radius: 40px;
|
||||
width: 128px;
|
||||
height: 128px;
|
||||
}
|
||||
@@ -8,9 +8,11 @@ import { completeSplashReplay } from '@/core/splash-replay';
|
||||
|
||||
const INITIAL_SCALE_FACTOR = Dimensions.get('screen').height / 90;
|
||||
const DURATION = 600;
|
||||
/** Matches expo-splash-screen `imageWidth` in app.config.ts */
|
||||
const SPLASH_LOGO_SIZE = 200;
|
||||
|
||||
/** Brand gate background (matches native splash / overlay). */
|
||||
export const BRAND_BOOTSTRAP_BG = '#208AEF';
|
||||
/** Brand gate background — matches native splash / adaptiveIcon (#E6F4FE). */
|
||||
export const BRAND_BOOTSTRAP_BG = '#E6F4FE';
|
||||
|
||||
export function AnimatedSplashOverlay() {
|
||||
const [visible, setVisible] = useState(true);
|
||||
@@ -61,100 +63,41 @@ export function BrandBootstrapLoading() {
|
||||
);
|
||||
}
|
||||
|
||||
const keyframe = new Keyframe({
|
||||
0: {
|
||||
transform: [{ scale: INITIAL_SCALE_FACTOR }],
|
||||
},
|
||||
100: {
|
||||
transform: [{ scale: 1 }],
|
||||
easing: Easing.elastic(0.7),
|
||||
},
|
||||
});
|
||||
|
||||
const logoKeyframe = new Keyframe({
|
||||
0: {
|
||||
transform: [{ scale: 1.3 }],
|
||||
transform: [{ scale: 0.92 }],
|
||||
opacity: 0,
|
||||
},
|
||||
40: {
|
||||
transform: [{ scale: 1.3 }],
|
||||
opacity: 0,
|
||||
easing: Easing.elastic(0.7),
|
||||
},
|
||||
100: {
|
||||
opacity: 1,
|
||||
transform: [{ scale: 1 }],
|
||||
easing: Easing.elastic(0.7),
|
||||
},
|
||||
});
|
||||
|
||||
const glowKeyframe = new Keyframe({
|
||||
0: {
|
||||
transform: [{ rotateZ: '0deg' }],
|
||||
},
|
||||
100: {
|
||||
transform: [{ rotateZ: '7200deg' }],
|
||||
easing: Easing.out(Easing.cubic),
|
||||
},
|
||||
});
|
||||
|
||||
export function AnimatedIcon() {
|
||||
return (
|
||||
<View style={styles.iconContainer}>
|
||||
<Animated.View
|
||||
entering={glowKeyframe.duration(60 * 1000 * 4)}
|
||||
style={styles.glow}
|
||||
>
|
||||
<Image
|
||||
style={styles.glow}
|
||||
source={require('@/assets/images/logo-glow.png')}
|
||||
/>
|
||||
</Animated.View>
|
||||
|
||||
<Animated.View
|
||||
entering={keyframe.duration(DURATION)}
|
||||
style={styles.background}
|
||||
<Animated.View
|
||||
style={styles.logoContainer}
|
||||
entering={logoKeyframe.duration(DURATION)}
|
||||
>
|
||||
<Image
|
||||
style={styles.splashLogo}
|
||||
source={require('@/assets/images/splash-icon.png')}
|
||||
contentFit="contain"
|
||||
/>
|
||||
<Animated.View
|
||||
style={styles.imageContainer}
|
||||
entering={logoKeyframe.duration(DURATION)}
|
||||
>
|
||||
<Image
|
||||
style={styles.image}
|
||||
source={require('@/assets/images/expo-logo.png')}
|
||||
/>
|
||||
</Animated.View>
|
||||
</View>
|
||||
</Animated.View>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
imageContainer: {
|
||||
logoContainer: {
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
glow: {
|
||||
width: 201,
|
||||
height: 201,
|
||||
position: 'absolute',
|
||||
},
|
||||
iconContainer: {
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
width: 128,
|
||||
height: 128,
|
||||
zIndex: 100,
|
||||
},
|
||||
image: {
|
||||
position: 'absolute',
|
||||
width: 76,
|
||||
height: 71,
|
||||
},
|
||||
background: {
|
||||
borderRadius: 40,
|
||||
experimental_backgroundImage: `linear-gradient(180deg, #3C9FFE, #0274DF)`,
|
||||
width: 128,
|
||||
height: 128,
|
||||
position: 'absolute',
|
||||
splashLogo: {
|
||||
width: SPLASH_LOGO_SIZE,
|
||||
height: SPLASH_LOGO_SIZE,
|
||||
},
|
||||
backgroundSolidColor: {
|
||||
...StyleSheet.absoluteFillObject,
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import { Image } from 'expo-image';
|
||||
import { StyleSheet, View } from 'react-native';
|
||||
import Animated, { Keyframe, Easing } from 'react-native-reanimated';
|
||||
import Animated, { Easing, Keyframe } from 'react-native-reanimated';
|
||||
|
||||
import classes from './animated-icon.module.css';
|
||||
/** Matches expo-splash-screen `imageWidth` in app.config.ts */
|
||||
const SPLASH_LOGO_SIZE = 200;
|
||||
const DURATION = 300;
|
||||
|
||||
/** Brand gate background (matches native splash / overlay). */
|
||||
export const BRAND_BOOTSTRAP_BG = '#208AEF';
|
||||
/** Brand gate background — matches native splash / adaptiveIcon (#E6F4FE). */
|
||||
export const BRAND_BOOTSTRAP_BG = '#E6F4FE';
|
||||
|
||||
export function AnimatedSplashOverlay() {
|
||||
return null;
|
||||
@@ -21,81 +22,30 @@ export function BrandBootstrapLoading() {
|
||||
);
|
||||
}
|
||||
|
||||
const keyframe = new Keyframe({
|
||||
0: {
|
||||
transform: [{ scale: 0 }],
|
||||
},
|
||||
60: {
|
||||
transform: [{ scale: 1.2 }],
|
||||
easing: Easing.elastic(1.2),
|
||||
},
|
||||
100: {
|
||||
transform: [{ scale: 1 }],
|
||||
easing: Easing.elastic(1.2),
|
||||
},
|
||||
});
|
||||
|
||||
const logoKeyframe = new Keyframe({
|
||||
0: {
|
||||
transform: [{ scale: 0.92 }],
|
||||
opacity: 0,
|
||||
},
|
||||
60: {
|
||||
transform: [{ scale: 1.2 }],
|
||||
opacity: 0,
|
||||
easing: Easing.elastic(1.2),
|
||||
},
|
||||
100: {
|
||||
transform: [{ scale: 1 }],
|
||||
opacity: 1,
|
||||
easing: Easing.elastic(1.2),
|
||||
},
|
||||
});
|
||||
|
||||
const glowKeyframe = new Keyframe({
|
||||
0: {
|
||||
transform: [{ rotateZ: '-180deg' }, { scale: 0.8 }],
|
||||
opacity: 0,
|
||||
},
|
||||
[DURATION / 1000]: {
|
||||
transform: [{ rotateZ: '0deg' }, { scale: 1 }],
|
||||
opacity: 1,
|
||||
easing: Easing.elastic(0.7),
|
||||
},
|
||||
100: {
|
||||
transform: [{ rotateZ: '7200deg' }],
|
||||
easing: Easing.out(Easing.cubic),
|
||||
},
|
||||
});
|
||||
|
||||
export function AnimatedIcon() {
|
||||
return (
|
||||
<View style={styles.iconContainer}>
|
||||
<Animated.View
|
||||
entering={glowKeyframe.duration(60 * 1000 * 4)}
|
||||
style={styles.glow}
|
||||
>
|
||||
<Image
|
||||
style={styles.glow}
|
||||
source={require('@/assets/images/logo-glow.png')}
|
||||
/>
|
||||
</Animated.View>
|
||||
|
||||
<Animated.View
|
||||
style={styles.background}
|
||||
entering={keyframe.duration(DURATION)}
|
||||
>
|
||||
<div className={classes.expoLogoBackground} />
|
||||
</Animated.View>
|
||||
|
||||
<Animated.View
|
||||
style={styles.imageContainer}
|
||||
entering={logoKeyframe.duration(DURATION)}
|
||||
>
|
||||
<Image
|
||||
style={styles.image}
|
||||
source={require('@/assets/images/expo-logo.png')}
|
||||
/>
|
||||
</Animated.View>
|
||||
</View>
|
||||
<Animated.View
|
||||
style={styles.logoContainer}
|
||||
entering={logoKeyframe.duration(DURATION)}
|
||||
>
|
||||
<Image
|
||||
style={styles.splashLogo}
|
||||
source={require('@/assets/images/splash-icon.png')}
|
||||
contentFit="contain"
|
||||
/>
|
||||
</Animated.View>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -106,36 +56,12 @@ const styles = StyleSheet.create({
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
container: {
|
||||
alignItems: 'center',
|
||||
width: '100%',
|
||||
zIndex: 1000,
|
||||
position: 'absolute',
|
||||
top: 128 / 2 + 138,
|
||||
},
|
||||
imageContainer: {
|
||||
logoContainer: {
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
glow: {
|
||||
width: 201,
|
||||
height: 201,
|
||||
position: 'absolute',
|
||||
},
|
||||
iconContainer: {
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
width: 128,
|
||||
height: 128,
|
||||
},
|
||||
image: {
|
||||
position: 'absolute',
|
||||
width: 76,
|
||||
height: 71,
|
||||
},
|
||||
background: {
|
||||
width: 128,
|
||||
height: 128,
|
||||
position: 'absolute',
|
||||
splashLogo: {
|
||||
width: SPLASH_LOGO_SIZE,
|
||||
height: SPLASH_LOGO_SIZE,
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user